regex yacc的输出延迟

gcuhipw9  于 2023-04-22  发布在  其他
关注(0)|答案(1)|浏览(73)

我在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操作等。

mnemlml8

mnemlml81#

你的lexer忽略了白色字符。在空格的情况下这是可以的,但是parser也不会得到任何关于Enter键的信息。结果,你得到了一个完全不受白色字符影响的解析器。例如,你可以将一个语句分成多行,它仍然可以工作。
这本身并不坏,但解析器在看到下一个语句(或EOF)的至少一部分之前,无法知道上一个语句已经结束,下一个语句已经开始。毕竟,你可以这样写:

4 * 3
+ 5

正确的结果是17,如果只解析第一行就返回12,那是不正确的。
要解决这个问题,你必须引入一些字符来标记语句的结束(例如;),或者停止在语法中忽略\n
我会选择第二种解决方案。
在解析器中添加一个新的token ENTER,并更改规则program,使其只在看到语句时结束:

%token ENTER
program:
    program statement ENTER {printf("Answer : %d\n", $2);}
    |
    ;

在lexer中,停止忽略\n并返回标记ENTER

" "    {/* do nothing */}
\n     {return ENTER;}

相关问题