Bison中的错误报告和令牌别名

Error reporting and token aliases in Bison

本文关键字:令牌 别名 报告 错误 Bison      更新时间:2023-10-16

好的,所以我正在试验令牌别名并面临一些问题。

让我们以我的(超简化)Bison语法的这一部分为例:

/****************************************
 Definitions
 ****************************************/
%union 
{
    char* str;
}
/****************************************
 Tokens & Types
 ****************************************/
%token <str> ID "identifier"
%token <str> NUMBER_DEC "number" 
%token <str> NUMBER_HEX "number" 
%token <str> NUMBER_BIN "number"
%token <str> NUMBER_FLOAT "number"
%type <str> identifier number
%type <str> assignment_st
%type <str> statements statement
%type <str> program
/****************************************
 Directives
 ****************************************/
%glr-parser
%locations
%start program
%define parse.error verbose
%%

/****************************************
 Grammar Rules
 ****************************************/
identifier          :   ID
                    ;
number              :   NUMBER_DEC
                    |   NUMBER_HEX
                    |   NUMBER_BIN
                    |   NUMBER_FLOAT
                    ;
assignment_st       :   identifier '=' number ';'                   { printf("assignment : %s = %sn",$identifier,$number); }
                    ;
statement           :   assignment_st
                    ;
statements          :   statement
                    |   statements statement
                    ;
program             :   statements
                    ;
%%

现在,如果我尝试a = 2;,这显然是好的语法。如果我尝试a = b;,这是一个错误,因为它期望一个数字。在这种情况下,解析器报告:

syntax error, unexpected identifier, expecting number or NUMBER_HEX or NUMBER_BIN or NUMBER_FLOAT

(好吧,"数字"别名的重复,因为它在4个令牌中使用)。

然而,我会寻找更像unexpected identifier, expected number的东西。

你会怎么做呢?

还有,我是否有可能在消息中也包含错误行?


注:我已经研究了最新的Bison文档好几个小时了,但我觉得好像我最终要构建一个…火箭,而不是修复错误信息…lol

你会怎么做呢?

我将使用单个NUMBER令牌。我看不出有任何理由让解析器关心它所查找的是哪种类型的数字字面值。

当然,有可能你的完整语法确实涉及到只允许某些格式的数字字面量的地方,尽管我对这类事情的总体倾向是"讨厌"。最可能的情况是,在某些规则中,整型常量是可以的,而浮点常量则不行。在这种情况下,除非您为浮点数提供与整数不同的别名,否则您将无法为特定的产品获得良好的错误消息。不过,总的来说,我还是坚持用"yuk"。

如果你有一个单一的数字标记类型,别名为"number",那么错误应该很好地解决。