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

Flex/Bison中YYABORT未识别及相关编译错误求助

Flex 2.6.4 + Bison 3.8 解析器编译错误解决指南

使用Flex 2.6.4与Bison 3.8开发JavaScript子集解析器,已在Bison代码中添加%locations启用位置跟踪,但编译时出现YYLTYPE未识别、YYABORT未定义、yyerror函数隐式声明/类型冲突等错误,手动声明无效。以下是相关代码、错误信息及解决建议:

js.l 代码

%{
#include "js-parser.h"

#define YY_USER_ACTION \
    yylloc.first_line = yylloc.last_line; \
    yylloc.first_column = yylloc.last_column; \
    yylloc.last_column += yyleng; \
    if (yytext[yyleng-1] == '\n') { \
        yylloc.last_line++; \
        yylloc.last_column = 1; \
    };

void yyerror(YYLTYPE *loc, const char *s);
%}

%option yylineno

%%

"var"                                { return VAR; }
"const"                              { return CONST; }
"let"                                { return LET; }


[a-zA-Z_][a-zA-Z0-9_]*               { yylval.sval = strdup(yytext); return IDENTIFIER; }


[0-9]+(\.[0-9]*)?([eE][-+]?[0-9]+)?|\.[0-9]+([eE][-+]?[0-9]+)?    { yylval.ival = atoi(yytext); return NUMBER; }

"//"                                 { input(); while (input() != '\n'); }
"/*"                                 { do { while(input() != '*'); } while (input() != '/'); }


"+"                                  { return PLUS; }
"-"                                  { return MINUS; }
"*"                                  { return MULTIPLY; }
"/"                                  { return DIVIDE; }
"("                                  { return LPAREN; }
")"                                  { return RPAREN; }


"="                                  { return ASSIGN; }
";"                                  { return SEMICOLON; }



[ \t\n]+                             ;


.                                    { return yytext[0]; }


%%

js.y 代码

%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int yylex();
void yyerror(YYLTYPE *loc, const char *s);
int main();
%}

%locations

%union {
    int ival;
    char *sval;
};

%token <ival> IDENTIFIER
%token <ival> NUMBER

%token VAR CONST LET PLUS MINUS MULTIPLY DIVIDE LPAREN RPAREN ASSIGN SEMICOLON

%left PLUS MINUS
%left MULTIPLY DIVIDE

%right NEG

%type <ival> expr

%%

program:
    | program statement SEMICOLON
    ;

statement:
    type IDENTIFIER
    | type IDENTIFIER ASSIGN expr
    ;

type:
    VAR
    | CONST
    | LET
    ;

expr:
    NUMBER
    | IDENTIFIER
    | expr PLUS expr               { $$ = $1 + $3; }
    | expr MINUS expr              { $$ = $1 - $3; }
    | expr MULTIPLY expr           { $$ = $1 * $3; }
    | expr DIVIDE expr             { if ($3) $$ = $1 / $3; else { yyerror(@3, "division by zero"); }; }
    | LPAREN expr RPAREN           { $$ = $2; }
    | MINUS expr %prec NEG         { $$ = -$2; }
    ;

%%

void yyerror(YYLTYPE *loc, const char *s) {
    fprintf(stderr, "Error at %d: %s\n", loc->first_line, s);
    YYABORT;
};

int main() {
    printf("Use this js parser");
    yyparse();
    return 0;
};

编译错误信息

js.y:7:14: 错误:未知类型名‘YYLTYPE’
    7 | void yyerror(YYLTYPE *loc, const char *s);
      |              ^~~~~~~
js.y: 在函数‘yyparse’中:
js.y:53:117: 警告:隐式声明函数‘yyerror’;您指的是‘yyerrok’吗? [-Wimplicit-function-declaration]
   53 |     | expr DIVIDE expr             { if ($3) $$ = $1 / $3; else { yyerror(@3, "division by zero"); }; }
      |                                                                                                                     ^      
      |                                                                                                                     yyerrok
js.y: 在顶层:
js.y:60:6: 警告:‘yyerror’的类型冲突;应为‘void(YYLTYPE *, const char *)’
   60 | void yyerror(YYLTYPE *loc, const char *s) {
      |      ^~~~~~~
js.y:53:117: 附注:‘yyerror’的先前隐式声明类型为‘void(YYLTYPE *, const char *)’
   53 |     | expr DIVIDE expr             { if ($3) $$ = $1 / $3; else { yyerror(@3, "division by zero"); }; }
      |                                                                                                                     ^      
js.y: 在函数‘yyerror’中:
js.y:62:5: 错误:标签‘yyabortlab’已使用但未定义
   62 |     YYABORT;
      |     ^~~~~~~

解决建议

1. 修复YYLTYPE未定义错误

YYLTYPE是Bison生成的位置结构体,定义在Bison输出的头文件(即js-parser.h)中。需在js.y的%{ ... %}块中先包含该头文件,让编译器识别类型:

%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "js-parser.h"  // 添加此行

int yylex();
void yyerror(YYLTYPE *loc, const char *s);
int main();
%}

2. 移除yyerror中的YYABORT调用

YYABORT是Bison为yyparse函数定义的内部宏,仅能在Bison语法动作块(%%之间的代码)中使用,无法在外部yyerror函数中调用。若需错误时终止解析,可改为直接退出程序:

void yyerror(YYLTYPE *loc, const char *s) {
    fprintf(stderr, "Error at %d: %s\n", loc->first_line, s);
    exit(EXIT_FAILURE);
};

3. 解决yyerror隐式声明问题

通过提前包含js-parser.h,确保yyerror的声明在yyparse调用前被编译器识别。也可在Bison代码中添加%define api.header.include "js-parser.h",让Bison自动在生成的头文件中包含必要声明。

4. 修正语义值类型不匹配问题

js.l中IDENTIFIER的语义值赋值给yylval.sval(字符串),但js.y中声明为<ival>(整数),会导致运行时内存错误,需修正token声明:

%token <sval> IDENTIFIER  // 将<ival>改为<sval>
%token <ival> NUMBER

5. 正确编译命令

使用以下命令生成并编译代码:

# 生成解析器头文件与源码
bison -d -o js-parser.c js.y --defines=js-parser.h
# 生成词法分析器
flex -o js-scanner.c js.l
# 编译可执行文件
gcc -o js-parser js-parser.c js-scanner.c -lfl

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 13:19:57