1

ファイルのセットを解析するフロントエンドをtxt作成しています。各ファイルには一連の が含まれていproceduresます。たとえば、1 つの txt ファイルは次のようになります。

Sub procedure1
...
End Sub

Sub procedure2
...
End Sub

...

syntax.ml内容:

type ev = procedure_declaration list
type procedure_declaration = 
  { procedure_name : string; procedure_body : procedure_body }
type procedure_body = ...
...

parser.mly次のようになります。

%start main
%type <Syntax.ev> main
%%
main: procedure_declarations EOF { List.rev $1 }

procedure_declarations:
  /* empty */ { [] }
| procedure_declarations procedure_declaration { $2 :: $1 }

procedure_declaration:
SUB name = procedure_name EOS
body = procedure_body
END SUB EOS
{ { procedure_name = name; procedure_body = body } }
...

procedure_declarationここで、 (例外処理の目的で)の解析を取得したいと思います。つまり、 and を作成parser_pd.mlylexer_pd.mllparser.mlycallを呼び出しますparser_pd.main。したがって、parser_pd.mly次のようになります。

%start main
%type <Syntax.procedure_declaration> main
%%
main: procedure_declaration EOF { $1 };
...

以前のコンテンツのほとんどはparser.mlyに移動する必要があるためparser_pd.mlyparser.mly以前よりもはるかに軽くなり、次のようになります。

%start main
%type <Syntax.ev> main
%%
main: procedure_declarations EOF { List.rev $1 }

procedure_declarations:
  /* empty */ { [] }
| procedure_declarations procedure_declaration { $2 :: $1 }

procedure_declaration:
SUB name = procedure_name EOS
??????
END SUB EOS
{ { procedure_name = name; 
    procedure_body = Parser_pd.main (Lexer_pd.token ??????) } }

??????問題は、その部分の書き方がわからないことであり、lexer.mllどちらが軽くなければならないかということです ( token ENDSUBandのみを読み取り、EOSによって処理されるコンテンツを許可するためlexer_pd.mll)。おそらく、Lexingモジュールのいくつかの機能が必要ですか?

私の質問が明確であることを願っています...誰か助けてくれますか?

4

1 に答える 1

0

あなたはprocedure_declarationの解析を取得したいと書いていますが、あなたのコードではprocedure_bodyのみを取得したいので、それがあなたが望むものだと思います。

私自身の言葉で言えば、どの文法が埋め込まれているかを埋め込み文法に伝えずに、文法を構成する必要があります。これに関する問題 (あなたの場合は問題ありません。幸運なことに、非常に親しみやすい文法を持っているからです) は、LALR(1) では、どのルールを採用するかを決定するために先読みのトークンが 1 つ必要になることです。文法は次のようになります。

procedure_declaration:
  SUB procedure_name EOS
  procedure_body
  END SUB EOS

procedure_name と procedure_body を組み合わせることができるため、ルールとセマンティック アクションは次のようになります。

procedure_declaration:
  SUB combined = procedure_name EOS /* nothing here */ EOS
  { { procedure_name = fst combined; procedure_body = snd combined; } }

procedure_name:
  id = IDENT {
    let lexbuf = _menhir_env._menhir_lexbuf in
    (id, Parser_pd.main Lexer_pd.token lexbuf)
  }

Parser_pd には次のルールが含まれます。

main: procedure_body END SUB { $1 }

procedure_body は自己区切りではない可能性が高いため、Parser_pd で END SUB が必要になる可能性が非常に高くなります。

プロシージャ名識別子の後の最初の EOS を解析する前にサブパーサーを呼び出すことに注意してください。これが先読みであるためです。EOS でそれを呼び出すと 、手遅れであり、パーサーはすでに本体からトークンを取得しています。2 番目の EOS は END SUB の後のものです。

これ_menhir_envは明らかに、menhir でのみ機能するハックです。menhir --inferユーザーがそれを参照することを期待していないため、機能させるには別のハックが必要になる場合があります (それを使用する場合)。そのため、シンボルはスコープ内にありません。そのハックは次のようになります。

%{
  type menhir_env_hack = { _menhir_lexbuf : Lexing.lexbuf }
  let _menhir_env = { _menhir_lexbuf = Lexing.from_function
    (* Make sure this lexbuf is never actually used. *)
    (fun _ _ -> assert false) }
%}
于 2014-02-04T03:37:33.683 に答える