我正在构建资产xchange格式的解析器。我在bison文件中包含%token-table指令,但是从flex代码我无法访问表或与之关联的常量。那是在尝试编译这段代码时:
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;
}
}
gcc说YYNTOKENS和yytname都是未宣布的。那么令牌表最终被弃用和擦除了或者交易是什么?
答案 0 :(得分:1)
Bison 2.6.2手册(PDF中的p82):
%token-table
[指令]在解析器实现文件中生成一个令牌名称数组。的名字 数组是
yytname
;yytname[i]
是其内部Bison令牌的令牌名称 代码是i
。 yytname的前三个元素对应于预定义的 令牌“$end
”,“error
”和“$undefined
”;在这些之后出现了符号 语法文件。表中的名称包含表示令牌所需的所有字符 野牛。对于单字符文字和文字字符串,这包括周围 引用字符和任何转义序列。例如,野牛单字符 文字
’+’
对应于三个字符的名称,在C中表示为"’+’"
;和 Bison双字符文字字符串"\\/"
对应于五个字符的名称, 在C中表示为"\"\\\\/\""
。当您指定%token-table时,Bison还会为宏生成宏定义
YYNTOKENS
,YYNNTS
,YYNRULES
和YYNSTATES
:
YYNTOKENS
最高的令牌号,再加上一个。
YYNNTS
非终结符号的数量。
YYNRULES
语法规则的数量,
YYNSTATES
解析器状态的数量(参见章节5.5 [分析器状态],第104页)。
看起来它应该在那里。
当我尝试一个简单的语法时,表格存在:
#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
这可确保定义令牌表。
答案 1 :(得分:1)
围绕'静态'问题有一种快速简便的方法。我试图用我的C到6502编译器打印一个人类可读的抽象语法树,其中包含每个非终端的字符串表示。这就是我做的......
在上一节的.y文件中,创建一个名为token_table的非静态变量
%%
#include <stdio.h>
extern char yytext[];
extern int column;
const char ** token_table;
...
现在,在调用yyparse的main方法中,将yytname指定给token_table
int main(int argc, char ** argv) {
FILE * myfile;
yydebug = 1;
token_table = yytname;
...
现在,只需将其声明为extern,就可以在任何编译单元中访问token_table,如:
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_table(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 = y.tab.h选项运行bison):
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
DOWHILE = 258,
UAND = 259,
UMULT = 260,
...
答案 2 :(得分:0)
避免静态符号问题的最简单方法是直接在野牛输入文件的第三部分#include
词法分析器:
/* token declarations and such */
%%
/* grammar rules */
%%
#include "lex.yy.c"
int main() {
/* the main routine that calls yyparse */
}
然后你只需要编译.tab.c文件,这就是你所需要的。