Chapter 4: Generated files

Flexc++ generates four files from a well-formed input file:

The first file, lex.cc contains lookup tables, the code to walk through the lookup tables and the actions specified in the lexer file. Since the lookup tables and actions (possibly) change every time flexc++ is called, lex.cc is rewritten at each new flexc++ run.

The file Scannerbase.h contains the Scanner's base class The Scanner class is derived from ScannerBase. The Scannerbase.h is `owned' by flexc++, and flexc++ reqrites Scannerbase.h at each new flexc++ run.

The other two files Scanner.h and Scanner.ih are created only once, and can safely be edited by the programmer. The Scanner.h header file contains the final Scanner class, to which new members may be added. These members may be called from the actions defined in flexc++'s input file (lexer).

Finally, Scanner.ih contains declarations which are used by the implementations of the Scanner members. One can place using statements here as well as includes which are only required by member implementations. In a well-designed classq, source files defining new members of the class Scanner should only have to include Scanner.ih.

4.1: Multiple input streams

Some scanners (such as those which support `include' files) require reading from several input streams. Usually, a directive like #include is defined controlling stack-wise stream switching. Alternatively, direct switches to other streams can be requested. Flexc++ offers both ways to switch streams.

The members void pushStream(std::istream &curStream) and void pushStream(std::string const &curName) are provided for stack-wise stream switching. By default, at a stream's end-of-file the member bool popStream() is automatically called by flexc++, closing the currently processed input stream and continuing the processing of the most recently stacked input stream (removing it from the stack of streams). If this switch was successfully performed true is returned. Otherwise (e.g., when the stream stack is empty) false is returned. If the stream to switch to does not exist a std::exception is thrown. An exception is also thrown when files are recursively pushed.

Returning to the previously stacked stream is handled automatically and does not require the use of an <<EOF>> rule. If an <<EOF>> rule is defined, however, previously pushed streams are not automatically re-activated. In that case, returning to previously pushed streams is the responsibility of the programmer. After completely processing the first input file the member lex returns 0.

When switching to another stream the line number counter and file name are reset to, respectively, 1 and the new file's name. When returning to a previously suspended (stacked) stream that stream's line number and file name are restored.

Direct, non-stack based stream switching is handled by various public support member functions of the Scanner class (actually, the functions are implemented as members of the ScannerBase base class):

When switching streams using the above input-stream switching members processing of the current input file ends, and continues at the file or stream specified when calling these members.