BNF での構文
int_lit ::= 0 | 1 | 2 | 3 | ... (literal; 自然数の定数) exp ::= int_lit | Plus(exp,exp) | Times(exp,exp) (expression; 式)
OCaml でのデータ型の定義
type exp = IntLit of int (* リテラル *) | Plus of exp * exp (* 足し算 *) | Times of exp * exp (* かけ算 *)type というキーワードを使って、新しいデータ型 exp を定義した。 このデータ型が本質的に BNF定義された exp と同じものを表すことが 理解できよう。なお、exp, int が小文字で始まっていて、 IntLit, Plus, Times が大文字で始まっているのは OCaml言語での規約 による。(大文字で始まる単語と、小文字で始まる単語は使える場所が明確に 異なるので、それを間違えると、意味がよくわからないエラーとなる。)
構文解析アルゴリズムは、古くからよく研究されており、 C言語に対しては、言語の文法規則等を記述するだけで、 その文法に特化した構文解析器を自動生成してくれる yacc/lex という夢のようなツールがある。 OCaml でも同様のことをしてくれる ocamlyacc と ocamllex という ツールがある。 これらを使うと、 我々は、構文解析器をどう効率よく書くか、といったことで悩まなくて済む。 実際、プログラム言語の処理系作成の授業の多くでは、yacc/lex (あるいは OCaml 版の yacc/lex)を使って 構文解析を行っているようである。
ただし、このためには文法の記述法(一種の言語)を学習する必要があり、 今まさに OCaml という新しい言語を覚えようとしている受講生には負担が きつい。
そこで本実験では、 当初は構文解析器(パーサ)を作ったり使ったりするのはやめ, 「構文解析した結果のプログラム(内部データ構造で記述されたプログラム)」 を直接人間が入力することにする。 これはかなり無謀な案に思えるかもしれないが,この範囲でも結構いろいろな ものが書けるものである. このような形で入力を記述していると、大きなプログラム例を入力するときは かなり大変になるので、いずれは、構文解析器を使うことにする。
結論として,本実験では,当面、
exp型(を拡張したもの)をもつデータ(プログラム)を入力し, そのプログラムを実行する処理系を作成する.
後に、ocamllex/ocamlyacc を使った構文解析の世界に、 ちょっとだけ足を踏み入れることにする。
亀山 幸義