継続行とは

列7(標識列)に - が記述されている行は 継続行(Continuation Line) と呼ばれ、 直前の行の続きとして結合される。継続行自体の列7は結合後に不要になる。

COBOL — 継続行の例(Step1後のイメージ)
* 通常の命令の継続
     MOVE 'THIS IS A VERY LONG STRING THAT NEEDS TO BE SPLIT ACRO
-    SS MULTIPLE LINES' TO WS-MSG.

* 数値・識別子の継続(スペースで自然につながる)
     MOVE WS-VERY-LONG-WORKING-STORAGE-VARIABLE-NAME
-        TO WS-ANOTHER-LONG-VARIABLE.

文字列リテラル継続の引用符ルール

通常の命令継続(識別子・数値など)はそのまま前行の末尾に空白を挟んで結合すればよい。 しかし 文字列リテラル の継続には COBOL 独自のルールがある。

  • 前行の末尾には開き引用符が残るが、リテラルは 途中で切れている
  • 継続行の先頭(Area B の先頭 = インデックス5以降)には 閉じ引用符が再度書かれる
  • 結合時はこの「前行の末尾引用符」と「継続行の先頭引用符」を除去してつなぎ合わせる
COBOL — 文字列リテラル継続の例
* 元ソース(シーケンス番号付き)
000100     MOVE 'HELLO WOR
000200-    LD' TO WS-MSG.

* Step1後のイメージ
     MOVE 'HELLO WOR       ← 末尾は引用符なしで終わっている
-    LD' TO WS-MSG.        ← 継続行の先頭に引用符 ' がある

* 正しい結合結果
     MOVE 'HELLO WORLD' TO WS-MSG.

💡 引用符の種類

COBOLでは '(シングルクォート)と "(ダブルクォート)の両方が文字列リテラルの区切りとして使われる。 実装では両方に対応する必要がある。

実装 — join_continuation_lines

Python — 継続行結合
def join_continuation_lines(lines: list[str]) -> list[str]:
    """
    標識列が '-' の継続行を前行に結合する。
    Step1〜3(シーケンス番号除去・コメント削除・識別領域除去)適用後に呼ぶ。

    継続行の先頭(インデックス0)は標識 '-'。
    Area B の開始はインデックス5(元の列12、Step1で6文字削除後は列7基準のインデックス5)。

    文字列リテラル継続の場合:
      前行末尾の引用符を除去し、継続行先頭の引用符も除去してから結合する。
    通常継続の場合:
      前行末尾の空白を除去し、継続行の命令部分(インデックス1以降をlstrip)をスペースで結合する。
    """
    result = []
    for line in lines:
        if not line:
            continue

        indicator = line[0]  # Step1後は先頭文字が標識列

        if indicator == '-':
            # 継続行: 前行に結合する
            if not result:
                # 最初の行が継続行の場合は単独行として扱う(通常はありえない)
                continuation_body = line[1:].lstrip()
                result.append(continuation_body)
                continue

            prev = result[-1]
            # Area B の先頭(インデックス1からlstrip)
            continuation_body = line[1:].lstrip()

            # 文字列リテラル継続の判定
            # 継続行の先頭文字が引用符(' または ")なら文字列リテラルの継続
            if continuation_body and continuation_body[0] in ("'", '"'):
                quote_char = continuation_body[0]
                # 前行末尾の引用符(同種)を除去
                if prev.endswith(quote_char):
                    prev = prev[:-1]
                # 継続行の先頭引用符を除去
                continuation_body = continuation_body[1:]
                # 空白なしで結合(文字列は途切れなくつながる)
                result[-1] = prev + continuation_body
            else:
                # 通常継続: スペース1文字で結合
                result[-1] = prev.rstrip() + ' ' + continuation_body
        else:
            result.append(line)

    return result

動作確認

Python — 動作確認
lines = [
    "     MOVE 'HELLO WOR",          # 文字列リテラル継続(前行)
    "-    LD' TO WS-MSG.",           # 文字列リテラル継続(継続行)
    "     MOVE WS-LONG-VAR",         # 通常継続(前行)
    "-        TO WS-DEST.",          # 通常継続(継続行)
    "     DISPLAY 'SIMPLE'.",        # 継続なし
]

result = join_continuation_lines(lines)
for line in result:
    print(repr(line))
実行結果
"     MOVE 'HELLO WORLD' TO WS-MSG."
"     MOVE WS-LONG-VAR TO WS-DEST."
"     DISPLAY 'SIMPLE'."

文字列リテラルが正しく 'HELLO WORLD' としてつながり、通常継続もスペース区切りで結合されていることが確認できる。

⚠️ 3行以上にまたがる継続

継続行が連続して3行以上になるケースも存在する(非常に長い文字列定数など)。 本実装では継続行を検出するたびに result[-1](最後の確定行)に結合していくため、 何行続いても正しく処理できる。

次の章では…

PART 05 ではインデントや余分なスペースを除去する スペースの正規化 を実装する。 文字列リテラル内のスペースを誤って変更しないための保護処理が重要なポイントだ。

→ PART 05 — スペースの正規化へ