Evaluating infix expressions using stacks - python

So I am currently learning about postfix, prefix, and infix expressions; and one of the challenge questions was about evaluating infix expressions using stacks. I think I understand the concept of it. However, I am really puzzled as to why my operators are not pushing onto my stack. I believe the problem is within line 31. However, I am not sure as to why. Could someone help me find and fix the problem?
class Stack:
def __init__(self):
self.items = []
def is_empty(self):
return self.items == []
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop()
def peek(self):
return self.items[len(self.items) - 1]
def size(self):
return len(self.items)
def infix(equation):
prec_dictionary = {"(": 0, ")": 0, "^": 4, "*": 3, "/": 3, "+": 2, "-": 2, "<": 1, ">": 1}
operator_stack = Stack()
operand_stack = Stack()
allowed_operators = "+-/*^<>"
a_list = equation.split()
for i in a_list:
if i in allowed_operators:
if operator_stack.is_empty():
operator_stack.push(i)
else:
if prec_dictionary[i] > prec_dictionary[operator_stack.peek()]:
operator_stack.push(i)
if i == "(":
operator_stack.push(i)
elif i == ")":
while operator_stack.peek() != "(":
value1 = int(operand_stack.pop())
operator = operator_stack.pop()
value2 = int(operand_stack.pop())
value = compute(value1, value2, operator)
operand_stack.push(value)
operator_stack.pop()
else:
operand_stack.push(i)
return operand_stack.pop()
def compute(number1, number2, operator):
if operator == "+":
return number1 + number2
elif operator == "-":
return number1 - number2
elif operator == "*":
return number1 * number2
elif operator == "/":
return number1 / number2
elif operator == "^":
return number1 ** number2
elif operator == "<":
return min(number1, number2)
else:
return max(number1, number2)
print(infix('2 ^ ( 1 + 3 ^ 2 )'))

Related

