Assignment #2

CS 152
due October 13, 2005
100 points

In this Java programming exercise you are to define a Simulator class and one or more classes that extend a Code abstract class. These classes are to have methods (as described below) to simulate both parsing and execution of programs in the language generated by the simple grammar G' given below. Note that G' is very similar to, but not identical to, the grammar of Assignment #1. Once again, version 5.0 of Java is recommended.

The Simulator class is to have a method parse that takes a string and returns a representation of the code whose execution is to be simulated. Note that the only executable statements in legal programs are print statements and call statements. Your parse method should detect the errors of attempting to print a function, and attempting to call a nonfunction.

For the parse method, you may use either the parser that you used for Assignment 1 or my parser (with any needed modifications or desired improvements). The parser should behave as in Assignment 1, except as specified in this document. In particular, you needn't print any symbol tables, you need not use an explicit type, and you are to use the new grammar G' rather than the old grammar G. Also, you should still use the representation of addresses as offset pairs.

The parse method is to return an object of a class that extends the abstract Code class, which is available from the class web site. This class has an abstract execute method. You may define more than one class that extends Code, although they will all have to redefine execute (and they should all redefine toString). When executing the print statement, you should always print on a new line. Execution should not fail for code constructed by the parse method. Note that type information can be ignored during execution (parsing should already have handled all distinctions between function types and nonfunction types).

You are free to design your own representation of Code objects, although you will need to have representations of initial values of nonfunction variables, code for nested functions, lists of functions to be called, and lists of nonfunction variables to be printed.

The grammar G' has the productions given below. The start symbol is <program>. Once again all legal programs have a nested block structure.

  <program> ::= <block>
  <block> ::= { <block-name> <declaration>* <block>* <call-statement>* <print-statement>* } 
  <call-statement> ::= call <variable-name> ;
  <print-statement> ::= print <variable-name> ;
  <declaration> ::= declare <variable-name> <type-name>  <literal> ;
  <variable-name> ::= <letter-initial-token>
  <block-name> ::= <letter-initial-token>
  <type-name> ::= <letter-initial-token>
  <literal> ::= <digit-initial-token>
Braces (and semicolons} are nonterminal symbols of G', as opposed to metasymbols. You may assume that the tokens of a program in L(G') are separated by those white space characters that satisfy the Character.isWhitespace predicate.

The nonterminal <literal> is intended to represent initial values of variables of nonfunction types. Note that since there is no assignment statement in the language of this assignment, initial values are also final values.

Your execute method should use explicit environments and frames as described in class and in the text. Recall that you are to use static scoping rather than dynamic scoping.

Your parser need not (but may) treat the entire program as a global block. You may assume that there are no predefined identifiers in the language.

You may define any additional classes and methods that you find useful. Presumably you will at least want to define an Environment class and a Frame class.

You are to test your program with the test class A2.java available from the class web site. You are to turn in both hard and soft copies of all of your code (but not A2.java or the Code interface, unless you modify one of them). You are also to turn in a hard copy of the results of your testing.