字句解析器は、lexer.mllというファイルに記述してocamllexというツールで生成する。このツールは名前の通りlexのOCaml版である。
lexer.mllでは、tokenとcommentの2つのスキャナが定義されている。
MinCamlの文法は素直な文脈自由文法で、tokenスキャナでは予約語を認識して対応するトークンを返す。
例外はコメントの処理で、(*という文字列が来るとスキャナをcommentスキャナに切り替えて読み飛ばす(アクション部で更にスキャナを呼ぶというのは今読んだ文字列を読み飛ばすことを意味する)。commentスキャナでも(*を認識していて、これが来るとcommentスキャナを二度呼ぶ。これはMinCamlではコメントのネストを許しているためで、一回目でネストしたコメントを読み飛ばし、次に現在のコメントの残りを読む。
トークンは構文解析器を記述するparser.mly中の%token命令で定義される。構文解析器を生成するocamlyaccというツールにより、それらをデータ構成子とする型Parser.tokenが定義される。
parser.mlyでのトークンの定義:
%token <bool> BOOL %token <int> INT %token <float> FLOAT %token NOT %token MINUS %token PLUS ...
ocamlyaccにより生成されるparser.mliでのデータ型Parser.token:
type token = | BOOL of (bool) | INT of (int) | FLOAT of (float) | NOT | MINUS | PLUS ...
スキャナでは予約語以外の単語がくるとトークンIDENTを返す。このトークンの値となるId.tは文字列のみから成るデータ型で、以後変数や関数の名前に用いられる。
パターンマッチのダミーを示す'_'に対してはその都度新しく名前を生成する。
識別子等のアクション部で使われるLexing.lexeme lexbufという式はパターンにマッチした文字列を参照する。
OCamlメモ
open Module- 他のモジュールで定義した識別子を、モジュール名のプレフィクスなしで使えるようにする。Javaの
importやC++のusing namespaceに似ている。 int_of_string: string -> int- 文字列を整数として解釈する。
float_of_string: string -> float- 文字列を浮動小数として解釈する。