Access over 20 million homework documents through the notebank

Get on-demand Q&A homework help from verified tutors

Read 1000s of rich book guides covering popular titles

Anonymous

In this assignment, you will implement a small subset of the python interpreter. The user should be able to write an expression, and your program will evaluate it.

For example, here is a sample run of the program (the user’s input appears after the >>> prompt):

>>> r = 10

10.0

>>> pi= 3.1416

3.1416

>>> circumference = 2*

62.832

>>> volume=(1 + 1/3) * pi * r*r*r
4188.8

CS417 Programming Assignment #8
Due on Wednesday, April 22nd.
Late penalty: Thu 5%, Fri 10%, Sat/Sun/Mon 20%, Tue 50%, Wed 100%
Getting Started
Begin by dowloading these two files:
calculator.py
stack.py
Calculator
In this assignment, you will implement a small subset of the python interpreter. The user should
be able to write an expression, and your program will evaluate it.
For example, here is a sample run of the program (the user’s input appears after the >>>
prompt):
>>> r = 10
10.0
>>> pi= 3.1416
3.1416
>>> circumference = 2*
pi *r
62.832
>>> volume=(1 + 1/3) * pi * r*r*r
4188.8
Specifications
The calculator should accept ordinary infix expressions with the following parts:
Variables
Variable names must qualify as valid python variables:
they must start with a letter or an underscore
the remaining characters (if any) may be letters, digits, or underscores
Numbers
Numbers should not raise an error when evaluated with float(). However, your code does
not have to handle floats in mantissa-exponent notation such as 123.45e-6 .
Operators
The single-character binary operators should be implemented: +, -, *, /, and = . The last one
is the assignment operator:
its left operand (the lvalue) is a variable name,
its right operand (the rvalue) is a valid expression, and
its value is the value of the right operand.
Parentheses
Parentheses () may be used to override the rules of operator precedence.
Whitespace
Operators and operands may be adjacent in the infix expression, or may be separated by one
or more whitespace characters, which are blanks ' ' and tabs \t .
Behavior
The calculator should perform a read-evaluate-print loop (REPL), until end-of-file is reached on
the input:
get an infix expression from the input
convert the expression into an internal form: a postfix expression
evaluate the expression
print the result
Symbol Table
Some expressions, like 1 + 2 * 3.14 , do not change the state of the calculator. But others, like
a = 1 + 2 * 3.14 have a side effect: a variable a is created or modified.
To implement this functionality, your calculator will need a symbol table, which is a dict() that
maps strings (variable names) to floats (the variable’s value). This symbol table should be passed
into the code that evaluates an expression.
Code to be implemented
Implement your calculator in a module called calculator.py . Your module MUST implement
the following functions (our testing code will call these functions):
tokenize(line, specials, whitespace) : This function takes a string, and returns a
list of the tokens in the string.
line : an ordinary string (could be an infix or postfix expression)
whitespace : a string, containing characters to be treated as whitespace. Typically
whitespace == " \t"
specials : a string, containing characters to be treated as single-character tokens.
Typically specials == "+-*/()"
Example:
tokens = tokenize("1 +( total* 3/ 4.56)", "=+-*/()", " \t")
print (tokens)
should output
["1", "+", "(", "total", "*", "3", "/", "4.56", ")"]
to_postfix(infix_expression) : This function takes a string, and returns a list. The
input is an infix expression, and the output is the equivalent postfix expression. The postfix
expression is a list of tokens. Example:
postfix = to_postfix("1 +( total* 3/ 4.56)")
print (postfix)
should output
[1, 'total', 3, '*', 4.56, '/', '+']
eval_postfix(postfix_expression) : This function takes a list of tokens, and returns
a float. The input is a postfix expression, and the output is its value. This function may
change the state of the symbol table, which is passed in. Example:
value = eval_postfix([1, 2, 3, 4, '/', '*', '+'], symbols)
print (value)
should output 2.5 .
Turning in your work
When you are done, go to mycourses.unh.edu, and find CS417, and the assignment. Click the
“Submit” button and upload calculator.py.
CS417 Programming Assignment 8
Frequently-asked Questions
Q: How do I convert an infix expression to postfix?
A: Here is the pseudocode:
make an empty stack, which holds operators
make an empty postfix expression to begin with
for each token in the infix expression,
if token == '(',
push it
else if token is an operand,
append to postfix expression
else if token == ')',
while stack is not empty and its top isn't '(',
pop from S, append to postfix expression
pop the ')'
else (it's an operator),
while stack is not empty and the precedence of its top
is higher or equal to token's precedence,
pop from S, append to postfix expression
push token
when done, stack may hold some pending operators.
if so, pop them, and append to postfix expression
Q: How do I evaluate a postfix expression?
A: Here is the pseudocode:
make an empty stack
for each token in postfix expression,
if token is an operand,
push token
else (it's an operator)
pop right operand
pop left operand
apply operator
push result
Upon completion, the expression’s value will be at the top of the stack.
Q: If I have a token, how do I know it is an operator, a number, or a variable name?
A: This problem is part of a current lab, but here is the gist: (this is not python, it’s pseudocode)
if token is one of "+-*/=",
it's an operator
else,
try:
x = float(token)
it's a number, because no exception was raised
except ValueError:
if token obeys the rules for python variable names,
it's a variable
else,
the expression has an error, and can't be evaluated
Q: How are variables different from numbers?
A: You actually know this ☺, but it’s worth spelling out. Variables are treated differently,
depending on context.
If a variable is the right operand, you should get its value from the symbol table.
If a variable is the left operand of "+-*/", you should also get its value from the symbol
table.
If a variable is the left operand of "=", you should set a value in the symbol table.
All of this must be handled in your evaluate_postfix function.
Q: What is the precedence of each operator?
A: Again, you know this, but there are some subtleties:
* / : high precedence
+ - : medium precedence
= ( ) : low precedence
Parentheses should have low precedence, because of this code in the second question above:
while stack is not empty and the precedence of its top
is higher than token's precedence,
pop from S, append to postfix expression
Suppose you are converting this expression, and you are currently at the '-' token:
1 / (2 + 3 - 4)
^
At this point, the stack would have / ( + . The top of the stack is + . If ( had high precedence,
then the while loop will pop the +, then the (, then the /. You would, at that point, have this
partially-completed postfix expression:
1 2 3 + ( /
which is obviously wrong, because postfix expressions have no parentheses. The solution is to
give parentheses low precedence, so the while loop will exit as soon as it finds the ( on the top of
the stack.
Q: How do I implement the "=" operator? I know that the +, -, *, / operators produce a value.
Does = produce a value too?
A: Absolutely YES. Here is why: Suppose you have this infix expression:
a = b = 20
The expression b = 20 should have the value 20. Thus, the above expression would change the
value of b, and proceed to evaluate a = 20. As a result, both a and b get the value 20.
To make this happen, in evaluate_postfix, you should push a value on the stack, when you
process a = operator. That value is simply the value of the right operand.
Q: The "=" operator is still giving me problems. Why does a = b =
10 give an error?
A: The problem is that = is right-associative. In other words,
a = b = 10
is equivalent to
a = (b = 10)
Which, in postfix, is:
a b 10 = =
In other words, b = 10 is evaluated first. Unfortunately, our infix-to-postfix conversion
assumes that all operators are left-associative. For example, we expect that
a - b + c
should be interpreted as
(a - b) + c
Which, in postfix, is
a b - c +
In other words, a - b is evaluated first. Notice how the parentheses group differently in this
case.
The problem, ultimately, lies in this while loop:
while stack is not empty and the precedence of its top
is higher or equal to token's precedence,
pop from S, append to postfix expression
If you have several equal-precedence operators, they will be popped in left-to-right order. But if
there is an = operator on the stack, and you get another = operator, you should not pop from the
operator stack. So, the test in the while loop should be changed. You need to figure that one out.
...

Student has agreed that all tutoring, explanations, and answers provided by the tutor will be used to help in the learning process and in accordance with Studypool's honor code & terms of service.

This question has not been answered.

Create a free account to get help with this and any other question!

Brown University

1271 Tutors

California Institute of Technology

2131 Tutors

Carnegie Mellon University

982 Tutors

Columbia University

1256 Tutors

Dartmouth University

2113 Tutors

Emory University

2279 Tutors

Harvard University

599 Tutors

Massachusetts Institute of Technology

2319 Tutors

New York University

1645 Tutors

Notre Dam University

1911 Tutors

Oklahoma University

2122 Tutors

Pennsylvania State University

932 Tutors

Princeton University

1211 Tutors

Stanford University

983 Tutors

University of California

1282 Tutors

Oxford University

123 Tutors

Yale University

2325 Tutors