在使用Python创建解析器时转移/减少冲突
我用sly()编写了一个解析器,但是它毫无理由地有两个shift/reduce冲突。我该怎么解决这个问题 parser.py在使用Python创建解析器时转移/减少冲突,python,parsing,yacc,ply,Python,Parsing,Yacc,Ply,我用sly()编写了一个解析器,但是它毫无理由地有两个shift/reduce冲突。我该怎么解决这个问题 parser.py @_("NAME ASSIGN primary") def statement(self, p): self.variables[p[0]] = p[2] @_("primary") def statement(self, p): return p[0] @_("primary PLUS secund
@_("NAME ASSIGN primary")
def statement(self, p):
self.variables[p[0]] = p[2]
@_("primary")
def statement(self, p):
return p[0]
@_("primary PLUS secundary")
def primary(self, p):
return p[0] + p[2]
@_("primary MINUS secundary")
def primary(self, p):
return p[0] - p[2]
@_("secundary")
def primary(self, p):
return p[0]
@_("secundary MULTIPLY tertiary")
def secundary(self, p):
return p[0] * p[2]
@_("secundary FLOORDIV tertiary")
def secundary(self, p):
return p[0] // p[2]
@_("secundary DIVIDE tertiary")
def secundary(self, p):
return p[0] / p[2]
@_("secundary MOD tertiary")
def secundary(self, p):
return p[0] % p[2]
@_("tertiary")
def secundary(self, p):
return p[0]
@_("quaternary POWER tertiary")
def tertiary(self, p):
return p[0] ** p[2]
@_("quaternary")
def tertiary(self, p):
return p[0]
@_("tertiary quinary")
def quaternary(self, p):
return p[0] * p[1]
@_("quinary")
def quaternary(self, p):
return p[0]
@_("INTEGER")
def quinary(self, p):
return p[0]
@_("LPAREN primary RPAREN")
def quinary(self, p):
return p[1]
调试输出
state 27
(12) tertiary -> quaternary POWER tertiary .
(14) quaternary -> tertiary . quinary
(15) quinary -> . LPAREN primary RPAREN
(16) quinary -> . INTEGER
! shift/reduce conflict for LPAREN resolved as shift
! shift/reduce conflict for INTEGER resolved as shift
MOD reduce using rule 12 (tertiary -> quaternary POWER tertiary .)
DIVIDE reduce using rule 12 (tertiary -> quaternary POWER tertiary .)
FLOORDIV reduce using rule 12 (tertiary -> quaternary POWER tertiary .)
MULTIPLY reduce using rule 12 (tertiary -> quaternary POWER tertiary .)
MINUS reduce using rule 12 (tertiary -> quaternary POWER tertiary .)
PLUS reduce using rule 12 (tertiary -> quaternary POWER tertiary .)
$end reduce using rule 12 (tertiary -> quaternary POWER tertiary .)
RPAREN reduce using rule 12 (tertiary -> quaternary POWER tertiary .)
LPAREN shift and go to state 8
INTEGER shift and go to state 9
quinary shift and go to state 17
我只添加了调试文件的一部分,但是添加了整个语法,因为我认为其他语法都不相关,请告诉我是否应该发布更多代码
我不明白我的语法中怎么会有移位/减少冲突,因为我的规则没有含糊不清的地方 你的语法肯定是模棱两可的,因为
1次幂23
可以被解析为(1次幂2)*3
或1次幂(2*3)
。为了修复语法,您需要确定这两种解释中的哪一种是您想要的,然后更改语法以只允许正确的解释
据我所知,关于隐式乘法运算符的优先级还没有达成共识。许多人认为它应该与显式乘法具有完全相同的优先级和结合性。另一些人认为2a/7b
应该被解释为(2*a)/(7*b)
,而不是((2*a)/7)*b
,这导致了隐式乘法应该结合得更紧密的想法
当引入指数运算时,事情变得更加复杂。在数学中,指数运算通常是用排版效果写成二维的。这使得指数的分组更加明确。对于其余部分,求幂结合更紧密(甚至比一元否定更紧密)的约定是没有问题的,我们有:
- (1)
=>a2b
a*(2次电源b)
- (2)
=>a2b
a电源(2*b)
- (3)
=>a2b
(a电源2)*b
^
,则它们都将被写入a^2b
,解析器需要决定将两种可能的解释中的哪一种分配给字符串
想要将未解析表达式a2^b
和a^2b
解析为(1)和(2)的问题在于优先顺序不同:在情况(1)中,我们以幂运算为优先,而要实现情况(2),隐式乘法必须优先。我相信这就是你的语法试图做的,它失败了,正是因为这种形式的优先级反转非常棘手(通常会导致歧义)。将a^2b
解释为(3)要简单得多,因为优先级是相同的
所以我建议你接受口译(3)。语言设计的一个重要原则是,计算机难以消除歧义的东西,人类也往往难以消除歧义,因此最好避免困难的消除歧义规则。(作为一个激励的例子,参见C++中的所谓的常见错误,这是许多C和C++编译器在关于语法冲突的完美的法律表达式如“代码”>中发出警告的原因,在分析语法冲突时,看到整个语法是有用的。添加一条说明。@wendelin:第一步是找出您认为正确的解析。@wendelin:整理您的结果,使第三个是左联想隐式乘法,第四个是右联想指数运算。
# This version makes implicit multiplication bind more tightly
# than division. Otherwise, implicit multiplication would just be
# added to secondary.
@_("tertiary quaternary")
def tertiary(self, p):
return p[0] * p[1]
@_("quaternary")
def tertiary(self, p):
return p[0]
@_("quinary POWER quaternary"
def quaternary(self, p):
return p[0] ** p[2]
@_("quinary")
def quaternary(self, p):
return p[0]