How can exponentiation functionality be added to an expression evaluator handling addition, subtraction, multiplication and division? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 days ago.
Improve this question
I have been writing an expression calculator using tokenization, parsing, and interpreting. The program builds a binary tree of operation/number nodes by determining expressions, terms, and factors. I have been struggling with implementing exponentiation, and my knowledge in mathematics/parsing is limited.
The issue I currently have is the particular input value 15/3*(5-4)*3^2 which should evaluate to ((15/3)*(5-4)*(3^2)) = 45 gets evaluated as ((((15/3)*(5-4))*3)^2) = 225
This can be seen from the output of the tree with each node being represented by the repr method:
#dataclass
class OperationNode:
type: OperationType
left_node: any
right_node: Optional[any] = None
def __repr__(self):
if self.type == OperationType.ADD:
return f"({self.left_node}+{self.right_node})"
elif self.type == OperationType.SUBTRACT:
return f"({self.left_node}-{self.right_node})"
elif self.type == OperationType.MULTIPLY:
return f"({self.left_node}*{self.right_node})"
elif self.type == OperationType.DIVIDE:
return f"({self.left_node}/{self.right_node})"
elif self.type == OperationType.EXPONENTIATION:
return f"({self.right_node}^{self.left_node})"
elif self.type == OperationType.PLUS:
return f"(+{self.left_node})"
elif self.type == OperationType.MINUS:
return f"(-{self.left_node})"
From what I understand, this issue may have something to do with exponentiation being right-associative while the input gets parsed from left to right.
The operation tree I'm looking for can be visualized as follows:
How can I implement exponentiation in this program? Current incorrect parsing section:
def identify_expression(self):
term_a = self.identify_exponentiation()
while self.current_token is not None and self.current_token.type in (TokenType.PLUS, TokenType.MINUS):
if self.current_token.type == TokenType.PLUS:
self.next_token()
term_a = OperationNode(OperationType.ADD, term_a, self.identify_exponentiation())
elif self.current_token.type == TokenType.MINUS:
self.next_token()
term_a = OperationNode(OperationType.SUBTRACT, term_a, self.identify_exponentiation())
return term_a
def identify_exponentiation(self):
term_a = self.identify_term()
while self.current_token is not None and self.current_token.type == TokenType.EXPONENT:
self.next_token()
term_a = OperationNode(OperationType.EXPONENTIATION, self.identify_exponentiation(), term_a)
return term_a
def identify_term(self):
factor_a = self.identify_factor()
while (self.current_token is not None and self.current_token.type in
(TokenType.MULTIPLY, TokenType.DIVIDE, TokenType.EXPONENT)):
if self.current_token.type == TokenType.MULTIPLY:
self.next_token()
factor_a = OperationNode(OperationType.MULTIPLY, factor_a, self.identify_factor())
elif self.current_token.type == TokenType.DIVIDE:
self.next_token()
factor_a = OperationNode(OperationType.DIVIDE, factor_a, self.identify_factor())
elif self.current_token.type == TokenType.EXPONENT:
self.next_token()
factor_a = OperationNode(OperationType.EXPONENTIATION, factor_a, self.identify_factor())
return factor_a
def identify_factor(self):
token = self.current_token
if token.type == TokenType.LEFT_PARENTHESIS:
self.next_token()
factor = self.identify_expression()
if self.current_token.type != TokenType.RIGHT_PARENTHESIS:
raise Exception('Incorrect mathematical expression')
self.next_token()
return factor
elif token.type == TokenType.NUMBER:
self.next_token()
return NumberNode(token.value)
elif token.type == TokenType.PLUS:
self.next_token()
return OperationNode(OperationType.PLUS, left_node=self.identify_factor())
elif token.type == TokenType.MINUS:
self.next_token()
return OperationNode(OperationType.MINUS, left_node=self.identify_factor())
raise Exception('Incorrect mathematical expression')
def next_token(self):
self.current_token_index += 1
try:
self.current_token = self.tokens[self.current_token_index]
except IndexError:
self.current_token = None
def do_operations(self, node):
if isinstance(node, NumberNode):
return float(node.value)
elif isinstance(node, OperationNode):
if node.type == OperationType.ADD:
return float(self.do_operations(node.left_node) + self.do_operations(node.right_node))
elif node.type == OperationType.SUBTRACT:
return float(self.do_operations(node.left_node) - self.do_operations(node.right_node))
elif node.type == OperationType.MULTIPLY:
return float(self.do_operations(node.left_node) * self.do_operations(node.right_node))
elif node.type == OperationType.DIVIDE:
try:
return float(self.do_operations(node.left_node) / self.do_operations(node.right_node))
except ZeroDivisionError:
raise Exception('Cant divide by 0')
elif node.type == OperationType.EXPONENTIATION:
return float(self.do_operations(node.left_node) ** self.do_operations(node.right_node))
elif node.type == OperationType.PLUS:
return float(self.do_operations(node.left_node))
elif node.type == OperationType.MINUS:
return -float(self.do_operations(node.left_node))
Your approach is a grammar based approach, but there are several cases where you jump from the broadest level to the most narrow level (rule) without visiting the intermediate levels.
For instance, there is no good reason to call identify_exponentiation from identify_expression. The grammar rules you want to implement will drill down level by level until they get to the deepest level, like (in BNF):
<digit> ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
<literal> ::= <digit> { <literal> }
<exponentiation> ::= <literal> [ "^" <factor> ] | "(" <expression> ")"
<factor> ::= ( "-" | "+" ) <factor> | <exponentiation>
<term> ::= <factor> [ ( "*" | "/" ) <term> ]
<expression> ::= <term> [ ( "+" | "-" ) <expression> ]
So there should be no call of identify_exponentiation from every other grammar rule.
I didn't attempt to get your code right as it looked too verbose to me. This tokenizing shouldn't be that complex -- the tokens can be identified with one call of re.findall and then the grammar rules can start doing their jobs immediately:
import re
class Calculator:
def calculate(self, calculation):
self.tokens = iter(re.findall(r"\d+|\S", calculation))
self.current = None
self.next()
return self.expression()
def next(self): # Return current token and get next one
token = self.current
self.current = next(self.tokens, "")
return token
def literal(self):
if not self.current.isdigit():
raise ValueError(f"Expected integer, got '{self.current}'")
return int(self.next())
def power(self):
if self.current == "(":
self.next()
return self.expression(")")
val = self.literal()
if self.current in ["^"]:
self.next()
return val ** self.factor()
return val
def factor(self):
if self.current in ["-","+"]:
return -self.factor() if self.next() == "-" else self.factor()
return self.power()
def term(self):
val = self.factor()
while self.current in ["*","/"]:
val = val * self.factor() if self.next() == "*" else val / self.factor()
return val
def expression(self, ending=""):
val = self.term()
while self.current in ["+","-"]:
val = val + self.term() if self.next() == "+" else val - self.term()
if self.next() != ending:
raise ValueError(f"Expected '{ending}', but got '{self.current}'")
return val
You could execute your test cases like this:
def main():
calculator = Calculator()
tests = {
"5+8": 13,
"14-11": 3,
"21/3": 7,
"5*5": 25,
"5^2": 25,
"10^3": 1000,
"4+5+6": 15,
"4 + 5 + 6": 15,
"2+3*6": 20,
"7-8*4+3": -22,
"5 ^ 3 - 2 ^ 4": 109,
"(7 - 8) * 4 + 3": -1,
"15/3*5-4*3": 13,
"15 / 3 * (5 - 4) * 3": 15,
"15 / 3 * (5 - 4) * 3 ^ 2": 45
}
for expression, expected in tests.items():
result = calculator.calculate(expression)
if result != expected:
ValueError(f"test {expression}: expected {expected}, got {result}")
print("all done")

