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

Lex/Bison返回字符a提示无效令牌的问题排查

问题描述

原本开发的Lex/Bison解析器使用命名令牌规则(如Lex中a {return Tok_A;},Bison中声明%token Tok_A)时运行正常,正确输入可被接受。尝试改为直接返回字母ASCII值实现更通用的解析器,但返回字符"a"时,Bison提示无效令牌。

代码示例

parser.l

%{
#include "parser4.tab.h"
%}

%%
[a-h]    {return *yytext;}
\n   {return 0;}  /* EOF */
%%

parser.y

%{
   extern void yyerror(char *);
   extern int yylex(void);
   #define YYDEBUG 1 
 %}
 
%token a 

%%
S : a {printf("S->a");}
%%

int main(void)
{
#if YYDEBUG
  yydebug = 1;
#endif
    if(!yyparse())
        printf("End of input reached\n");
    return 0;
}

void yyerror (char *s)
{
  /* fprintf (stderr, "%s\n", s); */
  printf("Incorrect derivation!\n");
}

报错输出

输入"a"后得到:

Starting parse
Entering state 0
Stack now 0
Reading a token
a
Next token is token "invalid token" ()
Incorrect derivation!
Cleanup: discarding lookahead token "invalid token" ()
Stack now 0

用户推测问题出在Lex的return *yytext;规则上,已知Lex和Bison通过parser.tab.h通信,令牌从257开始编号,0-255对应ASCII字符,但疑惑为何直接返回"a"字符Bison无法识别。


问题原因与解决方法

核心原因

Bison中%token a声明的不是ASCII字符'a',而是一个用户自定义命名令牌,Bison会为其分配一个≥257的编号;而Lex中return *yytext;返回的是字符'a'的ASCII值(97),属于0-255的ASCII令牌范围。两者编号不匹配,导致Bison将Lex返回的ASCII值识别为无效令牌。

解决方法

有两种可行方案,根据需求选择:

方案1:直接使用ASCII字符字面量(推荐,符合通用解析需求)

去掉Bison中的%token a声明,在语法规则中用单引号包裹字符字面量,让Bison直接识别ASCII令牌:
修改后的parser.y核心部分:

%{
   extern void yyerror(char *);
   extern int yylex(void);
   #define YYDEBUG 1 
 %}
 
// 移除%token a声明
%%
S : 'a' {printf("S->a");}  // 用单引号包裹字符字面量
%%

此时Lex返回的ASCII值97(即字符'a')会被Bison正确匹配到规则中的'a',解析正常。

方案2:让Lex返回命名令牌的编号(适合需保留命名令牌的场景)

如果必须使用命名令牌,需确保Lex返回的编号与Bison定义的一致。比如在Bison中声明%token TOK_A,然后在Lex中对应返回该令牌:

  • parser.y中:%token TOK_A
  • parser.l中:a {return TOK_A;}

但这种方式不符合"通用解析器"的需求,因此方案1更合适。

补充说明

Bison的令牌编号规则:

  • 0:代表EOF(Lex返回0时触发)
  • 1-255:对应ASCII字符,可直接在语法规则中用'字符'引用
  • 257及以上:用户通过%token声明的自定义命名令牌,编号由Bison自动分配

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 08:43:25