我在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;
}
我
%{
#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完全陌生,所以非常感谢所有的帮助。请解释一下内部发生了什么,这样我就知道为什么会发生这样的行为。你可以假设我知道解析的理论部分,自下而上的解析,构建语法树的reduce/shift操作等。
1条答案
按热度按时间mnemlml81#
你的lexer忽略了白色字符。在空格的情况下这是可以的,但是parser也不会得到任何关于Enter键的信息。结果,你得到了一个完全不受白色字符影响的解析器。例如,你可以将一个语句分成多行,它仍然可以工作。
这本身并不坏,但解析器在看到下一个语句(或EOF)的至少一部分之前,无法知道上一个语句已经结束,下一个语句已经开始。毕竟,你可以这样写:
正确的结果是
17
,如果只解析第一行就返回12
,那是不正确的。要解决这个问题,你必须引入一些字符来标记语句的结束(例如
;
),或者停止在语法中忽略\n
。我会选择第二种解决方案。
在解析器中添加一个新的token
ENTER
,并更改规则program
,使其只在看到语句时结束:在lexer中,停止忽略
\n
并返回标记ENTER
: