Yacc - 语句 - 语法规则

时间:2012-02-07 00:03:13

标签: grammar yacc lex context-free-grammar

我有一个小程序读取输入并将数据返回到yacc文件,我只想打印出来。 我认为我在yacc文件中没有正确理解语法规则。

我收到的是NULL值,而且有些东西没有打印,语法错误

这是输入文件:

fd
bk 100
setc
int
fd 10 rt 90

这是yacc文件:

%{

#include <ctype.h>
#include <stdio.h>

%}

%token NUMBER
%token ID
%token FD
%token BK
%token SETC
%token RT
%token INT
%%


statement :  command arg   {printf("KEYWORDS: %s\n", $1);}
           |command    {printf("OR-> %s\n", $1);}
           ;

command : FD               {$$ = $1; printf("FD-> %s\n", $1);}
     |BK              {$$ = $1;  printf("BK-> %s\n", $1);}
     |SETC            {$$ = $1;  printf("SETC-> %s\n", $1); }
     |INT             {$$ = $1;  printf("INT->  %s\n", $1);}
     |RT              {$$ = $1;  printf("RT->  %s\n", $1);}
     ;


arg : NUMBER            {$$ = $1; printf("NUMBER-> %d\n", $1);}
     ;

%%

这是lex文件:

%{

 #include "y.tab.h"
 #include "stdio.h"
 #include <stdlib.h>


%}
%%

fd                    {return FD; }
bk                    {return BK;}
setc                  {return SETC;}
[-+]?[0-9]+           { yylval = atoi(yytext); return NUMBER;}
int                   {return INT;}
rt                    {return RT;}

.                    {printf("%s\n", yytext);}

%%

这是输出:

BK-> (null)

NUMBER-> 100
KEYWORDS: (null)

syntax error

那为什么它只打印BK而不是其他?为什么我得到NULL值?为什么我有语法错误?

抱歉有3个问题

1 个答案:

答案 0 :(得分:2)

首先,你的语法只接受一个语句,所以它解析第一个语句,然后给出语法错误,因为下一个读取的东西不是EOF。尝试在statement的规则之前添加以下内容:

input: /* nothing */
     | input statement
     ;

这将让解析器在EOF

之前解析任意数量的语句(0或更多)

其次,你的词法分析器没有为关键字设置yylval,而你的解析器期望它(它在对应于关键字标记的操作中访问$1),因此它会随机垃圾。在这种情况下,它恰好是一个NULL,它传递给printf - 你很幸运它没有崩溃。

要解决这个问题,你需要在yylval中返回一些东西(也许是yytext中的字符串),但由于你还没有把它定义为其他东西,yylval只是一个int,所以不能保存一个字符串。您可以使用%union使yylval成为一个可以容纳intchar *的联合,但这仍然会给您留下巨大的内存管理问题,为字符串分配空间并释放它,如果你不希望内存泄漏。最简单的方法是在这些操作中删除对$1的引用,因为您并不真正需要它。