python - return returns None

I wrote a function which gets two numbers and an operation (string) and returns the result of the two numbers with the given operation. For example calculate_matehamatical_expression(5,6,'+') should return 11. I divide the the assignment to little functions, but when I call these little function it always returns None. Can someone explain to me why that happens? This is the Code I wrote:
def mathematical_sum(num1,num2):
return num1 + num2
def mathematical_difference(num1,num2):
return num1 - num2
def mathematical_product(num1,num2):
return num1 * num2
def mathematical_division(num1,num2):
if num2 != 0:
return num1 / num2
else:
return None
def operation_error(operation):
if operation != "+" or operation != "-" or operation != "*" or operation != "/":
return None
def calculate_mathematical_expression(num1,num2,operation):
if operation == "+":
mathematical_sum(num1,num2)
elif operation == "-":
mathematical_difference(num1,num2)
elif operation == "*":
mathematical_product(num1,num2)
elif operation == "/":
mathematical_division(num1,num2)
else:
operation_error(operation)
You need to return again inside calculate_mathematical_expression, e.g.:
def calculate_mathematical_expression(num1,num2,operation):
if operation == "+":
return mathematical_sum(num1,num2)
The return in mathematical_sum doesn't affect the function it's being called from.
Your calculate_mathematical_expression function is not returning anything. Try following code:
def calculate_mathematical_expression(num1,num2,operation):
if operation == "+":
return mathematical_sum(num1,num2)
elif operation == "-":
return mathematical_difference(num1,num2)
elif operation == "*":
return mathematical_product(num1,num2)
elif operation == "/":
return mathematical_division(num1,num2)
else:
return operation_error(operation)
You need to return
When you return from a function, it only returns to the function that called it. So when you return in mathematical_sum(), the value is returned to calculate_mathematical_expression() & you need to return again from this function, like this:
if operation == "+":
return mathematical_sum(num1,num2)
elif operation == "-":
return mathematical_difference(num1,num2)
elif operation == "*":
return mathematical_product(num1,num2)
elif operation == "/":
return mathematical_division(num1,num2)
else:
return operation_error(operation)
...otherwise calculate_mathematical_expression() returns None.
operation_error() does not work
Use and instead of or. Otherwise your condition will always be True
Return a boolean, not None. Here, your function always return None
Example:
def operation_error(operation):
return operation != "+" and operation != "-" and operation != "*" and operation != "/"
You don't need operation_error()
Since you have a condition for each operator, you don't need the operation_error() function, you can directly do this:
else:
return None
...or even remove the else statement and let calculate_mathematical_expression() automatically return None when reaching its end.

