在野牛中有一种方法可以返回令牌的名称而不是其类型

时间:2015-09-08 02:42:59

标签: c++ c parsing bison flex-lexer

我正在与Flex和Bison合作。在我的parse.y(野牛)我定义了令牌。当令牌返回时,它返回一个int我想知道是否有办法获取该int并将其映射回bison源中的实际名称。 例如在我的parser.y

//define my tokens that are shared with my lexer (flex)
%token <tokenData> ID
%token <tokenData> NUMCONST

在我的语法中我然后使用

number : NUMCONST   {std::cout<<"Line "<<$1->linenum<<" Token: [I want NUMCONST]"<<<std::endl;}

我知道我可以显示从词法分析器返回的int但是在那里返回令牌的类型,例如&#34; NUMCONST&#34;或&#34; ID&#34;。我想要令牌&#34;输入&#34;而不是令牌&#34; int&#34;

2 个答案:

答案 0 :(得分:11)

是的,你可以,但你需要在你的野牛文件中启用该功能。

如果您将指令%token-table放入您的bison文件中,那么bison将生成一个名为yytname的令牌名称表。 (您还可以使用-k--token-table命令行标志启用此功能。)

yytname[i]是“内部野牛令牌代码编号”为i的令牌的名称。这与yylex返回的数字不同,因为bison使用名为yytranslate的(未记录的)表格对令牌进行重新编码。

如果您使用该功能,yytname表中的令牌名称是令牌别名。例如,如果您的语法包括:

%token EQEQ "=="
%%
exp: exp "==" exp
   | exp '+' exp

exp规则中显示的与两个运算符对应的标记的名称为"=="'+'

yytname还包括非终端的名称,以防您出于任何目的需要。

您可能希望使用yytranslate[t],而不是使用YYTRANSLATE(t),这是Bison生成的扫描程序本身所做的事情。该宏将超出范围的整数转换为2,其具有相应的名称$undefined。该名称还将显示在野牛语法中未使用的任何单字符标记。

bison生成的扫描程序中yytnameyytranslate都声明为static const,因此您只能在该文件中存在的代码中使用它们。如果要公开一个执行翻译的函数,可以在第二个%%之后将函数放在语法结尾中。 (例如,如果您想在扫描仪中找到与令牌编号对应的名称,则可能需要这样的功能。)它可能如下所示:

const char token_name(int t) {
  return yytname[YYTRANSLATE(t)];
}

通常,没有必要这样做。如果您只是想跟踪解析器正在做什么,那么最好启用bison的trace facility

答案 1 :(得分:1)

bison生成一个名为enum的{​​{1}},其中包含语法中所有令牌的枚举列表。它不提供与包含所有令牌名称的字符串的等效映射。

因此,您必须自己实施此映射。也就是说,实现一个带有yytokentype参数的实用程序函数,并返回给定标记的名称,您可以随后在诊断消息中使用该名称。另一个无聊的yytokentype农场。

话虽如此,编写一个实用程序switch脚本或同等程序,读取来自野牛的Perl并解析{{1}枚举和robo生成映射函数。使用合适的依赖关系规则将其粘贴到您的<filename>.tab.h中,然后您自己获得了一个令牌到名称映射函数的自动生成器。