2013-10-20 73 views
0
A: constant 
| OPENINGBRACES B C 
; 

constant: INTEGER | REAL | CHARACTER ; 

C: CLOSINGBRACES 
| COMMA CLOSINGBRACES 
; 

B: A 
| A COMMA B 
; 

此語法是生產移/減少error.after與-v選項運行它,它示出了在狀態7衝突..COMMA移/減少錯誤野牛

** 
state 7 

8 B: A . 
9 | A . COMMA B 

COMMA shift, and go to state 10 

COMMA  [reduce using rule 8 (B)] 
$default reduce using rule 8 (B) 
** 

規則8是
8 B:A

回答

3

shift/reduce是CONFLICT而不是ERROR--它告訴你語法不是LALR(1),所以bison生成的解析器只能識別你的語言的一個子集。這可能是一個問題,或者可能不是。

在你的情況,問題就來了一個事實,即CCLOSINGBRACES之前可選COMMA,但語法需要完成(減少)B它可以去之前提前解析C。因此,當您有像{ INT , INT , }這樣的輸入時,當它到達第二個COMMA時,它不知道是否應該減少B(完成列表),或者將COMMA移到另一個constant以添加到列表中。在這種情況下,它應該減少(因爲COMMA應該是C規則的一部分),但它不知道沒有兩個令牌前瞻來看,之後的}

在這種情況下,shift/reduce衝突的默認分辨率爲shift意味着解析器將始終期待逗號後面的另一個值,因此最終將解析語言而不使用可選逗號(就像規則C: COMMA CLOSINGBRACES的確如此不存在)

一個簡單的方法來解決這個問題是讓左遞歸,而不是右遞歸您B規則:

B: A 
| B COMMA A 
; 

這樣一個BB的有效的前綴,所以解析器總是可以減少B然後再添加A s到其後面(在轉移COMMA並查看下一個標記是什麼之後)。

+0

與野牛你應該_always_使用左遞歸而不是右遞歸,不僅要避免這樣的衝突,而且要確保解析器可以在有限的堆棧空間下操作。 –

+0

@JohnBollinger:* always *太強大了 - 當然如果其他所有的東西都是相等的,你應該更喜歡左遞歸到右遞歸,但是有時候右遞歸會簡化東西,而且如果你分配空間給無論如何整個列表。 –