Shift-Reduce Evaluation in Java

MCS-178: Introduction to Computer Science II

Introduction

In this project you will be working with a Java version of the shift-reduce evaluator from Section 13.2 of Concrete Abstractions. Your primary objective is to add one additional feature to the evaluator: the use of exclamation point as a factorial operation. You will work individually.

Day one: guided tour

On the first lab day, I will show you how to open the project up in the BlueJ system, which is a Java programming environment. I will demonstrate how you can interact with the existing code in BlueJ, and I will show and explain some portions of the code. My expectation is that this will pretty well occupy the first day, without your necessarily having any time to start your own work.

As I will demonstrate, to make your own copy of the project and open it up in BlueJ, the steps are as follows:

  1. Download the file evaluate.jar from this web page. You may need to specifically tell your web browser to save this file to disk rather than opening it. This file contains the whole project, all packaged together in one compressed file.

  2. Run BlueJ. You can either find it from your computer's main menu (probably in a submenu called "MCS"), or you can type bluej in a terminal window (also known as a shell).

  3. Within BlueJ, go into the Project menu and select "Open Non BlueJ...". From the file browser window that opens, select the evaluate.jar file. This should open up a new project window. As a side-effect, it also unpacks the contents of evaluate.jar into a directory called evaluate. In the future, when you run BlueJ it can directly open the project from this directory, without needing to go through these three steps.

Outside lab: design your addition

Before the second lab day, you should have turned in Exercise 13.28 on pages 478-479 as a homework problem. This problem concerns the addition of the factorial operation to the evaluator, at the conceptual level of adding it to the table, rather than at the detailed level of adding it to the Java code. Because this will serve as the foundation of your work, you should bring a copy of it with you to lab.

One item you may specifically want to check, because I have frequently seen students get it wrong, is that you correctly handle factorials of factorials, such as "3!!". I would be happy to talk with you about your design, if you don't want to progress into the Java coding without some confirmation of your design work.

Also, if you are for some reason held up on this homework problem, the first two sections of coding can be done without any real dependence on it.

Factorial procedure

Add a procedure to the Evaluate class (as a public static method) which takes an integer argument (that is, a value of type int) and returns its factorial (which should again be of type int). For now, you can assume that the argument is nonnegative and small enough that its factorial can be represented as an int. (Extra credit problems address these issues.) You will receive partial credit if you have a working procedure that calls itself recursively (as a Scheme version normally would). For full credit, you need to write a version that uses a while or for loop to carry out an iteration. Be sure to test your procedure on its own, using BlueJ.

Values on the evaluator's stack are stored as Strings. This explains why the procedure operateInts for carrying out arithmetic operations is accompanied by a wrapper procedure operate that converts the operands from Strings to ints and converts the result back into a String. You will need to provide a similar wrapper for your factorial procedure, unless you want to do the type conversions inside the factorial procedure itself or inside the reduce procedure.

New kind of reduction

Modify the reduce procedure, which corresponds to the Scheme procedure reduce!, so as to perform the appropriate kind of reduction if the top of the stack contains an exclamation point and a number. This should make use of your procedure for computing factorials. You should test your modified reduce procedure in BlueJ, after manually pushing appropriate strings onto the exprStack.

New conditions for when to shift or reduce

Your table from Exercise 13.28 needs to be translated into Java. Make the appropriate additions to the isReduce and isShift procedures, which are the Java equivalents of the Scheme procedures reduce? and shift?. Be sure to test your modified procedures on their own, using BlueJ, to verify that they correspond to your table.

Testing the whole system together

At this point, you should have all the pieces in place to test evaluating expressions that contain exclamation points. Do so.

Extra credit opportunities

You can do any of these, or more than one if you like. They are mostly independent of each other, though there is some interaction between the second and third.

  1. The program is currently light on error checking. Change your factorial procedure so that it throws an Error if asked to compute the factorial of a negative number. Also, the RAStack class has one error check already in place, but really should have another one as well. Find that second place and introduce the error check.

  2. If you take the factorial of a reasonably large integer, you'll find that the result is incorrect because the correct answer wouldn't fit in the number of bits available for an int. (You encountered this same issue in SLIME.) You can fix this by using the BigInteger class from the Java API. Because large integers can arise even without factorials, you shouldn't limit yourself just to factorials: you should use BigIntegers consistently throughout the whole evaluator.

  3. What happens if you evaluate an expression like "7/2"? Explain why. Design and program a modification to the evaluator so that it will provide more precise answers in cases like this.

What to turn in

You should write a report that uses your table from Exercise 13.28 as the focal point for explaining your modifications to the evaluator. Your target audience should be people who are familiar with the original evaluator but who don't know what feature you were adding or how you were doing so.

Your report should include the code for all modified or newly added procedures. However, don't include any procedures that are left unchanged.

You need not comment upon testing unless there is some bug that you found in the course of testing but were unable to fix. In that case, it is important for you to report what you found to be not working. Otherwise, you will lose double points: one loss of points for the programming difficulty, and another for (apparently) not having done adequate enough testing to uncover the existence of the bug.

If you take any of the extra credit opportunities, be sure to specifically mention them in your report, rather than relying on me to spot them in your code.

The gradesheet shows how the report will be graded.