module Genlex:汎用字句解析器sig..end
このモジュールでは、単純な「標準の」字句解析器を、文字のストリームからトークンのストリームへの関数として実装します。 この字句解析器は Caml の字句規約をおおよそ実装しつつ、目的の言語の予約語をパラメータとして与えることができるようになっています。
例: 電卓用の字句解析器は次のようにして作ることができます。
let lexer = make_lexer ["+";"-";"*";"/";"let";"="; "("; ")"]
これに対応する構文解析器は、 token stream から、例えば int
への関数とすると、次のような規則を持ったものになるでしょう。
let parse_expr = parser
[< 'Int n >] -> n
| [< 'Kwd "("; n = parse_expr; 'Kwd ")" >] -> n
| [< n1 = parse_expr; n2 = parse_remainder n1 >] -> n2
and parse_remainder n1 = parser
[< 'Kwd "+"; n2 = parse_expr >] -> n1+n2
| ...
type token =
| |
Kwd of |
| |
Ident of |
| |
Int of |
| |
Float of |
| |
String of |
| |
Char of |
Int と Float はそれぞれ整数と浮動小数点数です。
String はダブルクォートでくくった文字列リテラルです。
Char はシングルクォートでくくった文字リテラルです。
Ident は識別子(英文字、数字、下線、クォートの並びか、 + や * といった「演算子文字」の並び)です。
Kwd は予約語(識別子か、 ( や } のような単一の特殊文字)です。val make_lexer : string list -> char Stream.t -> token Stream.ts がこのリストに含まれていた場合、戻り値のストリーム内でその識別子は Kwd s になります。
そうでなければ Ident s になります。
特殊文字 s がこのリストに含まれていた場合、戻り値のストリーム内でその識別子は Kwd s になります。
そうでなければ字句エラー(Parse_error 例外)が発生します。
空白と改行は読み飛ばされます。
(* と *) で区切られたコメントも同じく読み飛ばされます。
コメントは入れ子にすることができます。