我正在尝试使用flex和bison创建一个非常基本的计算器。我是这里的菜鸟。因此,我创建了两个文件s1.l和s1.y。当我一起编译但出现错误时。这是我的代码。
********** s1.l *********
/* Simple scanner in flex */
%{
# include "s1.tab.h"
%}
%%
"+" { return ADD; }
"-" { return SUB; }
"*" { return MUL; }
"/" { return DIV; }
"|" { return ABS; }
[0-9]+ { yylval = atoi(yytext); return NUMBER; }
\n { return EOL; }
[ \t] { }
. { printf("Mystery character %c\n", *yytext); }
%%
int main(int argc, char *argv[] ) {
while(yylex());
return 0;
}
int yywrap() {
return 1;
}
***** s1.y ******
%{
#include <stdio.h>
%}
/* declare tokens */
%token NUMBER
%token ADD SUB MUL DIV ABS
%token EOL
%%
calclist:
| calclist exp EOL { printf("= %d\n", $1); }
;
exp:
| exp ADD factor { $$ = $1 + $3; }
| exp SUB factor { $$ = $1 - $3; }
;
factor:
| factor MUL term { $$ = $1 * $3; }
| factor DIV term { $$ = $1 / $3; }
;
term:
| ABS term { $$ = $2 >= 0? $2 : - $2; }
;
%%
main(int argc, char **argv)
{
yyparse();
}
yyerror(char *s)
{
fprintf(stderr, "error: %s\n", s);
}
我希望它可以用作简单的计算器,但是会产生如下错误:
satan@satan-GL63-8RC:~/Desktop/LEX$ bison -d s1.y
satan@satan-GL63-8RC:~/Desktop/LEX$ flex s1.l
satan@satan-GL63-8RC:~/Desktop/LEX$ gcc -o $@ s1.tab.c lex.yy.c
/tmp/cc85iL7m.o: In function `yylex':
lex.yy.c:(.text+0x31b): undefined reference to `yylval'
collect2: error: ld returned 1 exit status
satan@satan-GL63-8RC:~/Desktop/LEX$
我也很抱歉格式化不正确。我是这个平台的新手。
答案 0 :(得分:1)
一个问题是您的编译命令:
gcc -o $@ s1.tab.c lex.yy.c
我想您是从某些Makefile或其他文件中复制出来的,但是它肯定不能用作shell命令。在bash(或任何其他shell)中,$@
的意思是“ shell脚本的参数”,并且由于您是在控制台而不是shell脚本中工作,因此很可能没有参数,并且$@
为空。因此,替换后,该命令将显示为:
gcc -o s1.tab.c lex.yy.c
也就是说,它要求编译器编译flex生成的文件,并将生成的可执行文件放入s1.tab.c
中,从而覆盖bison生成的文件。由于仅编译扫描程序,因此找不到yylval
(它已在解析器中定义)。另一方面,该解析器从未编译过,这一事实使您摆脱了您可能会遇到的另一个问题:两个文件都包含main()
的定义。但是,只允许一个可执行文件具有一个main()
的定义。 (实际上,它只能对任何外部符号进行一个定义,但是main()
尤其重要。)
最后,如图所示,因为第二行和第四行(%{
和%}
)前面有空格字符,因此弹性文件s1.l将不会产生正确的结果。这些标记必须出现在行的开头,并且不能包含其他尾随字符。序言中带有空格的文本将逐字复制到生成的解析器中,并且gcc在读取%{
时肯定会产生语法错误。因此,我认为问题中显示的文件与您使用的文件不完全相同。