语法分析器如何忽略空白?解决无空格表达式语法报错问题
问题解决: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→ 计算结果为-62*3/6-1→ 计算结果为0--5+3→ 计算结果为8-(3+4)*2→ 计算结果为-14
这种方案不仅解决了无空格表达式的问题,还让计算器支持更复杂的嵌套负号表达式,语法逻辑也更符合常规表达式的优先级规则。
内容的提问来源于stack exchange,提问作者Timoumi
相关产品推荐
相关产品推荐

