You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Lex/Yacc实现简易计算器出现输出延迟问题求助

Lex/Yacc计算器输出延迟问题分析与解决

问题成因

  1. 语法规则无结束标记:当前Yacc语法中,statement支持无限链式扩展(如a+b+c+d),LR解析器遵循「最长匹配」原则,会持续等待更多Token,不会在输入换行时主动触发归约输出。
  2. 换行符被忽略:Lex规则直接跳过了换行符\n,未将其作为表达式结束的信号传递给解析器,导致解析器无法判断当前表达式已输入完成。

解决方法

步骤1:修改Lex代码(bas.l)

将换行符识别为独立Token,不再忽略:

%{
#include "y.tab.h"
#include <stdlib.h>
void yyerror(char *);
%}

%%
[0-9]+ {yylval=atoi(yytext);return INTEGER;}
[-+*/] {return *yytext;}
[ ]     ; // 仅忽略空格
\n      { return NEWLINE; } // 换行符作为NEWLINE Token返回
%%
int yywrap(void) {
return 1;
}

步骤2:修改Yacc代码(bas.y)

添加NEWLINE Token定义,调整语法规则让表达式以换行符(或EOF)结束时立即归约输出:

%{
#include <stdio.h>
int yylex(void);
void yyerror(char *);
%}

%token INTEGER NEWLINE // 新增NEWLINE Token定义

%%
program:
    program statement NEWLINE {printf("Answer : %d\n", $2);} // 匹配带换行的表达式
    | program statement       {printf("Answer : %d\n", $2);} // 处理最后一行无换行的EOF场景
    | /* 空规则,匹配初始状态 */
    ;
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;
}

效果验证

修改后输入:

54+1
25-54

会立即输出:

Answer : 55
Answer : -29

每输入一行表达式并回车,解析器就会触发归约并输出结果,彻底解决延迟问题。

内容的提问来源于stack exchange,提问作者Ku-hello

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 13:45:26