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

如何在Flex&Bison中区分词法与语法错误并优先输出词法错误

解决Flex+Bison同时输出词法/语法错误的问题

要实现仅输出词法错误、屏蔽后续语法错误的效果,核心思路是在词法错误发生时立即终止语法分析流程,并让Bison的错误处理函数跳过语法错误输出。以下是具体实现步骤:

1. Flex端修改:捕获词法错误并标记终止

在Flex代码中,添加全局错误标志,在匹配到非法字符时:

  • 输出词法错误信息
  • 设置错误标志位
  • 清空当前输入缓冲区(yyclearin)
  • 返回终止信号(return 0),让Bison停止语法分析

示例Flex代码(calc.l):

%{
#include "calc.tab.h"
#include <stdio.h>
// 全局标志:标记是否发生词法错误
int lex_error = 0;
%}

%%
[0-9]+          { yylval = atoi(yytext); return NUMBER; }
[+-]            { return *yytext; }
[ \t\n]         ; // 忽略空白字符
.               {
                    fprintf(stderr, "Lexical error: invalid character '%c'\n", *yytext);
                    lex_error = 1;
                    yyclearin; // 清空当前未处理的输入
                    return 0; // 终止词法分析,通知Bison输入结束
                }
%%

int yywrap() { return 1; }

2. Bison端修改:过滤语法错误输出

在Bison代码中:

  • 引入全局错误标志
  • 重写yyerror函数,仅当未发生词法错误时输出语法错误
  • 可选:在主函数中根据错误标志返回对应状态

示例Bison代码(calc.y):

%{
#include <stdio.h>
// 声明Flex中定义的全局错误标志
extern int lex_error;
%}

%token NUMBER
%left '+' '-'

%%
input: /* 空规则 */
     | input expr '\n'   { printf("Result: %d\n", $2); }
     ;

expr: NUMBER
    | expr '+' expr      { $$ = $1 + $3; }
    | expr '-' expr      { $$ = $1 - $3; }
    ;
%%

void yyerror(const char *msg) {
    // 仅当无词法错误时,才输出语法错误信息
    if (!lex_error) {
        fprintf(stderr, "Syntax error: %s\n", msg);
    }
}

int main() {
    int parse_ret = yyparse();
    // 如果是词法错误导致的退出,返回非0状态码
    return lex_error ? 1 : parse_ret;
}

为什么之前的yyclearin无效?

yyclearin仅能清空当前Flex输入缓冲区中未处理的字符,但不会终止Bison的语法分析流程。Bison仍会尝试基于已有的token进行错误恢复,进而触发语法错误输出。结合设置错误标志+终止词法分析的操作,才能彻底阻止后续语法错误的输出。

测试效果

输入包含词法错误的内容(比如5 + a),此时只会输出:

Lexical error: invalid character 'a'

不会再出现语法错误提示,符合需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 04:31:04