在此文件上运行Bison:
%{
#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;}
;
%%
Run Code Online (Sandbox Code Playgroud)
导致出现以下类型的警告:
警告:'exp'的$$没有声明的类型.
它是什么意思,我该如何解决?
Asa*_*f R 42
定义的并集(%union)不应直接使用.相反,你需要告诉Bison联盟的哪个成员被哪个表达式使用.
这是通过%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;}
;
%%
Run Code Online (Sandbox Code Playgroud)
作为进一步的想法,如果你想更明确地减少你的数量(如果你正在进行AST通知,这可能很方便)那么你可以使你的堆栈值指针然后自己处理类型值.与标量类型非常相似:
struct myScalar {
union {
int num;
char *id;
char *float_lexeme;
}payload;
enum {
TYPE_NUM,
TYPE_IDENTIFIER,
TYPE_FLOAT_CHAR
} type;
char *orig_lexeme;
};
Run Code Online (Sandbox Code Playgroud)
并有一个typedef和scalar_val *val堆栈.
当您转移到更复杂的编译器前端时,它可以帮助您构建这样的AST,这样当您遍历树时,您拥有更好的元数据,并且您还可以使用预语义类型的翻译来扩充翻译.然后它归结为你的叶片制作,如ID,将lexeme洗牌到正确的标量有效载荷.
不是一个完整的解释,但你明白了.
希望这有助于您未来的Bison/Lex前端和......
祝好运