我有一个小程序读取输入并将数据返回到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个问题
答案 0 :(得分:2)
首先,你的语法只接受一个语句,所以它解析第一个语句,然后给出语法错误,因为下一个读取的东西不是EOF。尝试在statement
的规则之前添加以下内容:
input: /* nothing */
| input statement
;
这将让解析器在EOF
之前解析任意数量的语句(0或更多)其次,你的词法分析器没有为关键字设置yylval,而你的解析器期望它(它在对应于关键字标记的操作中访问$1
),因此它会随机垃圾。在这种情况下,它恰好是一个NULL,它传递给printf - 你很幸运它没有崩溃。
要解决这个问题,你需要在yylval中返回一些东西(也许是yytext中的字符串),但由于你还没有把它定义为其他东西,yylval只是一个int,所以不能保存一个字符串。您可以使用%union
使yylval成为一个可以容纳int
或char *
的联合,但这仍然会给您留下巨大的内存管理问题,为字符串分配空间并释放它,如果你不希望内存泄漏。最简单的方法是在这些操作中删除对$1
的引用,因为您并不真正需要它。