本文共 626 字,大约阅读时间需要 2 分钟。
今天遇见一个很奇怪的归约/归约冲突,大概类似这样:
...%left NOT AND...expr: NUM | expr opt AND expr ;opt: NOT | /* empty */ ;...
一直在报归约/归约冲突,我就懵了,哪里冲突了???
直到我仔细研读了一波output文件才弄明白:
当栈里已经有expr
opt
AND
expr
的时候,本来应该按照左结合规则直接进行归约,但是bison却必须读到下一个字符才进行归约。 而如果下一个字符是AND
,那么就出现了问题: 因为此时首先已有的四个token可以归约为expr,与此同时,AND
前还可以归约出一个为空的opt。 然后就出现了问题!(?) 那就是一次归约只能出一个token(就不能归约两次么……),所以出现了归约/归约冲突。 不过这些都是根据output文件推出来的,至于bison为什么会生成这么诡异的规则……emmmmmm……我也不到啊!
但是总而言之,那就是:
在左结合的操作符的左边,不能有可以归约为空的token! 不然会导致归约/归约冲突。 另外,似乎在可以嵌套的括号右侧,也不能有可以归约为空的token(但是我自己还没有测试)所以如上代码应该改成:
expr: NUM | expr opt AND expr | expr AND expr ;opt: NOT ;
(如有错漏,还望指摘)
转载地址:http://ctxzi.baihongyu.com/