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
    ;

(如有錯漏,還望指摘)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章