2012-10-25 27 views
0

你好,我剛剛開始在bison/yacc中做一些解析。現在我的第一個程序已經失敗。什麼地方出了錯?我使用的是例如由: original source of tutorial用簡單的計算器語法解決衝突轉換/減少

%{ 
    #include <stdio.h> 
    int yylex(void); 
    void yyerror(char *); 
%} 


%token INTEGER 

%% 

program: 
     program expr '\n'   { printf("%d\n", $2); } 
     | 
     ; 

expr: 
     INTEGER     { $$ = $1; } 
     | expr '+' expr   { $$ = $1 + $3; } 
     | expr '-' expr   { $$ = $1 - $3; } 
     ; 

%% 

void yyerror(char *s) { 
    fprintf(stderr, "%s\n", s); 
} 

int main(void) { 
    yyparse(); 
    return 0; 
} 

使用野牛的2.4.1版本,我得到這個錯誤:

conflicts: 4 shift/reduce 
+0

[AIX文檔yacc](http://pic.dhe.ibm.com/infocenter/aix/v6r1/index.jsp?topic=%2Fcom.ibm.aix.genprogc%2Fdoc%2Fgenprogc%2Fie_prog_4lex_yacc.htm )解釋我的問題。我的語法是模糊的 – elcojon

回答

0

試一下:

expr: 
    INTEGER     { $$ = $1; } 
    | expr '+' INTEGER   { $$ = $1 + $3; } 
    | expr '-' INTEGER   { $$ = $1 - $3; } 

野牛/ yacc的不要」喜歡權利遞歸。如果輸入是1+2+3,那麼當解析器到達1+2+時,它不能決定將1+2減少爲expr,或者移動另一個令牌以便將2+3減少爲expr。通過在右側指定INTEGER,它可以決定一旦它看到1+2只留下expr + 3然後再減少。

您也可以通過指定+-是左關聯的,從而得到更高的優先級,以減少1+2在轉移新的令牌解決問題。在您的序言中添加該行:

%left '+' '-' 

希望它有幫助。

+0

謝謝你的回答。我剛剛自己弄明白了。它讓事情變得更加清晰。 – elcojon

+1

野牛與右遞歸沒有問題。如果你想要一個右聯合的'='運算符,你可以使用'expr:INTEGER'='expr;';沒關係。問題是當你在* both *方有'expr';那麼語法是不明確的。正如你所說,你可以用優先聲明來解決含糊不清的問題。 – rici

+0

「不喜歡右遞歸」在這裏並不重要。它們同時支持,但當堆棧空間是一個問題時(這裏不是這種情況),更喜歡左遞歸。這裏的問題是語法不明確,並且沒有說「1-2-3」是「(1-2)-3」還是「1-(2-3)」。當然,'左' - ''是做權的行爲,但它與Bison喜歡與否無關。 – akim