yacc 的输出有延迟

问题描述 投票:0回答:1

我在 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 完全陌生,所以非常感谢所有帮助。还请解释内部发生的事情,以便我知道为什么会发生这种行为。你可以假设我知道解析的理论部分,自下而上的解析,构建语法树等的减少/移位操作。

c regex yacc lex
1个回答
0
投票

因为递归

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

© www.soinside.com 2019 - 2024. All rights reserved.