Decaf

PA3: 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.

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 AST, rooted in an ASTProgram object. This function represents the root non-terminal 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.

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:1]
  Function: add : int (x:int, y:int)  [add.decaf:1:1]
    Block  [add.decaf:2:1]
      Return  [add.decaf:3:5]
        BinaryExpr: +  [add.decaf:3:14]
          Location: x  [add.decaf:3:12]
          Location: y  [add.decaf:3:16]
  Function: main : int ()  [add.decaf:6:1]
    Block  [add.decaf:7:1]
      Variable: a : int  [add.decaf:8:5]
      Assignment: a = 3  [add.decaf:9:5]
        Location: a  [add.decaf:9:5]
        Literal: 3 : int  [add.decaf:9:9]
      Return  [add.decaf:10:5]
        FunctionCall: add (a, 2)  [add.decaf:10:12]
          Location: a  [add.decaf:10:16]
          Literal: 2 : int  [add.decaf:10:19]
AST for add.decaf

Reflection

One of the goals of this course is to encourage introspection and thoughtful, deliberate development processes. For this project, you will compose a short (1-2 page) reflection paper, answering the following questions:

  • How does this project fit into the overall picture of our semester-long compiler project? Why is it important?
  • Describe your design and development process. Did you use a formal software development method?
  • What aspects of this project proved to be the most rewarding?
  • What aspects of this project proved to be the most challenging? How did you overcome these challenges?
  • How do you know your submission is correct? Briefly describe your testing regimen.
  • If you had to start the project again from scratch, what would you do differently?
  • What concepts from our theoretical class material or techniques from our classroom activities did you apply in this project?
  • Suppose you weren’t using any of the concepts or techniques we’ve covered in class this semester; how would your solution to this project be different?
  • What other areas of computer science (or CS courses you’ve taken) impacted your solution to this project?
  • Do you have any other feedback about this project?

Be sure to address all of the above questions in as much detail as you wish, but do not ramble. Concise answers are preferred over verbose ones.

Submission

DUE DATE: Friday, October 16, 23:59 EDT (11:59PM)

Please submit your .java file and your reflection paper to the appropriate assignments on Canvas.

Your reflection paper should be in a standard document format: plain text and PDF are preferred, but OpenDocument and MS Word files are also acceptable.

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.

More details and due date TBD.

Grading

Here is the grading breakdown for this project:

Automated tests35
Style grading5
Reflection paper5
Peer review5
TOTAL50