前: Token Positions, 上: Lexical
純粋な、つまり再入可能な、構文解析器を生成するために、
%pure_parserをBison宣言すると、広域変数yylvalと
yyllocを使えなくなります
(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を呼び出すべきです。