CS
210 Intermediate Computing with
Data Structures
Programming
Assignment 3
Spring 2006
Due Monday
Mar 20
at noon
Purpose
This assignment aims to help you:
· Gain experience with the Stack ADT and with linked lists
· Work with tokenization again, this time with Token objects
· Have experience in refactoring classes
· Learn about an interesting algorithm used in compiler design
Reading
Before working on this assignment, you should read 6.6.4, 11.1, 11.2, and 16.4 in the text.
Description
There are two parts to this assignment:
1. Implement a pure Stack, the JDK Stack subset of Figure 16.28, (not the Weiss nonstandard API, pg. 226) using JDK LinkedList—see Weiss 16.4 for most of this code, but drop size() as not in the "pure" subset. Call the class PureStack, to avoid naming conflicts with Stack in the JDK and make clear what this is. Replace the get() on line 31, pg. 558 with an appropriate LinkedList method call. Add a toString() method that mimics a Collection toString(), making sure that the top of stack is on the right-hand end.
2.
Following the
steps listed below, use your stack
class to build an implementation of Djiksta’s
“shunting
algorithm” for calculating the value of arithmetic
expressions such as (1
+ 2*3)/2. The shunting algorithm is used to calculate the
values of
arithmetic expressions taking into account parenthesis and operator
precedence. For this assignment we are going to work with
integer values
(int’s)
and integer
operators. The operators we will use are ^, *, /, %,
+,
-, &, and |. These
operators have the same
meaning they do in Java except for ^, and ^ is exponentiation, as
described in
Weiss, pg 380. Recall that | is bitwise OR and & is
bitwise AND.
The shunting algorithm works with two stacks: opStack - a stack of operators and postfixStack - a stack of values. We scan through an expression left to right. Each operator, operand, or parenthesis encountered is handled in turn. Evaluating the top consists of popping operator op from opStack, and popping val2and val1 from postfixStack, calculating val1 op val2, and pushing the result onto postfixStack., in other words, doing a postfix stack operation.
We will use the following table of operator precedence. All operators except ^ have left-to-right associativity. Thus 24/6/3 means (24/6)/3, not 24/(6/3) . But 2^3^2 means 2^(3^2).
|
Very high: |
^ |
|
High: |
*, /, % |
|
Medium: |
+, - |
|
Low: |
& |
|
Lower: |
| |
The shunting algorithm works by scanning through the expression and considering each token in turn:
· If the token is an integer, push it onto postfixStack.
· If the token is a left parenthesis (the ‘(‘ symbol), push it onto opStack.
· If the token is a right parenthesis (the ‘)‘ symbol), then you are evaluating a sub-expression. Repeat evaluating the top until the top of opStack is a left parenthesis. Finally, pop the left parenthesis from the top of opStack.
· If the token is an operator, do the following. While an operator on the top of opStack exists and has higher precedence (or is left-to-right associative and has equal precedence) than the encountered operator, repeat evaluating the top, Finally, push the encountered operator on the opStack.
· When the entire expression has been scanned, repeat evaluating the top until opStack is empty. The value on top of postfixStack is the value of the expression.
Steps
Note that these steps can be done in almost any order. Giving them numbers will make it easier to refer to them when asking for help, etc.
Start from Weiss’s calculator of 11.2, which already can do this job for most of the operators, and is available in Weiss’s website, and handles associativity via special precedence scores for operators. Also note that Weiss gives parentheses a precedence score, somewhat artificial, and uses another artificial token EOL. It would be nice to undo these tricks, but I’ll leave that up to you.
After completeing each step, firest make sure everything works right, and then make a backup copy of your directory, so you can go back to it if you get in trouble during the next step.
memo.txt
In the file memo.txt, answer the following questions:
· What problems did you encounter and how did you solve them?
· What Java development environment did you use? Any problems with it?
· Did you access any information on the Web during this work? Where?
. Did you skip any of the steps? Lack of time? Got stuck? or what?
· Is a doubly linked list (as in JDK’s LinkedList) a good data structure for implementing a stack? Why or why not?
· Do you think the program was improved by pulling the classes apart? Discuss advantages and disadvantages of the two designs.
· Explain what you would have to do to modify your implementation to use decimals like 1.45 in the calculations.
Turn In
Use the turnin system to submit your files. Before the due date, submit the following files to the program2 folder of your turnin system account:
·
memo.txt
· Token.java
· EvalTokenizer.java
· Precedence.java
· Evaluator.java with main(). Works the same way as the provided Evaluator program.
. PureStack.java
We will run a program that compiles and tests the Java code, and collect all files for the grader. It is your responsibility to make sure those files are present, that their names are spelled correctly (e.g. we will not find Memo.txt or memo.TXT) and that the files are turned in for the proper assignment folder.