Lex/Yacc实现简易计算器出现输出延迟问题求助
Lex/Yacc计算器输出延迟问题分析与解决
问题成因
- 语法规则无结束标记:当前Yacc语法中,
statement支持无限链式扩展(如a+b+c+d),LR解析器遵循「最长匹配」原则,会持续等待更多Token,不会在输入换行时主动触发归约输出。 - 换行符被忽略: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
相关产品推荐
相关产品推荐