raise ElementDoesNotExist stack.exceptions.ElementDoesNotExist

I have a problem with my RPN calculator:
def calculate_onp(onp):
from stack.stack import Stack
OPERATORS = ['+', '-', '*', '/']
s = Stack()
lista = onp.split(" ")
index = None
for i in range(1, len(onp)):
index = i - 1
if lista[index] in OPERATORS:
if lista[index] == OPERATORS[0]:
num1 = s.pop()
num2 = s.pop()
wyn = int(num1) + int(num2)
s.push(wyn)
elif lista[index] == OPERATORS[1]:
num1 = s.pop()
num2 = s.pop()
wyn = int(num1) - int(num2)
s.push(wyn)
elif lista[index] == OPERATORS[2]:
num1 = s.pop()
num2 = s.pop()
wyn = int(num1) * int(num2)
s.push(wyn)
elif lista[index] == OPERATORS[3]:
num1 = s.pop()
num2 = s.pop()
wyn = int(num1) / int(num2)
s.push(wyn)
else:
return 'ERROR'
else:
s.push(lista[index])
return int(s.pop())
I added a stack implementation to this:
from stack.exceptions import ElementDoesNotExist
class Stack(object):
def __init__(self):
self.stack = []
def __len__(self):
return len(self.stack)
def push(self, s):
return self.stack.append(s)
def pop(self):
if len(self.stack) == 0:
raise ElementDoesNotExist
else:
return self.stack.pop()
def show_list(self):
print(self.stack)
And exceptions:
for stack:
class ElementDoesNotExist(Exception):
pass
for rpn:
class OnpException(Exception):
pass
class OnpMissingOperationArgument(OnpException):
pass
class OnpMissingNumericArgument(OnpException):
pass
After running this:
File "/home/maciek/PycharmProjects/Calc/stack/stack.py", line 16, in pop
raise ElementDoesNotExist
stack.exceptions.ElementDoesNotExist
What's wrong?
your pop function has called to a function named len(self.stack). But It doesn't exists. so try on Changing the name def __len__(self): to def len(self):

Stack calculator (postfix, Python)

