0

私は会社のプロジェクトに取り組んでおり、Ocamlyacc と Ocamllex を使用して言語のコンパイラを作成する必要があります。Ocamlyacc パーサーで、入力の構文に一致する文法のルールがないことを示すルールを定義できるかどうかを知りたいです。

私は Ocamllex/Ocamlyacc の初心者であることを主張しなければなりません

大変お世話になりました。

4

2 に答える 2

3

入力に一致する文法規則がない場合、Parsing.Parse_error例外が発生します。通常、これはあなたが望むものです。

errorパーサーの状態を再同期できるようにする特別なトークンも呼び出されます。これは、レクサーによって生成された実際のトークンであったため、ルールで使用できeofます。トークンを参照してください。

menhirまた、より由緒あるの代わりに使用することをお勧めしますocamlyacc。使用とデバッグがより簡単で、事前定義された文法の優れたライブラリも付属しています。

于 2015-08-04T14:47:08.493 に答える
1

言語用のコンパイラを作成するときの最初のステップは、レクサーを実行し、プログラムがレキシカルな観点から適切かどうかをチェックすることです。

以下の例を参照してください。

{
  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. 1 + 2エラー字句エラーがなく、この式に対応する AST を構築できるため、受け入れられます。
  2. 1 ++ 2は拒否されます: 字句エラーはありませんが、そのような AST を構築する規則はありません。

ここでより多くのドキュメントを見つけることができます: http://caml.inria.fr/pub/docs/manual-ocaml-4.00/manual026.html

于 2015-08-04T14:21:52.523 に答える