我正在编写一个前端来解析一组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.mly
和lexer_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
应该很轻(因为它仅读取令牌END
,SUB
和EOS
,并让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) }
%}