このファイルで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;}
;
%%
次のような警告が表示されます。
警告: 'exp'の$$には宣言された型がありません。
それはどういう意味ですか、どうすれば解決できますか?
定義された共用体(%union)は、直接使用するためのものではありません。むしろ、組合のどのメンバーがどの式で使用されているかをバイソンに伝える必要があります。
これは %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注釈を付ける場合、これは便利です)、スタック値をポインターにして、型の値を処理できます。自分と同じです。
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などのリーフプロダクションにまとめて、語彙素を正しいスカラーペイロードにシャッフルします。
完全な説明ではありませんが、アイデアは理解できます。
これがあなたの将来のバイソン/レックスのフロントエンドに役立つことを願っています...
幸運