Cae*_*nog 10 grammar conflict gppg
我在理解移位/缩小语法的问题时遇到了问题,我知道语法没有歧义.这个案例是if else类型之一,但它不是'悬空的'问题,因为我有强制的END子句来分隔代码块.
这是gppg的语法(它是一个像编译器编译器一样的Bison ......而且它不是一个echo):
%output=program.cs
%start program
%token FOR
%token END
%token THINGS
%token WHILE
%token SET
%token IF
%token ELSEIF
%token ELSE
%%
program : statements
;
statements : /*empty */
| statements stmt
;
stmt : flow
| THINGS
;
flow : '#' IF '(' ')' statements else
;
else : '#' END
| '#' ELSE statements '#' END
| elseifs
;
elseifs : elseifs '#' ELSEIF statements else
| '#' ELSEIF statements else
;
Run Code Online (Sandbox Code Playgroud)
这是冲突输出:
// Parser Conflict Information for grammar file "program.y"
Shift/Reduce conflict on symbol "'#'", parser will shift
Reduce 10: else -> elseifs
Shift "'#'": State-22 -> State-23
Items for From-state State 22
10 else: elseifs .
-lookahead: '#', THINGS, EOF
11 elseifs: elseifs . '#' ELSEIF statements else
Items for Next-state State 23
11 elseifs: elseifs '#' . ELSEIF statements else
// End conflict information for parser
Run Code Online (Sandbox Code Playgroud)
我已经切换了所有内容,我确实知道如何解决它,但该解决方案涉及放弃'elseif'上的左递归以进行正确的递归.
我已经浏览了我在互联网上找到的关于这个问题的所有简明文档(我在最后发布了一些链接),但仍然没有找到一个优雅的解决方案.我知道ANTLR,我现在不想考虑它.请将您的解决方案限制为Yacc/Bison解析器.
我会欣赏优雅的解决方案,我设法做到这一点,通过消除/*空*/规则和复制所有需要空列表的东西但是在更大的语法中我正在努力它最终就像'sparghetti语法综合症'.
以下是一些链接:
http://nitsan.org/~maratb/cs164/bison.html
您修订的ELSEIF规则没有条件的标记 - 它应该名义上添加'('和')'.
更严重的是,你现在有一个规则
elsebody : else
| elseifs else
;
Run Code Online (Sandbox Code Playgroud)
和
elseifs : /* Nothing */
| elseifs ...something...
;
Run Code Online (Sandbox Code Playgroud)
不需要'什么'; 没有'elseifs','elsebody'会隐含地处理它.
我非常倾向于使用规则'opt_elseifs','opt_else'和'end':
flow : '#' IF '(' ')' statements opt_elseifs opt_else end
;
opt_elseifs : /* Nothing */
| opt_elseifs '#' ELSIF '(' ')' statements
;
opt_else : /* Nothing */
| '#' ELSE statements
;
end : '#' END
;
Run Code Online (Sandbox Code Playgroud)
我没有通过解析器生成器运行它,但我发现这相对容易理解.