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

Parsing 通过将.mly和.mll分开来检索解析的一部分,parsing,ocaml,lexical-analysis,ocamllex,ocamlyacc,Parsing,Ocaml,Lexical Analysis,Ocamllex,Ocamlyacc,我正在编写一个前端来解析一组txt文件,每个文件包含一组程序,例如一个txt文件如下所示: Sub procedure1 ... End Sub Sub procedure2 ... End Sub ... %start main %type <Syntax.ev> main %% main: procedure_declarations EOF { List.rev $1 } procedure_declarations: /* empty */ { [] } | pr

我正在编写一个前端来解析一组txt文件,每个文件包含一组程序,例如一个txt文件如下所示:

Sub procedure1
...
End Sub

Sub procedure2
...
End Sub

...
%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 } }
...
%start main
%type <Syntax.procedure_declaration> main
%%
main: procedure_declaration EOF { $1 };
...
syntax.ml包含:

type ev = procedure_declaration list
type procedure_declaration = 
  { procedure_name : string; procedure_body : procedure_body }
type procedure_body = ...
...
parser.mly看起来像:

Sub procedure1
...
End Sub

Sub procedure2
...
End Sub

...
%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 } }
...
%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 ??????) } }
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)
  }
问题是我不知道怎么写这个??????部分和lexer.mll,它应该是轻的,因为它只读取令牌END、SUB和EOS,并让内容由lexer_pd.mll处理。可能需要Lexing模块的一些功能


希望我的问题是清楚的。。。有人能帮忙吗

您写入要检索过程\u声明的解析, 但是在您的代码中,您只想检索一个过程体,所以我 假设那是你想要的

用我自己的话来说,你需要在没有 告诉嵌入语法嵌入哪个语法。问题不在这里 你的问题,因为你幸运地有一个非常友好的语法 在LALR1中,您需要一个前瞻标记来决定 要遵守哪条规则。您的语法如下所示:

procedure_declaration:
  SUB procedure_name EOS
  procedure_body
  END SUB EOS
您可以将过程\u名称和过程\u正文组合在一起,这样您的规则和 语义操作将如下所示:

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

_menhir_env这件事显然是一个只适用于menhir的黑客。 如果你使用它,你可能需要另一个黑客来让menhir-Inferre工作, 因为这并不期望用户引用它,所以符号不会 在范围内。那就是:

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