2013-01-07 20 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 ; 

这应该让你过去眼前的问题,并到一些新的:-)