前: Token Positions, 上: Lexical


4.2.4 再入可能構文解析器を呼び出す方法

純粋な、つまり再入可能な、構文解析器を生成するために、 %pure_parserをBison宣言すると、広域変数yylvalyyllocを使えなくなります (see A Pure (Reentrant) Parser)。 このような構文解析器では、2つの広域変数の代わりに、 yylexへの引数として渡されるポインタを使います。 yylexを次のように宣言し、 これらのポインタを通して情報を受け渡しする必要があります。

     yylex (lvalp, llocp)
          YYSTYPE *lvalp;
          YYLTYPE *llocp;
     {
       ...
       *lvalp = value;  /* 値をBisonスタックに積む。  */
       return INT;      /* トークン型を返す。 */
       ...
     }

文法ファイルがテキスト中の位置を参照するための`@'機能を 使っていない場合は、YYLTYPEは定義されません。 この場合、第2引数を省略し、yylexは 1個の引数をともなって呼び出されます。

再入可能な構文解析器を使っている場合、 再入可能な方法で構文解析器に追加の引数を渡す方法があります。 そのためには、マクロYYPARSE_PARAMを変数名として定義します。 すると、関数yyparseは、定義された名前で、型がvoid *の 追加の引数を受け取ります。

yyparseを呼び出すときに、オブジェクトの番地を void *型にキャストして渡します。 文法のアクションは、ポインタを適切な型へのポインタへキャストし、 逆参照して、オブジェクトの内容を参照できます。 例を示します。

     %{
     struct parser_control
     {
       int nastiness;
       int randomness;
     };
     
     #define YYPARSE_PARAM parm
     %}

次のように構文解析器を呼び出します。

     struct parser_control
     {
       int nastiness;
       int randomness;
     };
     
     ...
     
     {
       struct parser_control foo;
       ...  /* fooに正しいデータを記憶  */
       value = yyparse ((void *) &foo);
       ...
     }

文法アクションの中では、データを参照するために次のような式を使います。

     ((struct parser_control *) parm)->randomness

yylexに追加の引数を渡したい場合には、 YYPARSE_PARAMと同様に、マクロYYLEX_PARAMを定義します。 例を示します。

     %{
     struct parser_control
     {
       int nastiness;
       int randomness;
     };
     
     #define YYPARSE_PARAM parm
     #define YYLEX_PARAM parm
     %}

そして、yylexが追加の引数、parmの値を受け取るように、 yylexを定義する必要があります (型YYLTYPEのどの引数が渡されるかに応じて、 引数の合計が2個または3個になります)。 引数を正しいオブジェクト型として宣言できます。すなわちvoid *として 宣言し、上記の番地を参照できます。

YYPARSE_PARAMを使わずに、`%pure_parser'を使って、 再入可能な構文解析器を生成することも可能です。 その場合、引数をつけずにyyparseを呼び出すべきです。