読者です 読者をやめる 読者になる 読者になる

Cobolでピリオドを忘れると何が起きるのか

参考文献はこちら

定本 入門COBOL

定本 入門COBOL

言語仕様の確認

まず、Cobolのif文は次のようになっている。

ここには説明が無いが、書き方2の場合はif文の後にピリオドを付けて「完結文」として、そこで文を終わらせることでif文が終わる。またこの規則だけを見ると、文が1個だけしか書けないように見えるが、実際にはdisplayなどをいくつ並べても「文」として扱われる。
注意書きがあるようにend-ifで終わらせるのが現代的な書き方である。またここでnext sentenceとするのは「if文の特別な書き方」であるが、やはり現代的な書き方であるcontinueとした場合は「continue文」という、文の一種で他でも使われる。
というわけで、こちら( http://www.kt.rim.or.jp/~kbk/zakkicho/15/zakkicho1506b.html#D20150615-3 )のリンク先にある「THEN、ELSE、 END-IFなどが省略可能」というのはほとんど変で、

  • ELSE節を省略可能
  • 昔は、END-IFではなくピリオドで終了するという記法だった

ということになる。
続いてピリオドが絡みそうなあたりの説明であるが、

ここで、「入れ子の場合にも欠陥がある」とあるが、どういうことかというと、ピリオドで「ネストしているifが全部終わる」という仕様のために、ネストの内側のifを終わってネストの外側のifに戻る、ということができない、ということである。
Cobolが世界で最初期に設計された高水準プログラミング言語のひとつであるということを考えれば、ifのネストといったようなことを考えていない仕様だったことは自然だろう。

実例

この「ピリオドで、ネストしたif文が全部終わる」という仕様により、「ピリオドを忘れると、コンパイルエラーにはならずにバグになってしまう」という例を示す。
こちら http://www.magata.net/memo/index.php?OpenCOBOL を参考にしたhello worldプログラムを改造した、次のようなサンプルを実行すると、

      * Sample COBOL program

       identification division.

       program-id. sample.

       procedure division.

       if 0 is not zero
          then display "foo".

       display "bar"

       if 0 is zero
          then display "baz".

       display "hoge"

       stop run.

次のようになる。

$ cobc sample.cob
$ cobcrun sample
bar
baz
hoge

ここで、1個目のifに付いているピリオドを取ると、

      * Sample COBOL program

       identification division.

       program-id. sample.

       procedure division.

       if 0 is not zero
          then display "foo"

       display "bar"

       if 0 is zero
          then display "baz".

       display "hoge"

       stop run.
$ cobc sample.cob
$ cobcrun sample
hoge

2個目のifまでの全体が、1個目のifのthen節の中に入ってしまって、「hoge」しかプリントされなくなる。なお、さらに2個目のピリオドが無くても「ifが終わっていない」というようなエラーにもならない。
そういったわけで「古いCobolでピリオドを忘れることの危険」については以上で述べた通りであるが、「ときどきの雑記帖」が気になるとしているように、字下げのルール化ではこのミスのチェックは難しいし(むしろC言語の if (); などで悪名高い「字下げに騙されるパターン」である。一応、ルール化により「意図が見かけで表現されるので、それが実際の動作と一致していない」と気付けるかもしれない、という可能性はある)、「ミサイル発射実験の失敗」というのもおそらく9割5分、マリナーとマーキュリーの2件の無関係な事故がたいてい混同されているFORTRANのそれの混同ではなかろうかと思う。