為了避免 Bison 發出有關可預測的、合法的移位/歸約沖突的警告,可以使用 %expect n 聲明。但不建議
如何解決移進規約沖突?比如下面的文法就有沖突:
expr: expr - expr | expr * expr | - expr
對于輸入:-1 * 2
解析完1后,可以繼續移進 * ,或者根據規則 expr:-expr 規約為 -1。也就是說,解析方式有兩種:
-1 * 2 = (-1)*2 或者 -1 * 2 =- (1*2)
雖然結果一樣,但是程序不知道該選擇哪種方式。
之所以沖突,是因為移進和 歸約的優先級沒有確定,即符號 * 和規則 expr: -expr 的優先級沒有確定,出現了 * 就不知道該移進 * 還是利用規則來歸約了。
那么只要定義了它們的優先級,就可以解決沖突了。怎么定義呢?
(其實規則有默認的優先級,為該規則中最后一個符號的優先級,比如 IF expr THEN stmt 的優先級就是THEN的優先級)
- 
使用%prec定義規則對應的符號(即定義此規則和哪個符號的優先級相同)。
- 
使用%left/%right/%noassoc/%precedence來定義符號的優先級和結合性(分別是左結合、右結合、沒有結合性、未定義的結合性)。
所以需要先定義規則對應的虛擬符號,再定義這個虛擬符號和 * 的優先級關系,這樣就定義了此規則和 * 的優先級了。
于是定義符號的優先級。這里UMINUS在 * 的下方,表示優先級比 * 更高:
// 優先級從下往上遞減 %left - %left * %left UMINUS
當然了,這里的UMINUS只是一個虛擬符號,所以結合性無所謂,就用%left來定義吧(或者用%noassoc來定義)。
再定義規則對應的符號:
expr: expr - expr | expr * expr | - expr %prec UMINUS
這樣,UMINUS的優先級比 * 高了,就表示規則 expr:-expr 的優先級比 * 高了。這樣移進/規約沖突就解決了。