Parsing 解决LALR解析器中的移位/减少冲突
我一直在使用PLY为我的语言构建一个解析器,但是我遇到了一个shift/reduce冲突,这给我带来了一些麻烦。我的语言具有泛型类型,语法为ALLA C++模板。所以现在我有如下规则:Parsing 解决LALR解析器中的移位/减少冲突,parsing,yacc,lalr,ply,Parsing,Yacc,Lalr,Ply,我一直在使用PLY为我的语言构建一个解析器,但是我遇到了一个shift/reduce冲突,这给我带来了一些麻烦。我的语言具有泛型类型,语法为ALLA C++模板。所以现在我有如下规则: expression : expression LESS expression %prec COMPARISON expression : template template : NAME | NAME LESS templates GREATER tem
expression : expression LESS expression %prec COMPARISON
expression : template
template : NAME
| NAME LESS templates GREATER
templates : template
| templates COMMA template
但是,我发现它无法解析:
a < 2
a<2
(这是一个有明显原因的问题)。以下是调试输出:
PLY: PARSE DEBUG START
State : 0
Stack : . <Token: 'NAME' 'a'>
Action : Shift and goto state 42
State : 42
Stack : NAME . <Token: 'LESS' '<'>
Action : Shift and goto state 81
State : 81
Stack : NAME LESS . <Token: 'NUMBER' '2'>
ERROR: Error : NAME LESS . <Token: 'NUMBER' '2'>
PLY:解析调试开始
州:0
堆栈:。
行动:转移和转到状态42
国家:42
堆栈:名称。
措施:移位和转到状态81
州:81
堆栈:无名称。
错误:错误:无名称。
如果需要更多的解析器,我可以提供它。谢谢
编辑:向我建议的一个解决方案是使类型成为它们自己的标记。这需要做一点工作,因为我的语言没有使用预处理器,包括C/C++之类的系统。不过,我认为这仍然是可能的,我更喜欢仅限于语法的解决方案。Yacc解析器不是特别强大,尝试无上下文解析可能要求太多。我建议使用某种技巧使yacc像解析上下文敏感语法一样工作,或者,不要尝试使用解析器强制执行所有语法规则
- 添加上下文
在分析类型时进行识别,设置标志或调用方法将其传达给扫描仪,然后在这种情况下为
返回不同的终端符号 - 简化语法
或者,继续使用统一的表达式/模板语法作为模板生成的一部分,并在代码中删除除模板语法以外的任何内容。解析器是系统中功能最差的部分,因此尽可能将工作转化为代码。(对代码没有限制,对yacc有很多限制。)
Python和Ruby有什么等价物吗?这将解决问题。Bison的
%glr解析器
功能也可以“解决”类似的问题,尽管是以一种相当BFI的方式。不幸的是,如果不使用特定的模板规则,语法将更加模糊,并且在更琐碎的情况下失败。我认为您是对的,我需要添加上下文,这对于简单的情况(内置类型或该文件中定义的类型)来说很容易,但是对于使用导入系统的情况来说很难。哦,好吧:)