lex 和 yacc 中的简单计算器程序不提供输出
Simple calculator program in lex and yacc not giving output
我正在尝试使用 lex 和 yacc 编写一个非常简单的计算器程序,但在打印输出时卡住了。这些文件是:
calc.l:
%{
#include "y.tab.h"
extern int yylval;
%}
%%
[0-9]+ {yylval = atoi(yytext); return NUMBER;}
[ \t] ;
\n return 0;
. return yytext[0];
%%
calc.y:
%{
#include <stdio.h>
void yyerror(char const *s) {
fprintf(stderr, "%s\n", s);
}
%}
%token NAME NUMBER
%%
statement: NAME '=' expression
| expression {printf(" =%d\n", );}
;
expression: expression '+' NUMBER {$$ = + ;}
| expression '-' NUMBER {$$ = - ;}
| NUMBER {$$ = ;}
;
我用过的命令:
flex calc.l
bison calc.y -d
gcc lex.yy.c calc.tab.c -lfl
./a.out
在 运行 最后一个命令之后,虽然程序从键盘接收输入但不打印任何内容,只是简单地终止。编译时我没有收到任何警告或错误,但它没有给出任何输出。请帮忙。
你没有main
的定义,所以会用到-lfl
中的main函数。该库用于 flex 程序,其 main
函数将调用 yylex
-- 词法扫描器 -- 直到它 returns 0.
您需要调用解析器。此外,您需要重复调用它,因为您的词法扫描器 returns 0,表示输入结束,每次它读取一个换行符。
所以你可以使用这样的东西:
int main(void) {
do {
yyparse();
} while (!feof(stdin));
return 0;
}
但是,这会暴露出一些其他问题。最令人恼火的是,您的语法不接受空输入,因此空行会触发语法错误。这肯定会发生在输入的末尾,因为 EOF 会导致 yylex
立即变为 return 0,这与空行没有区别。
此外,在解析过程中遇到的任何错误都将导致解析立即终止,使输入行的其余部分无法读取。
总的来说,扫描器通常为换行符 return 换行标记(或 \n
)更好。
除了您不需要的 main
函数外,-lfl
中唯一的东西是 yywrap
的默认定义。你可以自己定义这个函数(它只需要 return 1),或者你可以通过添加
来避免需要这个函数
%option noyywrap
到你的 flex 文件。其实我一般推荐
%option noyywrap noinput nounput
这将避免编译器警告(你没有看到,因为你在编译程序时没有提供 -Wall
,你应该这样做。)
另一个编译器警告将通过在 yyerror
定义之前添加 yylex
声明到您的 bison 输入文件来避免:
int yylex(void);
最后,yylval
在y.tab.h
中声明,所以你的flex文件中不需要extern int yylval;
。在这种情况下,这并没有什么坏处,但是如果您更改语义值的类型(您最终可能会想要这样做),那么这一行也需要更改。最好只是消除它。
我正在尝试使用 lex 和 yacc 编写一个非常简单的计算器程序,但在打印输出时卡住了。这些文件是:
calc.l:
%{
#include "y.tab.h"
extern int yylval;
%}
%%
[0-9]+ {yylval = atoi(yytext); return NUMBER;}
[ \t] ;
\n return 0;
. return yytext[0];
%%
calc.y:
%{
#include <stdio.h>
void yyerror(char const *s) {
fprintf(stderr, "%s\n", s);
}
%}
%token NAME NUMBER
%%
statement: NAME '=' expression
| expression {printf(" =%d\n", );}
;
expression: expression '+' NUMBER {$$ = + ;}
| expression '-' NUMBER {$$ = - ;}
| NUMBER {$$ = ;}
;
我用过的命令:
flex calc.l
bison calc.y -d
gcc lex.yy.c calc.tab.c -lfl
./a.out
在 运行 最后一个命令之后,虽然程序从键盘接收输入但不打印任何内容,只是简单地终止。编译时我没有收到任何警告或错误,但它没有给出任何输出。请帮忙。
你没有main
的定义,所以会用到-lfl
中的main函数。该库用于 flex 程序,其 main
函数将调用 yylex
-- 词法扫描器 -- 直到它 returns 0.
您需要调用解析器。此外,您需要重复调用它,因为您的词法扫描器 returns 0,表示输入结束,每次它读取一个换行符。
所以你可以使用这样的东西:
int main(void) {
do {
yyparse();
} while (!feof(stdin));
return 0;
}
但是,这会暴露出一些其他问题。最令人恼火的是,您的语法不接受空输入,因此空行会触发语法错误。这肯定会发生在输入的末尾,因为 EOF 会导致 yylex
立即变为 return 0,这与空行没有区别。
此外,在解析过程中遇到的任何错误都将导致解析立即终止,使输入行的其余部分无法读取。
总的来说,扫描器通常为换行符 return 换行标记(或 \n
)更好。
除了您不需要的 main
函数外,-lfl
中唯一的东西是 yywrap
的默认定义。你可以自己定义这个函数(它只需要 return 1),或者你可以通过添加
%option noyywrap
到你的 flex 文件。其实我一般推荐
%option noyywrap noinput nounput
这将避免编译器警告(你没有看到,因为你在编译程序时没有提供 -Wall
,你应该这样做。)
另一个编译器警告将通过在 yyerror
定义之前添加 yylex
声明到您的 bison 输入文件来避免:
int yylex(void);
最后,yylval
在y.tab.h
中声明,所以你的flex文件中不需要extern int yylval;
。在这种情况下,这并没有什么坏处,但是如果您更改语义值的类型(您最终可能会想要这样做),那么这一行也需要更改。最好只是消除它。