我在 bas.l 和 bas.y 中有以下 lex 和 yacc 代码。我正在尝试构建一个仅包含加法 (+)、减法 (-)、乘法 (*) 和除法 (/) 的简单计算器。 我想要它,以便可以评估包含两个以上数字(但由相同操作分隔)的每个表达式,并立即打印出答案。但是我的输出延迟了。这是代码:
bas.y
#include <stdio.h>
int yylex(void);
void yyerror(char *);
%}
%token INTEGER
%%
program:
program statement {printf("Answer : %d\n", $2);}
|
;
statement:
INTEGER {$$=$1;}
|statement '+' INTEGER {$$ = $1 + $3;}
|statement '-' INTEGER {$$ = $1 - $3;}
|statement '*' INTEGER {$$ = $1 * $3;}
|statement '/' INTEGER {$$ = $1 / $3;}
;
%%
void yyerror(char *s) {
fprintf(stderr, "%s\n", s);
}
int main(void){
yyparse();
return 0;
}
bas.l
%{
#include "y.tab.h"
#include <stdlib.h>
void yyerror(char *);
%}
%%
[0-9]+ {yylval=atoi(yytext);return INTEGER;}
[-+*/] {return *yytext;}
[ \n]
%%
int yywrap(void) {
return 1;
}
这是我给出的输入:
54+1
25-54
输出:
Answer : 55
Answer : -29
但是输出有延迟。当我给出第一行
54+1
时,我期望立即输出Answer : 55
。但我不明白,相反,扫描仪正在等待我的输入。当我输入第二个输入25-54
时,就是我得到输出Answer : 55
的时候,但我没有得到第二个输出。在此之后,当我用Control + D
(我在Mac OS上)打断时,我得到第二个输出Answer : -29
.
我期望的是在我输入后立即打印输出。我对 lex 和 yacc 完全陌生,所以非常感谢所有帮助。还请解释内部发生的事情,以便我知道为什么会发生这种行为。你可以假设我知道解析的理论部分,自下而上的解析,构建语法树等的减少/移位操作。
因为递归
program
规则的问题:
program:
program statement {printf("Answer : %d\n", $2);}
;
因为它的递归性质,递归必须在打印last语句的结果之前结束。
一个可能的解决方案是为语句列表添加一个新规则,并在其中打印每个语句后的结果:
program
: statement_list
;
statement_list
: statement {printf("Answer : %d\n", $1);}
| statement {printf("Answer : %d\n", $1);} statement_list
;
这当然可以直接在
program
规则中完成,但是左递归相当重堆栈,添加新规则可以使解析器更具前瞻性和更易于维护(IMO)。