P3: Decaf Parser
Objective
The goal of our semester-long project is to gain experience in compiler implementation by constructing a simple compiler.
The goal of this part of the project is to gain experience implementing syntax analysis by implementing a recursive-descent parser as the second pass of our Decaf compiler.
Introduction
The semester-long project for this course is to build a compiler for the Decaf language. In this project, you will implement a parser for Decaf, which will be the second phase in our compiler. You will do this by transforming the given Decaf grammar into an LL(1) grammar and implementing a recursive descent parser.
Thoroughly read the Decaf grammar in the reference document. For this assignment, you will need to construct a parser that will accept a stream of tokens and return an abstract syntax tree (AST). There are various AST objects, each of which represents some construct in the Decaf grammar.
You should download the project starter files from the "Files" tab in Canvas. The starter files include many new .java files as well as .class files representing compiled solutions.
Before you begin writing code, you should spend some time reading through all of the infrastructure files provided in the starter files. Our compiler this semester is a large project. Your solution will need to interface with several other classes, and you will need to thoroughly read through those classes to understand their interactions. Also, there are utility functions that you may find useful.
As you study the code, you may find it useful to generate Javadoc
references for the existing project files. To do this, run mvn site
and then open (using a web browser) the index.html
file that is
created in the target/site/apidocs
folder.
If you have questions about the existing code, please ask them on the Piazza forum (see the link on the sidebar in Canvas).
Assignment
WARNING: You should only proceed with actual development once you are SURE you understand exactly what your task is and how your code should interact with the rest of the system.
Implement the MyDecafParser
class by providing an implementation
for the following function:
public ASTProgram parseProgram(Queue<Token> tokens) throws InvalidSyntaxException
This function takes as input a Queue
of Token
objects from the lexing phase. The function should return an abstract syntax
tree (AST), rooted in an ASTProgram
object. This function
represents the root non-terminal (i.e., start symbol) parsing routine in your
recursive descent parser.
For this particular project, you should pay special attention to the following classes:
DecafParser
- Base class for your parser. Provides some useful helper methods for manipulating the queue of tokens.ASTNode
- Abstract syntax tree (AST) base class. All other AST node objects inherit from this one.InvalidSyntaxException
- Special exception that your code should throw when you detect invalid syntax.
You will first want to make sure you understand the grammar in the Decaf reference document. Then, you will want to spend some time modifying it so that it is more useful to you for this assignment (i.e., converting it to be LL(1) with proper precedence and associativity). Then, you should begin writing your parser, using your LL(1) grammar as a guide as discussed in class and the textbook.
WARNING: This is a large project! The code you will write is not terribly complicated, but there is a lot of it because you will be writing a method for almost every non-terminal in your grammar. This is a daunting task if you have never written a parser before, so you must start early and ask questions. I suggest starting with a much-reduced form of the grammar, then gradually expanding it. Here is an example grammar that represents a small portion of the Decaf grammar, suitable for getting started on this project:
Program -> VarDecl* VarDecl -> Type IDENTIFIER ';' Type -> 'int' | 'bool'
Of course, variable declarations are more complex in real Decaf because they could be arrays. However, the above grammar does describe a complete language, and that language is a subset of the real Decaf language. Thus, it is an easier target to aim for when you first start working on the project.
NOTE: For literals, you should also parse the token text into the appropriate format. For integers, this means converting it to an actual Integer type, and for string literals this means removing the leading and trailing quotes and expanding escape codes.
Your solution should accept all valid Decaf programs, building the appropriate AST and annotating every node with source information. It should also reject all invalid Decaf programs, printing a descriptive error message about the earliest error encountered with source information.
Sample Input
def int add(int x, int y) { return x + y; } def int main() { int a; a = 3; return add(a, 2); }
Sample Output
Program [add.decaf:1] Function: add : int (x:int, y:int) [add.decaf:1] Block [add.decaf:2] Return [add.decaf:3] BinaryExpr: + [add.decaf:3] Location: x [add.decaf:3] Location: y [add.decaf:3] Function: main : int () [add.decaf:6] Block [add.decaf:7] Variable: a : int [add.decaf:8] Assignment: a = 3 [add.decaf:9] Location: a [add.decaf:9] Literal: 3 : int [add.decaf:9] Return [add.decaf:10] FunctionCall: add (a, 2) [add.decaf:10] Location: a [add.decaf:10] Literal: 2 : int [add.decaf:10]
Submission
Please submit your MyDecafParser.java
file
to the appropriate assignment on Canvas by the due date indicated there.
Code Reviews
One of the goals of this course is to encourage good software development practices, especially when building a large software system (such as a compiler). For this project, you will be assigned two other random students in the course. You must review their code and offer constructive feedback according to the given rubric.
Submit your review on Canvas by midnight a week following the original project due date.
Grading
Here is the grading breakdown for this project:
Automated tests | 80 |
Instructor review | 10 |
Peer review | 10 |
TOTAL | 100 |