Computer Science 301 - 2001


Tutorial for week 20 - Constraint Analysis and Symbol Tables

In class we have discussed the use of a symbol table for storing properties gleaned from the declaration of named constants and variables in Clang programs, and for checking that these have been correctly declared and used if they are referred to within statements and expressions. The relevant parts of the code (which appears in full in the source files for the book rather than the book itself) are quoted below for convenience:

     OneConst
     =                             (. TABLE_entries entry;
                                      int value; .)
        Ident<entry.name>          (. entry.idclass = TABLE_consts; .)
        "=" number ";"             (. Table->enter(entry); .) .

     OneVar
     =                             (. TABLE_entries entry; .)
                                   (. entry.idclass = TABLE_vars;
                                      entry.scalar = true; .)
        Ident<entry.name>
        [ UpperBound               (. entry.scalar = false; .)
        ]                          (. Table->enter(entry); .) .

     Assignment =  Variable ":=" Expression .

     Variable
     =                             (. TABLE_entries entry; .)
        Designator<classset(TABLE_vars), entry>.

     Designator<classset allowed, TABLE_entries &entry>
     =                             (. TABLE_alfa name;
                                      bool found; .)
        Ident<name>                (. Table->search(name, entry, found);
                                      if (!found) SemError(202);
                                      if (!allowed.memb(entry.idclass)) SemError(206);
                                      if (entry.idclass != TABLE_vars) return; .)
        ( "["                      (. if (entry.scalar) SemError(204); .)
          Expression "]"
          |                        (. if (!entry.scalar) SemError(205); .)
        ) .

     Expression =  ( "+" Term | "-" Term | Term ) { AddOp Term } .

     Term =  Factor {  MulOp Factor } .

     Factor
     =                             (. TABLE_entries entry; .)
          Designator<classset(TABLE_consts, TABLE_vars), entry>
        | number
        | "(" Expression ")" .

---------------------------------------------------------------------------------------------

            // Interface to symbol table for Clang level 1 parser (no code generation)

            const int TABLE_alfalength = 15;   // maximum length of identifiers
            typedef char TABLE_alfa[TABLE_alfalength + 1];

            enum TABLE_idclasses { TABLE_consts, TABLE_vars, TABLE_progs };

            struct TABLE_entries {
              TABLE_alfa      name;           // identifier
              TABLE_idclasses idclass;        // class
              bool            scalar;
            };

            class TABLE {
              public:
                void enter(TABLE_entries &entry);
                // Adds entry to symbol table

                void search(char *name, TABLE_entries &entry, bool &found);
                // Searches table for presence of name.  If found then returns entry

                void printtable(FILE *lst);
                // Prints symbol table for diagnostic purposes

                TABLE(REPORT *R);
                // Initializes symbol table

            };

In the similar language CS301-1, which forms the focus of the current practical, constants can be declared slightly differently, variables can be of integer or Boolean type, and the grammar for Expressions is different. How would you add attributes/actions to the corresponding parts of the grammar below to be able to exercise the same sorts of semantic constraints? Hint: This introduces the notion of "type checking" which is not present in Clang since Clang only has one type to worry about!

  ConstDeclarations = "CONST" OneConst { OneConst } .
  OneConst          = Ident "=" ( number  | "TRUE" | "FALSE" ) ";" .
  VarDeclarations   = ( "INT" | "BOOL" ) OneVar { "," OneVar } ";" .
  OneVar            = Ident [ UpperBound ] .
  Assignment        = Variable ":=" Expression .
  Variable          = Designator .
  Designator        = Ident [ "[" Expression "]" ] .
  Expression        = AndExp   { "OR" AndExp } .
  AndExp            = RelExp   { "AND" RelExp } .
  RelExp            = AddExp   [ RelOp AddExp ] .
  AddExp            = MultExp  { AddOp MultExp } .
  MultExp           = UnaryExp { MulOp UnaryExp } .
  UnaryExp          = Factor | AddOp UnaryExp | "NOT" UnaryExp .
  Factor            = Designator | number | "TRUE" | "FALSE" | "(" Expression ")" .


Home  © P.D. Terry