Flex 2.5では、 Flexに対するC++インターフェイスが提供されています。
FlexのC++インターフェイスを使うためには、 Flex実行時に‘-+’オプションを指定するか、 スキャナ定義ファイルの中で‘%option c++’を指定する必要があります。 これにより、 C++のスキャナ・クラスを実装するlex.yy.ccというファイルが生成されます。
lex.yy.ccは、
Flexが提供するFlexLexer.hをインクルードします。
このFlexLexer.hの中に、
C++スキャナ・クラスの実装に利用される2つのC++クラス
(FlexLexer
とyyFlexLexer
)
が定義されています。
FlexLexer
は、
C++スキャナ・クラスが実装すべきインターフェイスを構成する抽象仮想関数を定義するクラスです。
FlexLexer
の持つメンバを以下に示します。
次に、
FlexLexer
の持つメンバ関数のうち、
抽象仮想関数ではないものを以下に示します。
const char* YYText()
yytext
の値を返します。
int YYLeng()
yyleng
の値を返します。
int yylex(istream*
new_in, ostream*
new_out = 0)
switch_streams()
を呼び出した後、
メンバ関数int yylex(void)
を呼び出します。
int lineno() const
yylineno
の値を返します。
int debug() const
yy_flex_debug
の値を返します。
void set_debug(int
flag)
yy_flex_debug
に代入します。
次に、
FlexLexer
の持つ抽象仮想メンバ関数を列挙します。
void yy_switch_to_buffer(struct yy_buffer_state* new_buffer) struct yy_buffer_state* yy_create_buffer(istream* s, int size) void yy_delete_buffer(struct yy_buffer_state* b) void yyrestart(istream* s) int yylex() void switch_streams(istream* new_in = 0, ostream* new_out = 0)
最初の5つのメンバ関数は、
FlexのCインターフェイスにおける同名の関数と同等の機能を実現します。
Cインターフェイスでは、
FILE*
となっていた引数の型が、
istream*
となっている点に注意してください。
最後のswitch_streams()
は、
入出力ストリームの切り替えを行います。
これらの抽象仮想メンバ関数の定義は、
サブクラスyyFlexLexer
において与えられ、
そのコードはlex.yy.ccの中に生成されます。
yyFlexLexer
は、
FlexLexer
のサブクラスです。
デフォルトの状態では、
yyFlexLexer
のインスタンスを生成して、
yylex()
メンバ関数を呼び出すことによって、
スキャナの処理が実行されます。
以下に例を示します。
int main( int /* argc */, char** /* argv */ ) { FlexLexer* lexer = new yyFlexLexer; while(lexer->yylex() != 0) ; return 0; }
これは、 Cインターフェイスにおける、 以下のコードに対応します。
int main( int /* argc */, char** /* argv */ ) { yylex(); return 0; }
スキャナ定義ファイルの中に‘%option yyclass="classname"’を指定すると、
lex.yy.ccにclassname::yylex()
が生成されます。
クラスclassnameをyyFlexLexer
のサブクラスとして定義することによって、
classnameのインスタンスを使ってスキャン処理を実行することができます。
クラスclassnameを定義する際、
以下に示す、
yyFlexLexer
の持つprotected
メンバ関数を再定義することによって、
スキャナの振る舞いを変更することができます。
int LexerInput(char*
buf, int
max_size)
#ifdef YY_INTERACTIVE
を使います。
void LexerOutput(const char*
buf, int
size)
void LexerError(const char*
msg)
スキャン処理に関わるすべてのコンテキスト情報は、
yyFlexLexer
のインスタンスの内部に閉じています。
このことは、
C++スキャナ・クラスを使うことによって、
再入可能なスキャナを生成することが可能であることを意味しています。
複数のC++スキャナ・クラスを生成して、
1つの実行プログラムにリンクすることも可能です。
これを行うには、
Flex起動時に‘-Pprefix’オプションを指定するか、
スキャナ定義ファイルの中に‘%option prefix="prefix"’を指定することによって、
yyFlexLexer
の名前を‘prefixFlexLexer’に変更します。
prefixFlexLexer
クラスを使うソース・ファイルの中では、
以下のようにしてFlexLexer.hをインクルードすることによって、
prefixFlexLexer
(実際にはyyFlexLexer
)
の定義を参照する必要があります。
#undef yyFlexLexer #define yyFlexLexer prefixFlexLexer #include <FlexLexer.h>