TC-1 Code to Write

Be sure to read Flex and Bison documentations and tutorials, see Flex & Bison.

See the lecture notes, and read the C++ chapter of GNU Bison’s documentation. Note that the version being used for the Tiger project may differ from the latest public release, thus students should build their own documentation by running make html in the provided Bison tarball.

Pay special attention to its ‘’Complete C++ Example’’ which is very much like our set up.

Makefile.am

Include your own test suite in the tests directory, and hook it to make check.

src/parse/scantiger.ll

The scanner must be completed to read strings, identifiers, etc. and track locations.

  • If the environment variable SCAN is defined (to whatever value) Flex scanner debugging traces are enabled, i.e. set the variable yy_flex_debug to 1.

  • Strings will be stored as C++ std::string. See the following code for the basics.

    ...
    "\""        grown_string.clear(); BEGIN SC_STRING;
    
    <SC_STRING>{ /* Handling of the strings.  Initial " is eaten. */
      "\"" {
        BEGIN INITIAL;
        return TOKEN_VAL(STRING, grown_string);
      }
    ...
      \\x[0-9a-fA-F]{2}  {
        grown_string.append(1, strtol(yytext + 2, 0, 16));
      }
    ...
    }
    
  • Symbols (i.e. identifiers) must be returned as misc::symbol objects, not strings.

  • The locations are tracked. The class Location to use is produced by Bison: src/parse/location.hh.

    To track locations, adjust your scanner, use YY_USER_ACTION and the yylex prologue:

    ...
    %%
    %{
      // Everything here is run each time :code:`yylex` is *invoked*.
    %}
    
    /* The rules. */
    
    "if"    return TOKEN(IF);
    ...
    %%
    
src/parse/parsetiger.yy
  • The grammar must be complete but without actions.

  • Use %skeleton "lalr1.cc" to have Bison generate a LALR(1) parser.

  • Use %expect 0 to have Bison report conflicts are genuine errors.

  • Use the environment variable PARSE to enable parser traces, i.e. to set yydebug to 1, run:

    PARSE=1 tc foo.tig
    
  • Use %printer to implement --parse-trace support for terminals (see TC-1 Samples). For instance,

    %define api.value.type variant
    %token <int> INT "integer"
    %printer { yyo << $$; } <int>
    
src/parse/tiger-parser.cc

The class TigerParser drives the lexing and parsing of input file. Its implementation in src/parse/tiger-parser.cc is incomplete.

TigerParser acts as a bridge between the lexer, the parser and the error handling, among other things. For more information, see old/02-parser-scanner.pdf: most of what you need to know is detailed here.

lib/misc/symbol.*, lib/misc/unique.*

The class misc::symbol keeps a single copy of identifiers, see The lib/misc Directory. Its implementation in lib/misc/symbol.hxx and lib/misc/symbol.cc is incomplete. Note that running make check in lib/misc exercises lib/misc/test-symbol.cc: having this unit test pass 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 on misc::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<T0, Ts...> lacks a couple of conversion operators that you have to supply.