HW13: Interpreter, Part I

25 points; due Fri 5/16 @ 11am.

Goals

To explore stacks and their uses, to learn some about how compilers and interpreters make sense of source code, and to get experience working with a large body of preexisting code.

Setup and Requirements

It is strongly suggested that you work on this assignment with a partner.

Download interpreter.zip and unzip it into the directory that you've created for your work on this assignment.

You're going to want to look carefully at the methods defined for the Scanner, String, and Character classes when you do Step 3 (syntax checking). Be sure to look them up in the Java documentation.

Your Tasks

Step 1: Starter Code

This assignment is structured around modifying a relatively large, pre-existing code base (from the zip file). The program expressed in the code is a virtual machine (VM) simulator for a fake programming language. The code compiles and runs, with very limited capabilities, without any initial modification. So before you try writing any code of your own, you should first verify that you’re starting from the right place.

  1. Compile the code from interpreter.zip. It should compile with no errors just as you downloaded it. (Side note: you may get a compiler warning on the SimulationComponent class having to do with “unchecked or unsafe operations”. This is a known issue with the starter code, so you should just ignore this warning for this particular class.)

    If you run into any problems with this code before you start modifying it (that is, if anything goes wrong in an unexpected way), your development environment probably doesn’t match the “supported” environment; that is, the Carleton lab machines. Try doing these steps on lab machines instead of your own computer to isolate any problems.

  2. Try running the MainWindow class as a Java application (that is, run java MainWindow on the command line). The VM Simulator window should appear. You should not get any error messages at this point.
  3. Open one of the given “programs” (that is, one of the files named program-XXXX.txt that are included with the project) by using the Load button.
    1. On the command line (where you typed in the java command to run the program), you should see an error message that says:

      Cannot instantiate CallStack. Method calls won't work.
      The CallStack class doesn't exist yet. (ClassNotFoundException)
      

      This is normal, and it should still happen even once you've completed this assignment — we’ll fix it in the next homework assignment.

    2. In the “Status Information” window, you should see a message like this:

      Syntax error in program-1.txt:
      Syntax checking not implemented!
      Program not loaded.
      

      Again, this message is normal at this point, but we want to implement syntax checking so that it goes away.

Note that in the rest of this assignment, you will only need to edit two files: the file in which you write your implementation of the Stack ADT, and Program.java. If you'd like to take a look at the other code, you're welcome to, but you're not expected to understand it, you don't need to understand it to do this assignment, and really you should just ignore it.

Step 2: Your Own Stack Implementation

In order to do the next step (syntax checking), you'll need an implementation of the Stack ADT. So let's get down to writing it!

  1. Create a new class that implements the included Stack interface. If you do the array-based implementation, name your class ArrayStackImplementation; if you do the link-based one, name it LinkedStackImplementation. You're free to choose either implementation.
  2. When a client attempts to pop() or peek() an empty stack, rather than returning null as a sentinel value, throw an EmptyStackException using the following code:

    throw new EmptyStackException();
    

    (EmptyStackException is a built-in Java exception that can be imported from java.util.)

  3. Write a main() method that thoroughly tests all the Stack ADT methods on a stack constructed with your implementation.

Step 3: Syntax Checking

The goal of this part is to write a method that can read through the lines of a text file and determine whether it has properly matching parentheses, square brackets, and curly brackets. You’ll use the Stack implementation that you just wrote to properly parse the syntax of a fake “Java-like” program.

I say “Java-like” because the “programs” that we’ll be using are mostly just nonsense written in an extremely simplistic pseudocode version of Java. For now, we’re only going to pay attention to the balance of brackets in these “program”.

  1. Go into the Program class and edit the syntaxCheck(Scanner) method. Notice now that it currently just throws a SyntaxErrorException. Modify the method so that it returns true when the syntax is correct, and throws a SyntaxErrorException otherwise.

    Important: the only thing you should edit in the Program class is the syntaxCheck(Scanner) method. Do not change any other code.

    Here are the steps to implement this capability:

    1. Create a new Stack<String> or Stack<Character>.
    2. Go through the input character-by-character.
    3. Whenever a (, [, or { is encountered, push that character onto the stack.
    4. Whenever a ), ], or } is encountered, see if it is the matching complement of the top character on the stack. If it is, pop the character on the top of the stack. If it isn’t, throw an exception.
    5. If the end of the file is reached, check the stack. If it isn’t empty, throw an exception.

    Note that a switch/case statement might be helpful in structuring your code for this portion of the assignment.

    Make sure that the exceptions you throw contain helpful messages. The optional first argument to the exception constructor is a string containing the exception's message. Clearly identify in your exception the line number on which the error happened (keeping in mind that lines are traditionally counted starting from 1, not 0) and what the exact problem was.

    You know how frustrating vague error messages are when you get them from the compiler or other programs? Well now's your chance to be the change you want to see in the world!

  2. Once you are confident in your syntax checker, try loading the programs with the VM Simulator. You should be able to “run” them by using the Run button. At this stage, “running” the program simply results in all the lines of the first method being printed to the status window.

In the next assignment, you will be modifying this method again to add extra capabilities. Your job will be much easier then if you put extra effort now into keeping your logic clean and simple. The syntax-checking task given above does not require complicated logic.

Step 4: Handling Comments

For this part, you need to modify your code to handle comments.

In Java, two forward slashes (//) signifies what is known as a single-line comment. When this is encountered, the rest of the line should be ignored rather than treated as part of the program.

Change your syntaxChecker() method to look for double-slashes in the code, and ignore the rest of a line if it is found.

The programs program-error-comment-1.txt and program-error-comment-2.txt are included to help you test whether the comment checking is working. They should not load properly if only Step 3 is implemented, because they have mismatched brackets inside of single-line comments. If the single-line comment code is working, the programs should load properly.

Again, you're going to be modifying this method further in the next assignment, so really think carefully about how you can implement this capability as simply and cleanly as possible. You'll be grateful later that you spent the time now to untangle your code.

Submission and Grading

Zip up your Stack ADT implementation file and your modified Program.java into hw13.zip, and submit it on Moodle. Do not include any other files in your zip file.

Start early, ask lots of questions, and have fun!

Grading