我正在编写一个前端来解析一组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
模块中的一些函数?
希望我的问题很清楚......有人可以帮忙吗?
答案 0 :(得分:0)
你写的是你要检索procedure_declaration的解析, 但是在你的代码中,你只想检索一个procedure_body,所以我就是 假设这就是你想要的。
用我自己的话说,你想要不用编写语法 告诉嵌入语法嵌入了哪种语法。问题(没有 在你的情况下的问题,因为你幸运地有一个非常友好的语法) 这是在LALR(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 }
你很可能在Parser_pd中想要END SUB,因为procedure_body是 可能不会自我划分。
请注意,在解析第一个EOS之前调用子解析器 过程名称标识符,因为这是你的前瞻。如果你打电话 在 EOS中,为时已晚,解析器将从中提取令牌 身体,已经。第二个EOS是END SUB之后的那个。
_menhir_env
显然是一种只适用于menhir的黑客攻击。
您可能需要另一个hack来使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) }
%}