2015-05-25 52 views
0

我正在寫一個flex/yacc程序,它應該使用cygwin來讀取一些令牌和簡單的語法。 我猜我的BNF語法錯了,但我似乎無法找到問題。下面是一些代碼如何在我的yacc代碼中找到減少/移位衝突?

%start statement_list 

%% 
statement_list: statement 
      |statement_list statement 
      ; 

statement: condition|simple|loop|call_func|decl_array|decl_constant|decl_var; 

call_func: IDENTIFIER'('ID_LIST')' {printf("callfunc\n");} ; 

ID_LIST: IDENTIFIER 
     |ID_LIST','IDENTIFIER 
     ; 


simple: IDENTIFIER'['NUMBER']' ASSIGN expr 
     |PRINT STRING 
     |PRINTLN STRING 
     |RETURN expr 
     ; 

bool_expr: expr E_EQUAL expr 
     |expr NOT_EQUAL expr 
     |expr SMALLER expr 
     |expr E_SMALLER expr 
     |expr E_LARGER expr 
     |expr LARGER expr 
     |expr E_EQUAL bool 
     |expr NOT_EQUAL bool 
     ; 

expr: expr ADD expr {$$ = $1+$3;} 
| expr MULT expr {$$ = $1-$3;} 
| expr MINUS expr {$$ = $1*$3;} 
| expr DIVIDE expr {if($3 == 0) yyerror("divide by zero"); 
       else $$ = $1/$3;} 
|expr ASSIGN expr 
| NUMBER 
| IDENTIFIER  
; 

bool: TRUE 
|FALSE 
; 

decl_constant: LET IDENTIFIER ASSIGN expr 
      |LET IDENTIFIER COLON "bool" ASSIGN bool 
      |LET IDENTIFIER COLON "Int" ASSIGN NUMBER 
      |LET IDENTIFIER COLON "String" ASSIGN STRING 
      ; 

decl_var: VAR IDENTIFIER 
|VAR IDENTIFIER ASSIGN NUMBER 
|VAR IDENTIFIER ASSIGN STRING 
|VAR IDENTIFIER ASSIGN bool 
|VAR IDENTIFIER COLON "Bool" ASSIGN bool 
|VAR IDENTIFIER COLON "Int" ASSIGN NUMBER 
|VAR IDENTIFIER COLON "String" ASSIGN STRING 
; 

decl_array: VAR IDENTIFIER COLON "Int" '[' NUMBER ']' 
    |VAR IDENTIFIER COLON "Bool" '[' NUMBER ']' 
    |VAR IDENTIFIER COLON "String" '[' NUMBER ']' 
    ; 

condition: IF '(' bool_expr ')' statement ELSE statement; 

loop: WHILE '(' bool_expr ')' statement; 

我試圖改變語句轉換成

statement:';'; 

,讀一個簡單的標記,以測試它是否工作,但似乎我的代碼拒絕進入語法的一部分。

另外,當我編譯它,它告訴我有18個轉換/減少衝突。我應該嘗試找到並解決所有這些問題嗎?

編輯:我編輯我的代碼使用克里斯多德的答案,試圖通過查看輸出文件來解決每個衝突。最後幾個衝突似乎位於下面的代碼中。

expr: expr ADD expr {$$ = $1+$3;} 
| expr MULT expr {$$ = $1-$3;} 
| expr MINUS expr {$$ = $1*$3;} 
| expr DIVIDE expr {if($3 == 0) yyerror("divide by zero"); 
       else $$ = $1/$3;} 
|expr ASSIGN expr 
| NUMBER 
| IDENTIFIER  
; 

這裏是輸出文件的一部分,告訴我什麼是錯的。

state 60 

28 expr: expr . ADD expr 
29  | expr . MULT expr 
30  | expr . MINUS expr 
31  | expr . DIVIDE expr 
32  | expr . ASSIGN expr 
32  | expr ASSIGN expr . 

ASSIGN shift, and go to state 36 
ADD  shift, and go to state 37 
MINUS shift, and go to state 38 
MULT shift, and go to state 39 
DIVIDE shift, and go to state 40 

ASSIGN [reduce using rule 32 (expr)] 
ADD  [reduce using rule 32 (expr)] 
MINUS [reduce using rule 32 (expr)] 
MULT  [reduce using rule 32 (expr)] 
DIVIDE [reduce using rule 32 (expr)] 
$default reduce using rule 32 (expr) 

我不明白,爲什麼會選擇第32條時,它讀取ADD,MULT,DIVIDE或其他令牌?這部分語法有什麼問題?

此外,即使上面的語法部分是錯誤的,我的編譯器是否不能正確讀取其他語法?例如,

let a = 5 

應該是可讀的,但程序返回語法錯誤?

回答

1

你的語法看起來很合理,儘管它在表達式中有不明確的地方,其中大部分都可以通過優先級來解決。你一定要看看全部報告的衝突並理解它們爲什麼會發生,並且最好改變語法來擺脫它們。

至於你的具體問題,如果你改變它有statement: ';' ;,它應該接受。你沒有顯示任何你的lexing代碼,所以問題可能在那裏。編譯解析器-DYYDEBUG=1以啓用yacc/bison生成的調試代碼,並在調用yyparse之前將全局變量yydebug設置爲1,這可能會有助於轉儲解析器對stderr所做的所有操作。

+0

爲什麼我必須在最後添加另一個報價?另外,在我的lex代碼中,我可以讀取令牌並將其返回,所以我認爲它現在可以工作。並感謝您的調試提示! – ThunderBalls