2013-01-07 56 views
0

我有這樣的yacc文件Yacc的讀數只有第一個語法規則

%error-verbose 
%token END 
%token ID 
%token INT 
%token IF 
%token ELSE 
%token WHILE 
%token FOR 
%token BREAK 
%token CONTINUE 
%token RETURN 
%token SEM 
%token LPAR 
%token RPAR 
%token PLUS 
%token MINUS 
%token MULT 
%token DIV 
%token MOD 
%token GT 
%token LT 
%token GTE /* >= */ 
%token LTE /* <= */ 
%token EQUAL /* == */ 
%token NEQUAL /* != */ 
%token AND 
%token OR 
%token EQ 
%token COM 
%token PRINT 
%token READ 
%token FLOAT 
%token LABR 
%token RABR 
%token NUM 
%token STR 


/* 
* precedentce tabLTE 
*/ 

%right EQ PE ME TE DE RE 
%left OR 
%left AND 
%left EQUAL NEQUAL 
%left LT GT GTE LTE 
%left PLUS MINUS 
%left MULT DIV MOD 
%right PP MM 
%{ 
#include<stdio.h> 
extern char *yyname; 
extern char *yytext; 
extern int yylineno; 
void yyerror(char const *msg) 
{ 
fprintf(stderr,"%s:%d:%s\n", yyname,yylineno,msg); 

} 
%} 
%% 
program 
    : definitions 
    ; 
definitions 
    : definition 
    | definitions definition 
    ; 
definition: 
    | declaration 
    ; 
declarations 
    : /* null */ 
    | declarations declaration 
    ; 
declaration 
    : INT declarator_list SEM 
    ; 

declarator_list 
    : ID 
    | declarator_list COM ID 
    ; 
statements 
    : /* null */ 
    | statements statement 
    ; 
statement 
    : expression SEM 
    | SEM /* null statement */ 
    | if_prefix statement 
    | if_prefix statement ELSE statement 
    | loop_prefix statement 
    ; 
if_prefix 
    : IF LPAR expression RPAR 
    ; 
loop_prefix 
    : WHILE LPAR expression RPAR 
    ; 
expression 
    : binary 
    | expression COM binary 
    ; 
binary 
    : ID 
    | LPAR expression RPAR 
    | ID LPAR optional_argument_list RPAR 
    | binary PLUS binary 
    | binary MINUS binary 
    | binary MULT binary 
    | binary DIV binary 
    | binary MOD binary 
    | binary GT binary 
    | binary LT binary 
    | binary GTE binary 
    | binary LTE binary 
    | binary EQUAL binary 
    | binary NEQUAL binary 
    | binary AND binary 
    | binary OR binary 
    | ID EQ binary 
    | ID PE binary 
    | ID ME binary 
    | ID TE binary 
    | ID DE binary 
    | ID RE binary 
    ; 
optional_argument_list 
    : /* no actual arguments */ 
    | argument_list 
    ; 
argument_list 
    : binary 
    | argument_list COM binary 
    ; 

%% 

#include <stdlib.h> 
extern FILE *yyin; 
int main(int argc, char **argv) 
{ 
    int ok; 
    if (argc != 2) { 
     fprintf(stderr, "%s: Wrong arguments\n", argv[0]); 
     return EXIT_FAILURE; 
    } 
    yyname = argv[1]; 
    if ((yyin = fopen(yyname, "r")) == NULL) { 
     fprintf(stderr, "%s: %s: Invalid file\n", argv[0], argv[1]); 
     return EXIT_FAILURE; 
    } 
    return (yyparse() ? EXIT_SUCCESS : EXIT_FAILURE); 
} 

當輸入 INT X; 一切工作正常,但當輸入是「INT」 以外的東西可以說FOR FOR拋出一個錯誤: 意想不到的期待INT或$結束 所以它實際上只讀取規則集中的第一個規則。 此外,當應用bison命令時,它會一直顯示無用的非終端和終端。

這個yacc文件有什麼問題?

+0

你的「樂」到「LTE」全球編輯過猶不及用'/ * *先行tabLTE * /'(分散在3行)。 '優先'也不包含't'。 –

回答

2

麻煩的是,規則:

program 
    : definitions 
    ; 
definitions 
    : definition 
    | definitions definition 
    ; 
definition: 
    | declaration 
    ; 
declarations 
    : /* null */ 
    | declarations declaration 
    ; 
declaration 
    : INT declarator_list SEM 
    ; 

只允許通過的聲明;沒有任何東西允許statements作爲program的一部分。你的FOR不是一個聲明,所以語法會拒絕它。

的 '無用的非終端' 警告是想告訴你:

You have goofed big time; there is a bug in your grammar. You have tried to write rules for some production, but you never let it be recognized, so there was no point in adding it.

點左右...

也許你需要:

program 
    : definitions statements 
    ; 

或者,也許你需要也允許函數作爲定義,然後FOR語句將成爲函數體的一部分。

+0

感謝您的澄清,在添加語句後,使用終端/非終端的數量減少了,但它仍然期待$ end,而輸入文件中還有其他語句,如if語句,但它不會讀取這些語句。期待$ end – eMizo

+0

@doctorMizo:期望一個INT或一個$ end,而不僅僅是一個$ end。這是因爲所有的聲明都是以INT開始的,所以在看到一個聲明之後,它會期待另一個聲明或者文件的結尾 - 其他任何聲明都是語法錯誤。 –

+0

看看那些沒用的終端和非終端,並找出爲什麼它仍然抱怨它們沒用。或者消除無用的項目。 (您可以在VCS中的當前版本上添加一個標籤 - 不要告訴我您沒有使用該標籤;只需繼續使用它即可 - 然後刪除無用的內容,知道如果可以返回到當前版本/當你再次需要它們時)。令牌FOR會引起麻煩,因爲沒有規則引用它。 –

0

問我LL甲骨文有關修改語法:

Out of 15 non-terminals, 14 are reachable, 1 are unreachable: 
'declarations' 
Circular symbols: 
definitions 
definitions 

約圓形符號的投訴,「定義」可以得到自己。例如,'定義'可以產生'定義定義',但'定義'是可以空的,所以'定義'可以自己產生,很少有解析器生成器會以任何明智的方式處理無限循環。從另一個角度來看,你已經將'定義'定義爲一個可以爲空的符號列表,所以你需要匹配多少個epsilon?無窮大怎麼樣? :-)

這是yacc/bison風格的一個缺點,它試圖製作某些解析器,即使在語法中存在問題;如果你確切地知道你在做什麼,這非常方便,但是相反,這很容易混淆。

但是,對於如何處理文法循環的問題,這給你一個非常無用的(但是用口香糖編譯!)解析器。你如何讓'定義'爲空而不是'定義'? IOW:

definitions : | definitions definition ; 
definition : declaration ; 

儘量不要在可空性堆棧上空泛。所以,當你後來更改爲:

definition : declarations ; 

不要讓「聲明」可空(這已經由「定義」是可空的處理)。取而代之的是,將其更改爲:

declarations : declaration | declarations declaration ; 

這應該讓你過去眼前的問題,併到一些新的:-)