在这个文件运行野牛:
%{
#include <iostream>
int yylex();
void yyerror(const char*);
%}
%union
{
char name[100];
int val;
}
%token NUM ID
%right '='
%left '+' '-'
%left '*'
%%
exp : NUM {$$.val = $1.val;}
| ID {$$.val = vars[$1.name];}
| exp '+' exp {$$.val = $1.val + $3.val;}
| ID '=' exp {$$.val = vars[$1.name] = $3.val;}
;
%%
导致那种的警告:
警告:“EXP”的$$没有声明的类型。
这是什么意思?如何解决呢?
工会(%联盟)定义不意图直接使用。 相反,你需要告诉野牛该工会成员使用由表达。
这与done %TYPE指令 。
代码的固定版本是:
%{
#include <iostream>
int yylex();
void yyerror(const char*);
%}
%union
{
char name[100];
int val;
}
%token NUM ID
%right '='
%left '+' '-'
%left '*'
%type<val> exp NUM
%type<name> ID
%%
exp : NUM {$$ = $1;}
| ID {$$ = vars[$1];}
| exp '+' exp {$$ = $1 + $3;}
| ID '=' exp {$$ = vars[$1] = $3;}
;
%%
作为进一步的思考,如果你想与你的削减更明确的(如果你正在做AST annoation,这是很方便的),那么你可以让你的堆栈指针的值,然后处理类型值自己。 就像标量类型有:
struct myScalar {
union {
int num;
char *id;
char *float_lexeme;
}payload;
enum {
TYPE_NUM,
TYPE_IDENTIFIER,
TYPE_FLOAT_CHAR
} type;
char *orig_lexeme;
};
并且拥有一个typedef和scalar_val *val
堆栈。
当你移动到更复杂的编译器前端,它可以帮助你建立AST这样,这样当你遍历树你有更好的元数据,你也可以增加与翻译前的语义类型转换。 然后把它归结为你的叶子制作,例如ID为语义洗牌到右侧标有效载荷。
不是一个完整的解释,但你的想法。
希望这有助于你未来的野牛/莱克斯前端和...
祝好运