私は会社のプロジェクトに取り組んでおり、Ocamlyacc と Ocamllex を使用して言語のコンパイラを作成する必要があります。Ocamlyacc パーサーで、入力の構文に一致する文法のルールがないことを示すルールを定義できるかどうかを知りたいです。
私は Ocamllex/Ocamlyacc の初心者であることを主張しなければなりません
大変お世話になりました。
入力に一致する文法規則がない場合、Parsing.Parse_error
例外が発生します。通常、これはあなたが望むものです。
error
パーサーの状態を再同期できるようにする特別なトークンも呼び出されます。これは、レクサーによって生成された実際のトークンであったため、ルールで使用できeof
ます。トークンを参照してください。
menhir
また、より由緒あるの代わりに使用することをお勧めしますocamlyacc
。使用とデバッグがより簡単で、事前定義された文法の優れたライブラリも付属しています。
言語用のコンパイラを作成するときの最初のステップは、レクサーを実行し、プログラムがレキシカルな観点から適切かどうかをチェックすることです。
以下の例を参照してください。
{
open Parser (* The type token is defined in parser.mli *)
exception Eof
}
rule token = parse
[' ' '\t'] { token lexbuf } (* skip blanks *)
| ['\n' ] { EOL }
| ['0'-'9']+ as lxm { INT(int_of_string lxm) }
| '+' { PLUS }
| '-' { MINUS }
| '*' { TIMES }
| '/' { DIV }
| '(' { LPAREN }
| ')' { RPAREN }
| eof { raise Eof }
いくつかの算術式を認識するレクサーです。
字句解析器が入力を受け入れる場合、語彙素のシーケンスをパーサーに渡します。パーサーは指定された文法で AST を構築できるかどうかを見つけようとします。見る :
%token <int> INT
%token PLUS MINUS TIMES DIV
%token LPAREN RPAREN
%token EOL
%left PLUS MINUS /* lowest precedence */
%left TIMES DIV /* medium precedence */
%nonassoc UMINUS /* highest precedence */
%start main /* the entry point */
%type <int> main
%%
main:
expr EOL { $1 }
;
expr:
INT { $1 }
| LPAREN expr RPAREN { $2 }
| expr PLUS expr { $1 + $3 }
| expr MINUS expr { $1 - $3 }
| expr TIMES expr { $1 * $3 }
| expr DIV expr { $1 / $3 }
| MINUS expr %prec UMINUS { - $2 }
;
これは、算術式を解析するための小さなプログラムです。最後に AST を付けるために適用する文法規則がないため、プログラムはこのステップで拒否される可能性があります。認識されていないルールを定義する方法はありませんが、プログラムが受け入れられるか拒否されるかを定義する文法を記述する必要があります。
let _ =
try
let lexbuf = Lexing.from_channel stdin in
while true do
let result = Parser.main Lexer.token lexbuf in
print_int result; print_newline(); flush stdout
done
with Lexer.Eof ->
exit 0
レクサー、パーサー、および最後のプログラムをコンパイルすると、次のようになります。
1 + 2
エラー字句エラーがなく、この式に対応する AST を構築できるため、受け入れられます。1 ++ 2
は拒否されます: 字句エラーはありませんが、そのような AST を構築する規則はありません。ここでより多くのドキュメントを見つけることができます: http://caml.inria.fr/pub/docs/manual-ocaml-4.00/manual026.html