通过进行分开的.mly和.mll来检索解析的一部分



我正在编写一个前端来解析一组txt文件,每个文件包含一组procedures,例如一个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的解析(出于例外处理的目的)。这意味着,我想创建parser_pd.mlylexer_pd.mll,然后让parser.mly调用parser_pd.main。因此,parser_pd.mly看起来像:

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

由于上一个parser.mly中的大多数内容都应移至parser_pd.mly中,因此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
??????
END SUB EOS
{ { procedure_name = name; 
    procedure_body = Parser_pd.main (Lexer_pd.token ??????) } }

问题是我不知道如何编写??????零件,而lexer.mll应该很轻(因为它仅读取令牌ENDSUBEOS,并让lexer_pd.mll处理的内容)。也许需要Lexing模块的某些功能?

希望我的问题很清楚...谁能帮忙吗?

您写的是要检索Procedue_declaration的解析,但是在您的代码中,您只想检索Protecture_body,所以我假设这就是您想要的。

要插入我的话,您必须在没有的情况下撰写语法告诉嵌入语法嵌入哪种语法。问题(否在您的情况下,问题,因为幸运的是有一个非常友好的语法)这样的是,在拉尔(1)中,您需要一个lookahead的象征来决定要采取哪个规则。您的语法看起来像这样:

procedure_declaration:
  SUB procedure_name EOS
  procedure_body
  END SUB EOS

您可以组合Procedue_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 }

您很可能希望在Parser_pd中结束sub,因为Procedue_body是可能不是自我限制的。

请注意,在解析第一个EOS之后,请致电子份子过程名称标识符,因为那是您的lookahead。如果你打电话 eos中,为时已晚,解析器将从身体已经。第二个EOS是末端后方的一个。

_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) }
%}

最新更新