CS 453 Programming Assignment #4 — MiniJava: expressions, assignments, and println

Due Wednesday March 24th (by 11:59pm)

Introduction

This assignment is to be done in groups of two or three. In this assignment you will be extending your expression evaluator from PA3 to a program interpreter and compiler, where the programs can include constant expressions, assignment statements, and println statements. The goals of this assignment are for you to learn how to

The Assignment

You should create a jar file, PA4_groupname.jar, that can be executed as follows:
   java -jar PA4_groupname.jar --two-pass-interpret input_file
   
   java -jar PA4_groupname.jar --two-pass-mips input_file
   

For the option --two-pass-interpret, your program should generate an AST that is printed to an input_file.ast.dot file and the program should be interpreted by visiting the AST.

When called with the --two-pass-mips option, the program should generate an AST that is printed to a input_file.ast.dot file, and it should generate an input_file.s file with a MIPS program that executes the program in the input file. The generated MIPS program must be capable of being interpreted by the MARS interpreter.

The input_file will contain one or more statements with the assignment of constant expressions to variables and println statements. For example, the input_file might include the following list of statements:

{
    a = 4 * 5 + 3 - (6+3);
    System.out.println(a*2);
    System.out.println(10-9-8);
    b = 42;
}
The output from the interpreter and the mips program when run should be as follows:
    28
    -7

Note that we will be treating the list of statements as a block of statements in a similar fashion to how MiniJava uses statement blocks.

The test cases from PA3 can be converted into equivalent programs with assignments and println statements by wrapping the single expression from a PA3 input file into a println statement. For example,

    4 + 5 - 9 
would become
    System.out.println( 4 + 5 - 9 );
For this assignment, no error handling is necessary. In other words, you can assume the input is correct.

Getting Started

Download the MJExprAssignStart.tar file and untar it. You should have the following files:
MJExprAssignStart
|-- TestCases
|   |-- assign1.txt
|   |-- assign1.txt.two-pass-interpret.out
|   |-- assign1.txt.two-pass-mips.out
|   |-- assign2.txt.two-pass-interpret.out
|   |-- assign2.txt.two-pass-mips.out
|   |-- expr1.txt
|   |-- expr1.txt.two-pass-interpret.out
|   |-- expr1.txt.two-pass-mips.out
|   |-- expr2.txt
|   `-- regress.csh
`-- src
    |-- ast
    |   |-- analysis
    |   |   |-- AnalysisAdapter.java
    |   |   |-- DepthFirstAdapter.java
    |   |   |-- IAnalysis.java
    |   |   `-- ReversedDepthFirstAdapter.java
    |   `-- node
    |       |-- AssignStatement.java
    |       |-- BlockStatement.java
    |       |-- IExp.java
    |       |-- IStatement.java
    |       |-- ISwitch.java
    |       |-- ISwitchable.java
    |       |-- IdExp.java
    |       |-- IntegerExp.java
    |       |-- MinusExp.java
    |       |-- MulExp.java
    |       |-- Node.java
    |       |-- PlusExp.java
    |       |-- PrintStatement.java
    |       `-- Token.java
    `-- mjparser
        |-- JLex.jar
        |-- ParseException.java
        `-- TokenValue.java

As for PA3, we have given you all of the needed AST nodes and the DepthFirstAdapter class that is capable of visiting all the AST nodes including the new nodes PrintStatement, etc.

The TestCases directory includes some test cases and an example regression script.

Suggested steps for adding assignment statements and print statements to your expression evaluator:

  1. Copy your expression evaluator to a new directory. Remove expr_eval.cup from your new Makefile, because you will no longer need two parsers unless you want to maintain a one-pass evaluator for your own debugging purposes. You will want to expand on your expr_ast.cup file from PA3.
  2. Add new tokens to lexer for the assignment operator, the semicolon, identifiers, and the print command "System.out.println". Keep in mind that we don't need to separately tokenize "System", "out", and "println", so just create one token for the whole string. See 07-lex-with-JLex.txt for some ideas on how to specify the id token and don't forget to declare the new terminals in your .cup file.
  3. Add new grammar rules for the println statement to your .cup file. For better error messages from the parser to aid with debugging include the following code in your .cup file before you declare your terminals.
    parser code {:
        public void unrecovered_syntax_error(Symbol cur_token) {
            report_fatal_error("Fatal syntax error", cur_token);
        }
    
        public void report_fatal_error(String message, Object info) {
            report_error(message, info);
            done_parsing();
            Symbol token = (Symbol)info;
            mjparser.TokenValue tok = (mjparser.TokenValue)token.value;
            throw new mjparser.ParseException("Fatal parsing error",
                                              tok.line, tok.pos);
        }
    
        public void report_error(String message, Object info) {
            Symbol token = (Symbol)info;
            mjparser.TokenValue tok = (mjparser.TokenValue)token.value;
            System.err.println("[" + tok.line + "," + tok.pos + "] "
                                   + message + " at " + tok.toString() );
        }
    :}
    
    Also put the following in the .lex file:
    %eofval{
     return new Symbol(sym.EOF, new TokenValue("EOF", yyline, yychar));
    %eofval}
    
    and make sure all of the tokens result in a TokenValue being constructed.
  4. Add actions to your .cup file to generate the PrintStatement node in the AST.
  5. Extend your evaluation/interpreter and mips code generation visitors so that they are able to handle the PrintStatement node.
  6. Fully test the println statement.
  7. Step through the same process for assignment statements. Keep in mind that we are implementing a subset of the MiniJava grammar, therefore the full MiniJava grammar that can be found online is a good reference.

Submitting the Assignment

Late Policy

Late assignments will be accepted up to 24 hours past the due date and time for a deduction of 20% and will not accepted past this period. Late means anything after 11:59pm on the day the assignment is due, including 12 midnight.


mstrout@cs.colostate.edu .... March 22, 2010