TC-1/2-Lexer Code to Write
Be sure to read RE/flex documentation and tutorials, see RE/flex & Bison.
- Makefile.am
Include your own testsuite in the
testsdirectory. Some test examples are given in the tests folder (Given Test Cases). Do not hesitate to make use of them.Include your own test suite in the
testsdirectory, and hook it tomake check. See Generating The Test Driver.
- lib/misc/symbol.* & lib/misc/unique.*
The class
misc::symbolkeeps a single copy of identifiers, see The lib/misc Directory. Its implementation inlib/misc/symbol.hxxis incomplete. Note that runningmake checkat the root of the project will produce inlib/miscunit testing binaries. Having this unit testlib/misc/test-symbol.ccpass should be a goal by itself. As a matter of fact, unit tests were left to help you: once they pass successfully you may proceed to the rest of the compiler.misc::symbol’s implementation is based onmisc::unique, a generic class implementing the Flyweight design pattern. The definition of this class,lib/misc/unique.hxx, is also to be completed.- lib/misc/variant.*
The implementation of the class template
misc::variant<T, Ts...>lacks a couple of conversion operators that you have to supply.
- src/parse/scantiger.ll
- Specifications:
The scanner must be able to scan inputs as described in Lexical Specifications and Additional Lexical Specifications.
- What is RE/flex:
RE/flex is a C++ library used to generate lexical analyzers that can interact with Bison. Its purpose is to generate a C++ lexer class with a lex method, which can be called to initiate the lexical analysis of the input data and interact with Bison to produce a complete parser.
The file has a special syntax which is explained here.
More about RE/flex & Bison.
- What does RE/flex generate?
RE/flex generates two files
parsetiger.hhandparsetiger.cc. These files contain theparse::Lexerclass which has alexmethod that allows the lexer to be launched. Bison will use it to feed the parser with tokens.- How do I write a rule with RE/flex?
The goal of a lexer is to produce a token from an input stream. For that, RE/flex uses a Maximal Munch algorithm and thus proposes to define patterns as regex that will, when matched, create a token.
Here is an example of how to create a token from a regex to create an array token:
%% "array" return parser::make_ARRAY(td.location); "array" return TOKEN(ARRAY); // Alternatively. %%
To create the tokens in the parser you have to use the Bison functions defined for each token. They follow this pattern:
parser::make_TOKEN(...).The macro
TOKEN()allows to simplify the creation of tokens because Bison’s syntax for creating tokens is verbose.You can find out how to write a rule on the RE/flex documentation.
To have more readability on the regexes you can define them before using them as done on this example.
- RE/flex and sublexers:
To be able to lex the strings you will have to use sublexers, here is the syntax of the sublexers:
... "\"" {grown_string.clear(); start(SC_STRING);} /* Handling of the strings. Initial " is eaten. */ <SC_STRING>{ "\"" { start(INITIAL); return TOKEN_VAL(STRING, grown_string); } ... \\x[0-9a-fA-F]{2} { grown_string += strtol(text() + 2, 0, 16); } ... }
On RE/flex documentation, sublexers are called states.
Strings will be stored as C++
std::string. See the following code for the basics.Symbols (i.e. identifiers) must be returned as
misc::symbolobjects, not strings.- Metavariable:
Be careful, metavariable (Additional Lexical Specifications) keywords should only be scanned when extensions are enabled, i.e. not on direct user input.
- Trace the lexing
To keep track of lexing you can enable it using the
set_debug(true)method on the lexer or theSCANenvironment variable.- Location tracking
The locations are tracked. The class
Locationto use is produced by Bison:src/parse/location.hh.To track locations, adjust your scanner, use
YY_USER_ACTIONand thelexprologue:... %% %{ // Everything here is run each time `lex` is *invoked*. %} /* The rules. */ "if" return TOKEN(IF); ... %%