flex provides two different ways to generate scanners for use with C++. The first way is to simply compile a scanner generated by flex using a C++ compiler instead of a C compiler. You should not encounter any compilations errors (please report any you find to the email address given in the Author section below). You can then use C++ code in your rule actions instead of C code. Note that the default input source for your scanner remains yyin , and default echoing is still done to yyout . Both of these remain `FILE *' variables and not C++ streams .
You can also use flex to generate a C++ scanner class, using the `-+' option, (or, equivalently, `%option c++'), which is automatically specified if the name of the flex executable ends in a `+', such as flex++ . When using this option, flex defaults to generating the scanner to the file `lex.yy.cc' instead of `lex.yy.c'. The generated scanner includes the header file `FlexLexer.h', which defines the interface to two C++ classes.
The first class, FlexLexer , provides an abstract base class defining the general scanner class interface. It provides the following member functions:
yytext .
yyleng .
yy_flex_debug (see the Options section above). Note that you must build the scanner using `%option debug' to include debugging information in it.
Also provided are member functions equivalent to `yy_switch_to_buffer(), yy_create_buffer()' (though the first argument is an `istream*' object pointer and not a `FILE*', `yy_flush_buffer()', `yy_delete_buffer()', and `yyrestart()' (again, the first argument is a `istream*' object pointer).
The second class defined in `FlexLexer.h' is yyFlexLexer , which is derived from FlexLexer . It defines the following additional member functions:
yyFlexLexer object using the given streams for input and output. If not specified, the streams default to cin and cout , respectively.
yyFlexLexer and want to access the member functions and variables of S inside `yylex()', then you need to use `%option yyclass="S"' to inform flex that you will be using that subclass instead of yyFlexLexer . In this case, rather than generating `yyFlexLexer::yylex()', flex generates `S::yylex()' (and also generates a dummy `yyFlexLexer::yylex()' that calls `yyFlexLexer::LexerError()' if called).
yyin to new_in (if non-nil) and yyout to new_out (ditto), deleting the previous input buffer if yyin is reassigned.
In addition, yyFlexLexer defines the following protected virtual functions which you can redefine in derived classes to tailor the scanner:
YY_INTERACTIVE . If you redefine LexerInput() and need to take different actions depending on whether or not the scanner might be scanning an interactive input source, you can test for the presence of this name via `#ifdef'.
cerr and exits.
Note that a yyFlexLexer object contains its entire scanning state. Thus you can use such objects to create reentrant scanners. You can instantiate multiple instances of the same yyFlexLexer class, and you can also combine multiple C++ scanner classes together in the same program using the `-P' option discussed above. Finally, note that the `%array' feature is not available to C++ scanner classes; you must use `%pointer' (the default).
Here is an example of a simple C++ scanner:
// An example of using the flex C++ scanner class.
%{
int mylineno = 0;
%}
string \"[^\n"]+\"
ws [ \t]+
alpha [A-Za-z]
dig [0-9]
name ({alpha}|{dig}|\$)({alpha}|{dig}|[_.\-/$])*
num1 [-+]?{dig}+\.?([eE][-+]?{dig}+)?
num2 [-+]?{dig}*\.{dig}+([eE][-+]?{dig}+)?
number {num1}|{num2}
%%
{ws} /* skip blanks and tabs */
"/*" {
int c;
while((c = yyinput()) != 0)
{
if(c == '\n')
++mylineno;
else if(c == '*')
{
if((c = yyinput()) == '/')
break;
else
unput(c);
}
}
}
{number} cout << "number " << YYText() << '\n';
\n mylineno++;
{name} cout << "name " << YYText() << '\n';
{string} cout << "string " << YYText() << '\n';
%%
Version 2.5 December 1994 44
int main( int /* argc */, char** /* argv */ )
{
FlexLexer* lexer = new yyFlexLexer;
while(lexer->yylex() != 0)
;
return 0;
}
If you want to create multiple (different) lexer classes, you use the `-P' flag (or the `prefix=' option) to rename each yyFlexLexer to some other xxFlexLexer . You then can include `<FlexLexer.h>' in your other sources once per lexer class, first renaming yyFlexLexer as follows:
#undef yyFlexLexer #define yyFlexLexer xxFlexLexer #include <FlexLexer.h> #undef yyFlexLexer #define yyFlexLexer zzFlexLexer #include <FlexLexer.h>
if, for example, you used `%option prefix="xx"' for one of your scanners and `%option prefix="zz"' for the other.
IMPORTANT: the present form of the scanning class is experimental and may change considerably between major releases.