CSC 330 Assignment 3

Assignment 3: Some Additional Information



Implementation Details for Symbol Table Building

Add the following three declarations to the "parser code" section of your ejay.cup:

    public void initSymbolTable(int size) {
        symtab = new SymbolTable(size);
    }

    public SymbolTable getSymbolTable() {
        return symtab;
    }

    protected SymbolTable symtab;


This will support the testing program described below.

You can also add any additional methods you may find useful for calling from parser semantic actions to the "parser code" section. For example, I define symbol-table-building methods such as "enterVars" in this section. Such methods are invoked within semantic actions using the parser instance variable, e.g., parser.enterVars(...).

You will notice that the VariableEntry class has a field for the value of the variable's memory location. For Assignment 3, enter 0 for the value of the memorylocation field all variables. You should however properly set the boolean value of the isRef field, based on whether a formal parameter is declared as a ref in an EJay program. E.g., in the following EJay declaration

int f(int i, ref float x) { ... }
the variable entry for i has isRef set to false, whereas the variable entry for x has it set to true.

For FunctionEntrys, you need to assign appropriate values to all of the data fields. Specifically,

Further Testing Details

Here is the final testing program, with symbol table initialization and output steps:

import java.io.*;
import java_cup.runtime.*;

/****
 *
 * Test program for CSC 330 Assignment 3.  The main method constructs an
 * EJayLexer with a FileReader.  It then constructs an EJayParser, sending it
 * the lexer.  Then it calls EJayParser.parse and prints out the constructed
 * parse tree and symbol table.  Documentation on the form of the parse tree,
 * symbol table, and their printing are in the <a href= javadoc> javadoc </a>
 * for the TreeNode class, SymbolTable class, their extensions.
 *
 */
public class EJayParserTest {

    /**
     * See the class comment for documentation.
     */
    public static void main(String[] args) {
        TreeNode t;
        try {
            EJayParser parser = new EJayParser(
                new EJayLexer(new FileReader(args[0])));

            parser.initSymbolTable(500);
            t = (TreeNodeList) parser.parse().value;

            System.out.println(t);
            System.out.println(parser.getSymbolTable());
        }
        catch (Exception e) {
            System.out.println("Exception " + e);
            e.printStackTrace();
        }
    }

}

Some Key Differences between Pascal and EJay

The following is a list of some key differences between Pascal and EJay, to help clarify where the Pascal example does and does not apply to EJay:

  1. EJay primitive types use keywords, Pascal uses regular identifiers; e.g., "int" is a keyword in EJay, whereas "integer" as a type name in Pascal is returned by the lexer as a regular identifier.
  2. Pascal has nested procedures (functions), EJay does not. However, EJay has nested blocks, which can contain statements and declarations. Such nested blocks should be represented scopewise as anonymous inner scopes.
  3. The subset of Pascal in the example has array types, but not structs; so, you need to figure out an appropriate tree representation for struct types.
  4. In Pascal data declarations, the type comes after the variable name in the left-to-right order of the declaration. In EJay, the type comes first. This should make entering variables and formal parameters into the symbol table a bit easier in EJay than in Pascal.

Whither Information Hiding?

You should notice that all of the data fields in the parse tree and symbol table support classes are public. At a later point in 330, we may have the potentially contentious discussion about why Fisher thinks private data are an utter waste of compiler writers' valuable time. In the meantime, enjoy the freedom.