2016-04-17 40 views
0

我知道我的語法錯誤的部分原因,但我不知道如何解決它,我甚至使用%左和右,但它沒有幫助。任何人都可以幫助我找出這個語法有什麼問題。 在此先感謝您的幫助。yacc中的移位/減少錯誤

%token VARIABLE NUM 
%right '=' 
%left '+' '-' 
%left '*' '/' 
%left '^' 
%start S_PROOP 

EQUATION_SEQUENCE 
    : FORMULA '=' EQUATION 
    ; 
EQUATION 
    : FORMULA 
    | FORMULA '=' EQUATION 
    ; 
FORMULA 
    : SUM EXPRESSION 
    | PRODUCT EXPRESSION 
    | EXPRESSION '+' EXPRESSION 
    | EXPRESSION '*' EXPRESSION 
    | EXPRESSION '/' EXPRESSION 
    | EXPRESSION '^' EXPRESSION 
    | EXPRESSION '-' EXPRESSION 
    | EXPRESSION 
    ; 
EXPRESSION 
    : EXPRESSION EXPRESSION 
    | '(' EXPRESSION ')' 
    | NUM 
    | VARIABLE   
    ; 

回答

0

普通樣式是使用對非端子和端子上殼體下殼體;使用大寫不加區分地使你的語法難以閱讀(至少對於我們習慣於正常yacc /野牛風格的人來說)。所以我寫了這個答案,沒有太多的大寫鎖定鍵。

基本問題是生產

expression: expression expression 

這顯然是不明確的,因爲它不提供關聯的任何指示。在這方面,它不是來自

expression: expression '+' expression 

不同,但衝突可以使用優先權的聲明來解決:

%left '+' 

不同的是,第一個生產沒有任何終端的象徵,這使得它不可能使用優先規則來消除歧義:在yacc/bison中,優先級總是比較潛在的減少和潛在的轉變。潛在的減產是一些可以減少的產量;潛在的轉變是可能能夠延長一些生產的終端符號。由於潛在的轉換必須是終端符號,這就是優先聲明中所使用的符號;默認情況下,潛在縮減的優先級由右側的最後一個終端符號定義,但可以使用%prec標記指定不同的終端。在任何情況下,優先關係都涉及終端符號,並且如果語法允許並置兩個終端,則不存在相關的終端符號。

這很容易解決,因爲您沒有義務使用優先級來解決衝突。你可能只是避免衝突:

/* Left associative rule */ 
expr_sequence: expr | expr_sequence expr 

/* Alternative: right associative rule */ 
expr_sequence: expr | expr expr_sequence 

由於沒有任何跡象表明你打算用什麼並列,我不能推薦一個或另一個上述選擇,但通常我會傾向於對第一個。

雖然equation_sequence實際上使用了一個終端符號,所以它可以用優先級聲明處理,這與equation_sequence的語法並無太大區別。值得注意的是,equation_sequence,正如所寫,是右聯合的。對於賦值運算符通常被認爲是正確的,(a = b = c + 3,用C語言解析爲a = (b = c + 3)而不是(a = b) = c + 3,使得賦值爲少數右聯合運算符之一)。但是,如果您使用=作爲相等運算符,可能並不是你想要的。