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

语法分析器如何忽略空白?解决无空格表达式语法报错问题

问题解决:Lex/Yacc计算器无法解析无空格连续减号表达式

你的问题出在没有区分一元负号(取反)和二元减号(减法),同时Lex的数字匹配规则存在歧义,导致无空格的连续减号表达式无法被正确解析。以下是具体的修复方案:

修复步骤

1. 修正Lex词法规则(lexical.l)

去掉数字规则中的负号匹配,让负号作为独立的SUB token,交给语法层处理:

/* recognize tokens for the calculator and print them out */
%{
#include"syntax.tab.h"
%}

%%
"+"    { return ADD; }
"-"    { return SUB; }
"*"    { return MUL; }
"/"    { return DIV; }
"|"    { return ABS; }
[ \t]  { /* ignore whitespace */ }
[0-9]+ { yylval = atoi(yytext); return NUMBER; } // 只匹配正整数
\n     { return EOL; }
.      { printf("Mystery character %c\n", *yytext); }
%%

2. 在Yacc语法中添加一元负号支持(syntax.y)

一元负号的优先级高于乘除,所以要在term层级添加规则,这样能正确处理-2、--3、-(4+5)这类表达式:

/* simplest version of calculator */
%{
#include <stdio.h>
%}

/* declare tokens */
%token NUMBER
%token ADD SUB MUL DIV ABS
%token EOL

%%

calclist: /* nothing */                       
 | calclist exp EOL { printf("= %d\n", $2); }
 ;

exp: factor       
 | exp ADD factor { $$ = $1 + $3; }
 | exp SUB factor { $$ = $1 - $3; }
 ;

factor: term        
 | factor MUL term { $$ = $1 * $3; }
 | factor DIV term { $$ = $1 / $3; }
 ;

term: NUMBER   
 | ABS term   { if ($2 < 0) $$ = -$2; else $$ = $2; }
 | SUB term   { $$ = -$2; } // 添加一元负号规则
;
%%
main(int argc, char **argv)
{
  yyparse();
}

yyerror(char *s)
{
  fprintf(stderr, "error: %s\n", s);
}

效果验证

修改后,以下表达式都能正常解析:

  • -2-2-2 → 计算结果为 -6
  • 2*3/6-1 → 计算结果为 0
  • --5+3 → 计算结果为 8
  • -(3+4)*2 → 计算结果为 -14

这种方案不仅解决了无空格表达式的问题,还让计算器支持更复杂的嵌套负号表达式,语法逻辑也更符合常规表达式的优先级规则。

内容的提问来源于stack exchange,提问作者Timoumi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 22:48:13