Bison 操作符前可以为空导致的归约/归约冲突

今天遇见一个很奇怪的归约/归约冲突,大概类似这样:

...
%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
    ;

(如有错漏,还望指摘)

原创文章 34 获赞 41 访问量 5955

猜你喜欢

转载自blog.csdn.net/qq_44844115/article/details/102668186