web-dev-qa-db-ja.com

yylvalとunion

Yaccファイルでの結合の目的は何ですか?フレックスファイルのyylvalに直接関係していますか? yylvalを使用しない場合は、unionを使用する必要はありませんか?

17
neuromancer

unionの目的は、flexによって発行されたノードにさまざまな種類のオブジェクトを格納できるようにすることです。

よりよく説明するために、あなたは例えば持つことができます:

%union
{
    int intValue;
    float floatValue;
    char *stringValue;
}

intfloat、およびstringタイプの基本的なサポートを提供する場合は.yで。これで何ができますか?

2つのこと:

まず、トークンを生成するときに正しい値を自動的に設定できます。前の例の.lファイルについて考えてみてください。次のことができます:

[a-zA-Z][a-zA-Z0-9]* {
 yylval.stringValue = strdup(yytext);
 return IDENTIFIER;
}

[0-9]+ { 
 yylval.intValue = atoi(yytext);
 return INTEGER;
}

[0-9]*\.[0-9]+"f"? {
    yylval.floatValue = new atof(yytext);
 return FLOAT;
}

さらに、flex grammar:で直接値を使用できます。

nexp: nexp '+' nexp { $<floatValue>$ = $<floatValue>1 + $<floatValue>3 }

最後に、OOP構文ツリーを使用する場合は、ユニオンを次のように定義できます。

%union
{
    class ASTNode *node;
}

ここで、ASTNodeはあらゆる種類の構文ノードの祖先クラスです。

26
Jack

%union宣言は、yylvalのタイプを変更します。

bisonマニュアル 説明

通常の(再入力しない)パーサーでは、トークンのセマンティック値をグローバル変数yylvalに格納する必要があります。セマンティック値に1つのデータ型のみを使用している場合、yylvalにはその型があります。したがって、タイプがint(デフォルト)の場合、これをyylexに記述できます。

...
yylval = value;  /* Put value onto Bison stack. */
return INT;      /* Return the type of the token. */
...

複数のデータ型を使用している場合、yylvalの型は%union宣言から作成された和集合です(「値型のコレクション」セクションを参照)。したがって、トークンの値を格納するときは、ユニオンの適切なメンバーを使用する必要があります。 %union宣言が次のようになっている場合:

%union {
  int intval;
  double val;
  symrec *tptr;
}

その場合、yylexのコードは次のようになります。

...
yylval.intval = value; /* Put value onto Bison stack. */
return INT;          /* Return the type of the token. */
...
14
Greg Bacon