プログラミングユーティリティ

任意値型のサポート

デフォルトでは、アクションと字句アナライザによって返される値は整数です。yacc は、構造体などの他の型の値もサポートできます。また、生成されるパーサーの型を厳密に検査するために、yacc は型を監視して、適切な共用体のメンバー名を挿入します。yacc の値スタックは、必要なさまざまな型の値の共用体として宣言されます。共用体を宣言したら、値を持った各トークンと非終端記号に共用体のメンバー名を関連付けます。$$ または $n 構成によって値が参照されると、yacc は、不要な変換が起きないように、適切な共用体の名前を自動的に挿入します。

これには 3 つのメカニズムが用意されています。1 つ目は、共用体を定義する方法です。他のサブルーチン (特に、字句アナライザ) は共用体のメンバー名を知る必要があるので、この定義はユーザーが行わなければなりません。2 つ目は、共用体のメンバー名をトークンと非終端記号に関連づける方法です。3 つ目は、yacc が容易に型を判定できないごく少数の値の型を表すメカニズムです。

共用体を宣言するには、以下の記述を宣言セクションに加えます。

%union 
{ 
     共用体の本体 
}

これにより、yacc の値スタックと外部変数 yylval および yyval は、この共用体と同じ型で宣言されます。-d オプションを付けて yacc を呼び出した場合には、共用体の宣言は y.tab.h ファイルに YYSTYPE としてコピーされます。

YYSTYPE を定義したら、共用体のメンバー名を各種の終端および非終端の名前に関連づける必要があります。以下の構文を使用して、共用体のメンバー名を指定します。

<name>

%token%left%right%nonassoc のいずれかのキーワードの後に上記の指定が続いている場合は、共用体の名前は記述されているトークンに関連付けられます。

したがって、以下のように記述すると、これら 2 つのトークンによって返された値に対する参照には、すべて共用体のメンバー名 optype がタグとして付けられます。

%left <optype> '+' '-' 

もう 1 つのキーワード %type は、共用体のメンバー名を非終端記号に関連づける際に使用します。たとえば、以下の規則を使用すれば、共用体メンバー nodetype を非終端記号 exprstat に関連づけることができます。

%type <nodetype> expr stat

これらのメカニズムでは対応しきれないケースもいくつかあります。規則のなかにアクションがある場合には、そのアクションによって返される値には型がありません。同様に、左側のコンテキスト値 (たとえば、$0 など) を参照した場合は、yacc はその型を容易に知ることができなくなります。この場合には、最初の $ の直後の <> の間に共用体のメンバー名を挿入することによって、型を強制的に参照できます。その例を以下に示します。

rule       : aaa 
           { 
                $<intval>$ = 3; 
           } 
           bbb 
           { 
                fun( $<intval>2, $<other>0 ); 
           } 
           ;

この構文には特に説明することはありませんが、このような状況は頻繁に発生します。

任意値型のサポート機能は、実際に使用されるまでは起動されません。特に %type の使用によって、これらのメカニズムは有効になります。これらの機能を使用するときには、非常に厳密な検査が行われます。

たとえば、型が定義されていないものを $n または $$ を使用して参照すると、型の診断が行われます。これらの機能を起動しない場合は、yacc の値スタックは int を保持するために使用されます。