The question I'm having problem on is calculating the postfix form expressions: for example, (1, 2, '+', 3, '*').
By calculating the expression using the following algorithm:
1. If the expression only contains an integer, return that integer.
2. Otherwise, maintain a stack. Loop through the tuple and push every element to the stack. If the element is an operator, pop the first two element out of the stack, calculate the result and push the result into the stack.
To illustrate, we take the example above. Initially, the stack is empty.
The test case is
calculate((1, 2, '*', 3, '-', 2, '*', 5, '+'))
3
whereas my first code was no good (hardcoded and all >< ):
def calculate(inputs):
if len(inputs) ==1:
return inputs[0]
elif len(inputs) == 5:
s= []
push_stack(s, inputs[0])
push_stack(s, inputs[1])
if inputs[2] == '*':
A = s.pop() * s.pop()
elif inputs[2] == '+':
A = s.pop() + s.pop()
elif inputs[2] == '-':
A= s.pop() - s.pop()
elif inputs[2] == '/':
A = s.pop() / s.pop()
s.clear()
s= [A]
push_stack(s, inputs[3])
if inputs[4] == '*':
A = s.pop() * s.pop()
elif inputs[4] == '+':
A = s.pop() + s.pop()
elif inputs[4] == '-':
A= s.pop() - s.pop()
elif inputs[4] == '/':
A = s.pop() / s.pop()
return A
else:
s= []
push_stack(s, inputs[0])
push_stack(s, inputs[1])
if inputs[2] == '*':
A = s.pop() * s.pop()
elif inputs[2] == '+':
A = s.pop() + s.pop()
elif inputs[2] == '-':
A= s.pop() - s.pop()
elif inputs[2] == '/':
A = s.pop() / s.pop()
s.clear()
s= [A]
push_stack(s, inputs[3])
if inputs[4] == '*':
A = s.pop() * s.pop()
elif inputs[4] == '+':
A = s.pop() + s.pop()
elif inputs[4] == '-':
A= s.pop() - s.pop()
elif inputs[4] == '/':
A = s.pop() / s.pop()
s.clear()
s= [A]
push_stack(s, inputs[5])
if inputs[6] == '*':
A = s.pop() * s.pop()
elif inputs[6] == '+':
A = s.pop() + s.pop()
elif inputs[6] == '-':
A= s.pop() - s.pop()
elif inputs[6] == '/':
A = s.pop() / s.pop()
s.clear()
s= [A]
push_stack(s, inputs[7])
if inputs[8] == '*':
A = s.pop() * s.pop()
elif inputs[8] == '+':
A = s.pop() + s.pop()
elif inputs[8] == '-':
A= s.pop() - s.pop()
elif inputs[8] == '/':
A = s.pop() / s.pop()
return A
Sorry for making you read that! Then I changed the style to
def calculate(inputs):
if len(inputs) ==1:
return inputs[0]
else:
s =[]
for i in inputs:
if type(i) == int:
return push_stack(s, i)
elif i is '*' or '/' or 'x' or '+':
A = s.pop()
B =s.pop()
know = operator(i, A, B)
C = push_stack(s, know)
return C
def operator(sign, one, two):
if sign == '*':
A = one * two
elif sign == '+':
A = one + two
elif sign == '-':
A= one - two
elif sign == '/':
A = one / two
return A
Am I getting closer to the idea and how does my code improve?
** Edit **
Using IDLE:
>>> calculate((1, 2, '*', 3, '-'))
[1]
>>> calculate((1, 2, '+', 3, '*'))
[1]
>>> calculate((1, 2, '*', 3, '-', 2, '*', 5, '+'))
[1]
which is not the answer I'm looking for. It should be 1 then 9 then 3.
There is a problem with
elif i is '*' or '/' or 'x' or '+':
which is treated as
elif (i is '*') or ('/') or ('x') or ('+'):
which is not what you want (it's always true). You can instead use something like:
elif i in ('*', '/', 'x', '+'):
Also:
if type(i) == int:
return push_stack(s, i)
You shouldn't be returning there. You simply want:
if type(i) == int:
push_stack(s, i)
Lastly, I think a better approach would be to always use the stack, and just return the top of the stack at the end of your function. This saves you from having to create a special case for 1-element arguments to calculate(). Putting this all together, something along the lines of this should work:
def calculate(inputs):
stack = []
for a in inputs:
if type(a) is int:
stack.append(a)
continue
op1, op2 = stack.pop(), stack.pop()
if a == '+':
stack.append(op2 + op1)
elif a == '-':
stack.append(op2 - op1)
elif a == '*':
stack.append(op2 * op1)
elif a == '/':
stack.append(op2 / op1)
return stack.pop()
Right now this does no error-checking (e.g. for malformed expressions), but it's easy to add.
Part of the problem, which you seem to have realized, is that you are trying to make one function do everything. If you take a look at what the code is doing, and try to separate out the responsibilities, you end up with something like the following:
There are some crucial differences between Python 2.x and 3.x. Where these differences would cause problems, it's easiest to introduce helper functions and define them appropriately for each version:
import sys
if sys.hexversion < 0x3000000:
# Python 2.x
is_str = lambda s: isinstance(s, basestring)
inp = raw_input
else:
# Python 3.x
is_str = lambda s: isinstance(s, str)
inp = input
You do a fair bit of stack maintenance; this can be avoided by making a Stack class which knows how to pop and push multiple items. (It should also help your out-of-order arguments problem; 4 2 - should be 4 - 2, not 2 - 4)
class Stack(list):
def pop_n(self, n):
"""
Pop n items off stack, return as list
"""
assert n >= 0, "Bad value {}: n cannot be negative".format(n)
if n == 0:
return []
elif n <= len(self):
res = self[-n:]
del self[-n:]
return res
else:
raise ValueError("cannot pop {} items, only {} in stack".format(n, len(self)))
def push_n(self, n, items):
"""
Push n items onto stack
"""
assert n == len(items), "Expected {} items, received {}".format(n, len(items))
self.extend(items)
Rather than having a single "do-any-operation" function, we can let each operator have its own self-contained code. This makes it much easier to change or add operators without funny side-effects. First we make an Operator class
class Op:
def __init__(self, num_in, num_out, fn):
"""
A postfix operator
num_in: int
num_out: int
fn: accept num_in positional arguments,
perform operation,
return list containing num_out values
"""
assert num_in >= 0, "Operator cannot have negative number of arguments"
self.num_in = num_in
assert num_out >= 0, "Operator cannot return negative number of results"
self.num_out = num_out
self.fn = fn
def __call__(self, stack):
"""
Run operator against stack (in-place)
"""
args = stack.pop_n(self.num_in) # pop num_in arguments
res = self.fn(*args) # pass to function, get results
stack.push_n(self.num_out, res) # push num_out values back
then we define the actual operators as
ops = {
'*': Op(2, 1, lambda a,b: [a*b]), # multiplication
'/': Op(2, 1, lambda a,b: [a//b]), # integer division
'+': Op(2, 1, lambda a,b: [a+b]), # addition
'-': Op(2, 1, lambda a,b: [a-b]), # subtraction
'/%': Op(2, 2, lambda a,b: [a//b, a%b]) # divmod (example of 2-output op)
}
Now that the support structure is in place, your evaluation function is simply
def postfix_eval(tokens):
"""
Evaluate a series of tokens as a postfix expression;
return the resulting stack
"""
if is_str(tokens):
# if tokens is a string, treat it as a space-separated list of tokens
tokens = tokens.split()
stack = Stack()
for token in tokens:
try:
# Convert to int and push on stack
stack.append(int(token))
except ValueError:
try:
# Not an int - must be an operator
# Get the appropriate operator and run it against the stack
op = ops[token]
op(stack) # runs Op.__call__(op, stack)
except KeyError:
# Not a valid operator either
raise ValueError("unknown operator {}".format(token))
return stack
and to make it easier to test, we can make it interactive:
def main():
while True:
expr = inp('\nEnter a postfix expression (or nothing to quit): ').strip()
if expr:
try:
print(" => {}".format(postfix_eval(expr)))
except ValueError as error:
print("Your expression caused an error: {}".format(error))
else:
break
if __name__=="__main__":
main()
This runs like
Enter a postfix expression (or nothing to quit): 1 2 * 3 -
=> [-1]
Enter a postfix expression (or nothing to quit): 1 2 + 3 *
=> [9]
Enter a postfix expression (or nothing to quit): 1 2 * 3 - 2 * 5 +
=> [3]
Enter a postfix expression (or nothing to quit): 5 2 /%
=> [2, 1]
If you are doing calculator, or something like that, you should use function eval().
It will return result of expression.

Infix to Postfix Converter Python 2.7

I am trying to create a infix to postfix converter in python for a homework assignment, I found multiple ones online that seem simple enough but none of them meet the requirements I need. I have to use the following classes:
class Token(object):
UNKNOWN = 0 # unknown
INT = 4 # integer
MINUS = 5 # minus operator
PLUS = 6 # plus operator
MUL = 7 # multiply operator
DIV = 8 # divide operator
FIRST_OP = 5 # first operator code
def getPrecedence(self):
if self is '(':
return 0
elif self is '+'or '-':
return 1
elif self is '*' or '/':
return 2
else:
return 3
def _init_(self, value):
if type(value) == int:
self._type = Token.INT
else:
self._type = self._makeType(value)
self._value = value
def isOperator(self):
return self._type >= Token.FIRST_OP
def _str_(self):
return str(self._value)
def getType(self):
return self._type
def getValue(self):
return self._value
def _makeType(self, ch):
if ch == '*': return Token.MUL
elif ch == '/': return Token.DIV
elif ch == '+': return Token.PLUS
elif ch == '-': return Token.MINUS
else: return Token.UNKNOWN;
I had to add the getPrecedence(): method, which returns an Integer that represents the precedence level of an operator. I also had to use the following class:
from token import Token
class Scanner(object):
EOE = ';' # end-of-expression
TAB = '\t' # tab
def __init__(self, sourceStr):
self._sourceStr = sourceStr
self._getFirstToken()
def hasNext(self):
return self._currentToken != None
def next(self):
if not self.hasNext():
raise Exception, "There are no more tokens"
temp = self._currentToken
self._getNextToken()
return temp
def _getFirstToken(self):
self._index = 0
self._currentChar = self._sourceStr[0]
self._getNextToken()
def _getNextToken(self):
self._skipWhiteSpace()
if self._currentChar.isdigit():
self._currentToken = Token(self._getInteger())
elif self._currentChar == Scanner.EOE:
self._currentToken = None
else:
self._currentToken = Token(self._currentChar)
self._nextChar()
def _nextChar(self):
if self._index >= len(self._sourceStr) - 1:
self._currentChar = Scanner.EOE
else:
self._index += 1
self._currentChar = self._sourceStr[self._index]
def _skipWhiteSpace(self):
while self._currentChar in (' ', Scanner.TAB):
self._nextChar()
def _getInteger(self):
num = 0
while True:
num = num * 10 + int(self._currentChar)
self._nextChar()
if not self._currentChar.isdigit():
break
return num
I have to write a program that converts a infix expression to a postfix expression. This program should use the Token and Scanner classes (which I have included above). The program should consist of a main function that preforms the inputs and outputs, and a class named IFToPFConverter. The main function receives a input string an creates a scanner with it. The scanner is then passed as a argument to the constructor of the converter object. The converter objects convert method is then run to convert the infix expression. This method returns a list of tokens that represent the postfix string. The main function then displays this string. Here is what I have so far:
from arrayStack import ArrayStack
from token import Token
from scanner import Scanner
class IFToPFConverter(object):
def convert(self):
opStack = Stack()
postFixList = []
while self._scanner.hasNext():
currentToken = self._scanner.next()
if currentToken in '0123456789'
postFixList.append(currentToken)
elif currentToken == '(':
opStack.push(currentToken)
elif currentToken == '*':
opStack.push(currentToken)
elif currentToken == '/':
opStack.push(currentToken)
elif currentToken == '+':
opStack.push(currentToken)
elif currentToken == '-':
opStack.push(currentToken)
elif currentToken == ')':
opStack.push(currentToken)
while not opStack.isEmpty():
def main():
sourceStr = raw_input("Please enter an expression:")
scanner = Scanner(sourceStr)
conversion = IFToConverter.convert(scanner)
return conversion
main()
I don't know where to go from here, I don't even know if what I am trying to do at in my IFToPFConverter class will work. I have seen much simpler infix to postfix converters.

Categories