2014-10-08 48 views
0

我正在學習lex和yacc編程,並且這個yacc程序用於在給予我25shift/reduce衝突時驗證和評估算術表達式。在閱讀了其他的stackoverflow解釋之後,我明白這個問題是優先的,但是,我不確定如何使用錯誤處理來解決問題。我想知道是否有人可以幫助我。Lex yacc Shift/Reduce error

我已經試過了協會處理程序是這樣的:

%token VARNAME 
%token DIGIT 
%token EQ 
%token ADD SUB MULT DIV 
%token LPAREN RPAREN 
%token END 
%left ADD SUB MULT DIV LPAREN 
%right RPAREN END 
%nonassoc EQ VARNAME DIGIT 

但是,它不工作,我很困惑。這是我的1.y文件:

%{ 
#include <stdio.h> 
#include <stdlib.h> 

int main (int argc, char* argv[]) 
{ 
    FILE *fp; 
    extern FILE *yyin; 
    extern int yylex(); 
    extern int yyparse(); 
    extern int yydebug; 

    yydebug = 1; 
    if (argc == 2) 
    { 
     fp = fopen(argv[1], "r"); 
     if (!fp) 
     { 
     fprintf (stderr, "Usage: %s <filename>\n", argv[0]); 
     } 
     else 
     { 
      yyin = fp; 
      yyparse(); 
      fprintf (stdout, "***PARSE COMPLETE***\n"); 
     } 
    } 
    else 
     fprintf (stderr, "Usage: %s <filename>\n", argv[0]); 
} 

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

%} 

%token VARNAME 
%token DIGIT 
%token EQ 
%token ADD SUB MULT DIV 
%token LPAREN RPAREN 
%token END 

%% 
    statement: 
    END 
    | 
    expression END 
    {printf ("DONE!\n");}; 
    | 
    error 
    { printf(" INVALID EXPRESSION\n"); } 
; 

expression: 
    VARNAME 
    {printf("PARSED A VARIABLE!\n");}; 
    | 
    DIGIT 
    {printf("PARSED A DIGIT!\n");}; 
    | 
    expression ADD expression 
    {printf("PARSED A PLUS SIGN!\n");}; 
    | 
    expression SUB expression 
    {printf("PARSED A MINUS SIGN!\n");}; 
    | 
    expression MULT expression 
    {printf("PARSED A MULTPLY SIGN!\n");}; 
    | 
    expression DIV expression 
    {printf("PARSED A DIVIDE SIGN!\n");}; 
    | 
    expression EQ expression 
    {printf("PARSED A EQUALS SIGN!\n");}; 
    | 
    LPAREN expression RPAREN 
    {printf("PARSED A PARENTHESIS!\n");}; 
    ; 

%% 

我試圖像這樣的協會處理程序:

%token VARNAME 
%token DIGIT 
%token EQ 
%token ADD SUB MULT DIV 
%token LPAREN RPAREN 
%token END 
%left ADD SUB MULT DIV LPAREN 
%right RPAREN END 
%nonassoc EQ VARNAME DIGIT 

這是聯想是否正確?

+1

您需要指定運算符的優先級和關聯性。查找'%left','%right'和'%nonassoc'。或者以不同的方式完全寫出語法。例如,C標準中的語法不需要優先級或關聯性。 – 2014-10-08 05:18:05

+0

@JonathanLeffler我在格式化時遇到了問題,但是我嘗試着更新了文章。我是否正確地關聯了DIGITS,EQ和VARNAME? – user1093111 2014-10-08 05:34:48

+0

'%token'項看起來似乎合理。我認爲'%left'不需要'LPAREN'; '%right'也不需要'RPAREN'。我不確定你是否需要'%nonassoc'。我假設''代碼'(在開始處和''''代碼''結尾處是試圖格式化評論的文物。通常情況下,您希望ADD和SUB的優先級低於MULT和DIV。 – 2014-10-08 05:35:50

回答

0

這個問題在GNU bison manual中涵蓋得相當好。

由於@Jonathan萊弗勒說:

你需要指定的經營者的優先級和結合。查看%left,%right%nonassoc。或者以不同的方式完全寫出語法。例如,C標準中的語法不需要優先級或關聯性。

%token項目看起來似乎合理。我認爲%left不需要LPAREN; %right也不需要RPAREN。我不確定你是否需要%nonassoc。我假設最後的'code'(和最後的)'code'是試圖格式化評論的文物。通常情況下,您希望ADD和SUB的優先級低於MULT和DIV。

expression : term 
      | term ADD expression 
      | term SUB expression 
      ; 

term : factor 
    | factor MULT term 
    | factor DIV term 
    ; 

factor : VARNAME 
     | DIGIT 
     | LPAREN expression RPAREN 
     ; 

現在你有兩個關聯性,並以明確的語法定義運算符的優先級:

在運算實例中,這些通過編寫語法如同通常解決。