can';无法访问bison 2.6中的令牌表yytname,或者它已经不存在了?
我正在为资产交换格式构建一个解析器。我在bison文件中包含了%token table指令,但是,从flex代码中,我无法访问该表或与之相关的常量。即在尝试编译此代码时:can';无法访问bison 2.6中的令牌表yytname,或者它已经不存在了?,bison,flex-lexer,Bison,Flex Lexer,我正在为资产交换格式构建一个解析器。我在bison文件中包含了%token table指令,但是,从flex代码中,我无法访问该表或与之相关的常量。即在尝试编译此代码时: Frame|FrameTransformMatrix|Mesh|MeshNormals|MeshMaterialList|Material { printf("A keyword: %s\n", yytext); yylval.charptr_type = yytext; int i; for
Frame|FrameTransformMatrix|Mesh|MeshNormals|MeshMaterialList|Material {
printf("A keyword: %s\n", yytext);
yylval.charptr_type = yytext;
int i;
for (i = 0; i < YYNTOKENS; i++)
{
if (yytname[i] != 0
&& yytname[i][0] == '"'
&& !strncmp(yytname[i] + 1, yytext, strlen(yytext))
&& yytname[i][strlen(yytext) + 1] == '"'
&& yytname[i][strlen(yytext) + 2] == 0)
return i;
}
}
框架|框架变换矩阵|网格|网格法线|网格材质列表|材质{
printf(“关键字:%s\n”,yytext);
yylval.charptr_type=yytext;
int i;
对于(i=0;i
gcc表示,YYNTOKENS和yytname都未申报。那么,代币表最终被弃用并删除了吗?或者是怎么回事?野牛2.6.2手册说(PDF第82页):
%令牌表
[指令]
在解析器实现文件中生成令牌名称数组。名称
数组是yytname
yytname[i]
是其内部野牛令牌的令牌的名称
代码编号为i
。yytname的前三个元素对应于预定义的
令牌“$end
”、“error
”和“$undefined
”;这些符号之后是在中定义的符号
语法文件
表中的名称包括表示中的令牌所需的所有字符
野牛对于单字符文字和文字字符串,这包括
引用字符和任何转义序列。例如,野牛是单一字符
literal“+”
对应一个三个字符的名称,用C表示为“+”
;和
Bison两个字符的文字字符串“\\/”
对应一个五个字符的名称,
在C中表示为“\\\\\\/\”
当您指定%token table时,Bison还会为宏生成宏定义
YYNTOKENS
,yynts
和YYNRULES
,以及YYNSTATES
:
YYNTOKENS
最高的令牌号,加上一个
yynts
非终端符号的数量
YYNRULES
语法规则的数量
YYNSTATES
解析器状态的数量(参见第104页第5.5节[解析器状态])
看起来它应该在那里
当我尝试一个简单的语法时,桌子出现了:
#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
{
"$end", "error", "$undefined", "ABSINTHE", "NESTLING", "$accept",
"anything", 0
};
#endif
注:该表为静态表;如果您试图从文件外部访问它,那将不起作用
源代码中有一个较早的小节:
/* Enabling the token table. */
#ifndef YYTOKEN_TABLE
# define YYTOKEN_TABLE 1
#endif
这确保了令牌表的定义。有一种快速简便的方法解决“静态”问题。我试图为我的C到6502编译器打印一个可读的抽象语法树,其中包含每个非终端的字符串表示。这就是我所做的 在上一节的.y文件中,创建一个名为token_table的非静态变量
%%
#include <stdio.h>
extern char yytext[];
extern int column;
const char ** token_table;
...
int main(int argc, char ** argv) {
FILE * myfile;
yydebug = 1;
token_table = yytname;
...
现在,您只需将token_表声明为extern即可访问任何编译单元中的token_表,如中所示:
extern const char ** token_table;
/* Using it later in that same compilation unit */
printf("%s", token_table[DOWHILE - 258 + 3]); /* prints "DOWHILE" */
对于AST中的每个节点,如果将y.tab.h中的yytokentype值分配给它,只需减去258,再加上3,就可以索引到token_表(yytname)中。您必须减去258 b/c,这是yytokentype开始枚举的位置,并且必须添加3 b/c yytname在表的开头添加三个保留符号($end、$error)和“$undefined”)
例如,我生成的bison文件具有:
static const char *const yytname[] =
{
"$end", "error", "$undefined", "DOWHILE", "UAND", "UMULT", "UPLUS",
"UMINUS", "UBANG", "UTILDE", "ARR", "NOOP", "MEMBER", "POSTINC",
...
以及defines头(使用--defines=y.tab.h选项运行bison):
避免静态符号问题的最简单方法是将lexer直接包含在bison输入文件的第三部分中:
/* token declarations and such */
%%
/* grammar rules */
%%
#include "lex.yy.c"
int main() {
/* the main routine that calls yyparse */
}
然后您只需编译.tab.c文件,这就是您所需要的。所以我想如果它是静态的,那么我的lexer代码需要在生成的Bison代码中?。。。医生说你可以把Flex和Bison一起使用。但通常的使用方法是让bison生成头并将其包含在flex生成器文件中。如果我错了,请纠正我:然后,如果我有单独的flex和bison文件并在以后通过gcc链接它们,我需要返回一个通用关键字标记并在flex代码中设置yylval,然后在bison中创建一个泛型产品,如果有泛型关键字,我将检索yyval以查看发生了什么?然而,如果lexer代码也在bison文件中,那么直接访问该表的唯一方法是?是的,顺便说一句,你是对的。。我检查了错误的文件(在切换到%token table之前的a.tab.c)。但是。。我想我刚刚从文档中了解到,table选项应该与Flex一起使用。Flex词法分析器通常不需要tokenname表。您需要Bison生成的
grammar.tab.h
文件或其等效文件。通常,令牌名称不一定与所分析的源代码中令牌的拼写相同。也就是说,许多语法在标记名称前面使用前缀,例如KW\u
,因此KW\u SYMBOL
可能是分析器扫描的源代码中SYMBOL
的标记。yytnames
中的名称将是KW_符号';词法分析器将查找
symbol`。
/* token declarations and such */
%%
/* grammar rules */
%%
#include "lex.yy.c"
int main() {
/* the main routine that calls yyparse */
}