CMPU 102 - Assignment 5 |
Due: by 11:59 PM on Friday, October 7th |

In this assignment, you will implement an algorithm to parse arithmetic
expressions in Reverse Polish Notation (RPN) format and return them as
**Expression** objects. (You may remember **Expression** from
Lecture 4.)

$Revision: 1.1 $

RPN is a way of writing mathematical expressions. The defining characteristic
of RPN is that unlike ordinary *infix* notation, where binary operators
are placed between their operands, in RPN all operators come
*after* their operands. Example:

Infix: 3 + 4

RPN: 3 4 +

One advantage RPN has over traditional infix notation is that correctly formed RPN expressions are unambiguous: there is no need to use parentheses to force the evaluation order of particular sub-expressions. For example, consider the following (ambiguous) infix expression:

3 * 4 + 5

Depending on whether or not the multiplication is performed before the addition, we can get two different results:

(3 * 4) + 5 --> 17

3 * (4 + 5) --> 27

In RPN, the order of evaluation is explicit:

3 4 * 5 + --> 17

3 4 5 + * --> 27

As we discussed in class, stacks provide an easy way to evaluate RPN expressions. The rules are very simple:

- Simple expressions, such as literal values, are pushed onto the stack directly
- To evaluate the result of an operator that takes one or more operands, first pop the operands off the stack, compute the result, and push the result onto the stack

Essentially, the stack saves the values of operands until they are needed by the operator they are part of. When the entire expression has been parsed and evaluated, the stack should contain a single value representing the result.

In this assignment, rather than directly evaluating RPN expressions,
you will evaluate them *symbolically*. What that means
is that rather than computing a literal result each time you see
an operator, you will build an **Expression** object that
will be able to compute the result of the expression at a later time.

So, why compute the result of the expression symbolically? One
reason is that the expression might contain a *variable* whose
exact value is not known. By computing a symbolic version of the
expression, it can be evaluated later when the variable has been assigned
a value. Even better, we can evaluate a symbolic expression many
times for different values of the variable.

In your RPN expression parser, whenever you see the token "x", you will
push a special **Variable** object on the stack (which will be provided
as a parameter to the parsing method). This object
represents the variable **x**. By changing the value of this
variable, we can evaluate the entire expression for many values of
**x**, which we then use to implement a GUI program that visually
displays a graph of a function entered in RPN format:

You will need to handle expression strings that contain the following kinds of sub-expressions:

**Simple expressions**: literal numeric values ("3", "4.5", "-0.8"), and
the **x** variable ("x").

**Unary expressions**: the sine and cosine functions. For
example, "x sin" means the sine of **x**, and "x cos" means the
cosine of **x**. (The **Math.sin** and **Math.cos**
methods may be used to compute these functions.)

**Binary expressions**: the "+", "-", "*", and "/" operators perform
addition, subtraction, multiplication, and division, respectively.

If the RPN string you are given to parse is invalid, you should
throw an exception. Any kind of **RuntimeException** is
fine, including **IllegalArgumentException**, **IllegalStateException**,
**EmptyStackException**, etc.

Start by importing the file rpncalc.zip into Eclipse: from the menu, choose "File->Import->Existing Projects into Workspace", click "Select archive file", select "shapes.zip" from the file selection dialog, and then click the "Finish" button.

You will implement the **RPNParser.parse** method so that it
parses the input string given and returns an **Expression**
object representing the overall expression. Two **Expression**
classes are provided for you as an example: **Addition** and **Subtraction**.
You will need to add other **Expression** classes to implement the
other operators described above.
(Adding a new class in Eclipse.)

The **Expression** to use when you see the symbol "x" is the value
of the **xVariable** parameter passed to the **RPNParser.parse**
method.

You may implement your own stack, or you may use the **java.util.Stack**
class. In most respects, **java.util.Stack** is like the stack
classes we discussed in class, except that rather than having a
**getTop** method, it has a **peek** method to get the top value
on the stack (without removing it from the stack).

To test your implementation, you should add new JUnit test cases to
the **TestRPNParser** class. Several example tests are provided.
You may also run the **main** method of the **PlottingCalculator**
class, which plots the function represented by an RPN expression visually
for a range of X values.
(Running a main method in Eclipse.)

To submit the project, type the following commands in a terminal window (hitting return after each command):

cd cd eclipse-workspace submit102 rpncalc

You may submit as many times as you wish. The final submission prior to the deadline will be graded.