以下(简化)Bison语法产生减少冲突:
expr
: '(' expr ')'
| ID
| fn
;
arg_list
: ID
| arg_list ID
;
fn
: '(' ')' fnbody
| '(' arg_list ')' fnbody
;
fnbody
: '{' '}'
;
我看到了问题 - 只有一个前瞻标记,无法判断(an_id
是'(' expr ')'
还是fn
。但是我该如何解决呢?
答案 0 :(得分:3)
嗯,最简单的答案就是在解析器中使用更多的前瞻 - 使用btyacc之类的东西,或者使用bison的%glr-parser
选项。
第二种选择是在词法分析器中添加前瞻 - 在这种情况下,在返回')'
令牌之前,查看下一个令牌是否为'{'
并返回一个告诉您的特殊标记这是一个你要结束的arg_list,而不是一个带括号的表达式,或者只是将两个作为单个标记返回并根据需要修改你的语法。
第三种选择是将语法考虑在内。这并不总是容易的,可能会破坏语法的大小。基本思想是识别冲突的规则并将它们组合成一个规则,该规则可以由解析器进行重新规划,并推迟选择最终的构造,直到您看到足够的为止。
对于此示例,您将为冲突案例添加新规则:
expr_or_fnhead: '(' ID ')' ;
可能是表达式或fn
的开头,然后修改其他规则以使用它。 fn
规则变为:
fn : '(' ')' fnbody /* 0 arg function */
| expr_or_fnhead fnbody /* 1 arg function */
| '(' ID arg_list ')' fnbody /* 2+ arg function */
;
expr
规则更复杂:
expr : ID
| non_ID_expr
;
non_ID_expr: '(' non_ID_expr ')'
| expr_or_fnhead
| fn
;