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);

最后,yylvaly.tab.h中声明,所以你的flex文件中不需要extern int yylval;。在这种情况下,这并没有什么坏处,但是如果您更改语义值的类型(您最终可能会想要这样做),那么这一行也需要更改。最好只是消除它。