|CS 374 Compilers
Note: This work is to be done in assigned groups. Each group will submit one assignment. Although you may divide the work, both team members should be able to present/describe their partner's work upon request.
In the previous assignment, you constructed a parser to identify syntactically correct MiniJava programs. (These are not necessarily semantically correct programs, but we'll check for that in the next stage.) The output of the parser was either a ParseException or a message of success. In this assignment, you will augment your parser so that it constructs an abstract syntax tree. Whereas your parser grammar could take on many different correct forms, the abstract syntax tree representations will be identical across groups.
0. Preparation: Download this entire directory structure for this exercise. Read Chapter 4 and give special attention to Figure 4.9, the MiniJava abstract syntax specification.
1. Abstract Syntax Tree Building: Either by (1) using the Java Tree Builder (JTB) tool or (2) following the SLP examples in the Section 4.2 comments below, add to your parser the ability to construct an abstract syntax tree according to the specification of Figure 4.9. The corresponding abstract syntax tree classes are given here. You may use the Java Tree Builder (JTB) tool to construct a concrete syntax tree, but the final result of your semantic actions must be an abstract syntax tree according to Figure 4.9. If you are unsure, I would recommend adding semantic actions manually according to the SLP examples below.
2. Testing: You'll be using the
example MiniJava programs
for your testing. Two visitor classes are given for testing purposes, and
each can be used within Main.java in order to give different test output.
PrettyPrintVisitor takes the abstract syntax tree and prints the
corresponding MiniJava code. Correct outputs are given
here and can be compared to
your output using the Unix command "diff".
ASTPrintVisitor (perhaps more aptly called UglyPrintVisitor) prints an
abstract syntax tree in the form Node(Subnode(...), ..., Subnode(...)) with
occasional line breaks. The correct output from this visitor can be found
here. Note that all
of these are in the directory tree in (0) above.
(These comments are to supplement your reading. Question(s) asked are for you to think about on your own and need not be turned in with the homework.)
4.0: Since we're using JavaCC, a recursive descent parser, take special note of semantic actions in the sections to come.
4.1: The values we'll be returning from semantic actions will be parts of abstract syntax trees. Think back on the first assignment with the trees built by nested constructors. The recursive descent parser operates by recursively calling production parsing functions down through the parse tree. What is passed back upwards is the recursively constructed abstract syntax tree. At each level of the parsing, the parser calls for abstract syntax subtrees, and uses these to construct and return their parent abstract syntax subtree. If you've never had an appreciation for recursive thinking, you'll gain it here.
4.2: The Java Tree Builder (JTB) tool mentioned at the end of the previous section automatically adds semantic actions to a JavaCC grammar in order to construct what this section refers to as a concrete syntax tree. That is, the tree has the exact same structure as the grammar. There will likely be significant differences between your grammar and the desired target abstract syntax tree specified in Figure 4.9. This does not mean you should disregard such tools. Building abstract syntax trees is tedious, and if the concrete syntax tree closely resembles the desired abstract syntax tree, it may be wise to automate the construction of the abstract syntax tree (and its associated classes and visitors), and then write the small amount of code (and additional classes), to modify the tree to its desired form.
Here, we have an example of a straight-line program interpreter constructed using JTB.
$ jtb SLPParser.jj $ javacc jtb.out.jj $ javac *.java $ java SLPInterpreter < <input program>Compare this with a similar straight-line program interpreter which was constructed by hand in the same style. The creation of abstract syntax tree classes is tedious. However, there are often fewer classes which are easier to understand. A good general rule of thumb for deciding whether to (A) use a concrete syntax tree generated by a tool such as JTB, or (B) create abstract syntax tree and visitor classes by hand, is to consider how close the two are in form. The farther the concrete form is from the abstract, the more difficult the code will be to understand and maintain, and more effort will be expended in writing visitor classes. Which is the best approach for the MiniJava project?
4.3: The visitor pattern is an important concept to understand and apply in the stages to come. In the first assignment, one student expressed considerable irritation at having to write maxargs and interp code across many different classes, explaining that it was hard to follow/debug the code across so many different files. The visitor pattern addresses this issue. If our classes are largely fixed (in abstract syntax form), and we wish to add code for various tasks on this tree, it would be desirable to organize all code for each task in a separate class of its own. One way of doing this would involve a large recursive method with a big if-else chain making extensive use of the "instanceof" operator. The visitor pattern more elegantly makes use of Java's polymorphic method calling mechanism. Study Program 4.7 and 4.8 carefully, and also study this straight-line program interpreter visitor.
The abstract syntax tree for MiniJava is given in Figure 4.9. Your main task for this stage is to figure out how to build this tree by adding semantic actions (Java code) to your JavaCC grammar. We will begin this exercise together in class and use the following process for each production:
Don't be concerned if you lack a firm grasp on the material after reading. While the reading is important preparation, most of your learning will come through examples and exercise. You'll receive significant guidance in beginning this phase, and with the use of visitors in the next phase.