Parsing 为什么我的EOF/linebreak非终端总是有shift/reduce冲突?
所以,我在语法分析方面还处于初级阶段。我需要帮助剖析Menhir报告的冲突,当我需要减少冲突时 以这个小语法为例:Parsing 为什么我的EOF/linebreak非终端总是有shift/reduce冲突?,parsing,ocaml,shift-reduce-conflict,menhir,Parsing,Ocaml,Shift Reduce Conflict,Menhir,所以,我在语法分析方面还处于初级阶段。我需要帮助剖析Menhir报告的冲突,当我需要减少冲突时 以这个小语法为例: (* {2 Tokens } *) %token EOF %token COLON PIPE SEMICOLON %token <string> COUNT %token <string> IDENTIFIER %start <AST.t> script %start <AST.statement> statement %% (*
(* {2 Tokens } *)
%token EOF
%token COLON PIPE SEMICOLON
%token <string> COUNT
%token <string> IDENTIFIER
%start <AST.t> script
%start <AST.statement> statement
%%
(* {2 Rules } *)
script:
| it = separated_list(break, statement); break?; EOF { { statements = it } }
;
statement:
| COLON*; count = COUNT?; cmd = command { AST.make_statement ~count ~cmd }
;
command:
| it = IDENTIFIER { it }
;
break:
| SEMICOLON { }
;
%%
我花了一个晚上的时间试图通过文档挖掘出转换/减少冲突实际上是什么,但我不得不承认,我很难理解我所阅读的内容。有人能给我一个简单(好的,尽可能多)的解释转移/减少冲突吗?具体使用上述示例的上下文?问题在于,在查看分号时,解析器无法确定它应该使用EOF还是列表的其余部分。原因是您使用了
break
作为可选的终止符,而不是分隔符
我建议你改变你的主要规则:
script:
| it = optterm_list(break, statement); EOF { { statements = it } }
;
然后自己定义opterm_列表
combinator,如下所示:
optterm_list(separator, X):
| separator? {[]}
| l=optterm_nonempty_list(separator, X) { l }
optterm_nonempty_list(separator, X):
| x = X separator? { [ x ] }
| x = X
separator
xs = optterm_nonempty_list(separator, X)
{ x :: xs }
optterm_list(separator, X):
| separator? {[]}
| l=optterm_nonempty_list(separator, X) { l }
optterm_nonempty_list(separator, X):
| x = X separator? { [ x ] }
| x = X
separator
xs = optterm_nonempty_list(separator, X)
{ x :: xs }