我有一个flex生成的扫描器,输出来自yacc或bison。 yylex()需要返回一个指向类似于令牌的结构内存的指针,而不是指示令牌类型的int。
// example definition from foo.l
[A-Za-z_][A-Za-z0-9_]* { return scanner_token(T_IDENTIFIER); }
// example implementation of scanner_token
token *scanner_token(name) {
token *t = (token *)calloc(1, sizeof(token));
t->name = name;
t->lexeme = (char *)calloc(yyleng + 1, 1);
if (t->lexeme == NULL) {
perror_exit("calloc");
}
memmove(t->lexeme, yytext, yyleng);
return t;
}
// example invocation of yylex
token *t;
t = (token *)yylex();
当然,编译警告我 return会在没有强制转换的情况下从指针生成整数。
我在flex手册页中读到YY_DECL
控制如何声明扫描例程:
YY_DECL
控制扫描方式 例程被宣布。默认情况下,它 是“int yylex()
”,或者,如果 正在使用原型,“int yylex(void)
”。这个定义可能是 通过重新定义“YY_DECL
”而改变 宏。
当我尝试重新定义YY_DECL
时,生成的C文件无法编译。
#undef YY_DECL
#define YY_DECL (token *)yylex()
完成我想要的东西的正确方法是什么?
答案 0 :(得分:8)
正常的语法是:
#define YY_DECL token *yylex(void)
这个最小的Flex源文件显示了:
%{
typedef struct token { int tok; } token;
#define YY_DECL token *yylex(void)
token t;
%}
%%
. { t.tok = 1; return &t; }
%%
它为我编译。
答案 1 :(得分:3)
yylex应该返回一个int。保持此行为,并在辅助函数中包装对它的调用。助手返回您的令牌。不要乱用YY_DECL。
[A-Za-z_][A-Za-z0-9_]* { return T_IDENTIFIER; }
token *scanner_token() {
token *t;
int name;
if ((name = yylex()) == 0)
return 0;
else {
t = (token *)calloc(1, sizeof(token));
t->name = name;
t->lexeme = (char *)calloc(yyleng + 1, 1);
if (t->lexeme == NULL)
perror_exit("calloc");
memmove(t->lexeme, yytext, yyleng);
return t;
}
}
token *t = scanner_token();