Infix to Postfix Converter Python 2.7 - python

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.

Related

how to invoke a function in a Python app which has multiple files

I have two or three files in Python for s-expression. But I am not able to invoke the function to calulate the result of s-expression as I am not sure which function to invoke.
I have four files here:
1st file: calc.py
import sys
from parse import *
from expr import *
from calculator import *
def main():
if len(sys.argv)<2:
print('No Input!')
return
expr_list = ParseInput(sys.argv[1]).parse_to_list()
expression = Expression(expr_list)
if not expression.check_validation():
print('Not Valid Input!')
return
calculator = Calculator()
print(calculator.calculate(expression))
if __name__ == '__main__':
main()
2nd file: expr.py
class Expression(object):
def __init__(self, expr_list=None):
self.__expression = expr_list
def get_subexprs(self, expr_list):
res = []
i = 2
while i < len(expr_list)-1:
l = self.count_subexpr_length(expr_list, i)
res.append(expr_list[i:i+l])
i += l
return res
def count_subexpr_length(self, expr_list, i):
j = i+1
if expr_list[i] == '(':
count = 1
while count!= 0 and j<len(expr_list):
if expr_list[j] == ')':
count -= 1
if expr_list[j] == '(':
count += 1
j += 1
return j-i
def check_validation(self):
return self.is_valid(self.__expression)
def is_valid(self, expr_list):
if not expr_list:
return False
if len(expr_list)==1:
return self.is_integer(expr_list)
return self.is_func(expr_list)
def is_func(self, expr_list):
if len(expr_list) < 4:
return False
if expr_list[0] != '(' or expr_list[-1] != ')':
return False
if expr_list[1] not in ['add', 'multiply']:
return False
count = 0
for char in expr_list:
if char == '(':
count += 1
if char == ')':
count -=1
if count <0 :
return False
if count != 0 :
return False
for subexpr in self.get_subexprs(expr_list):
if not self.is_valid(subexpr):
return False
return True
def is_integer(self, expr_list):
return expr_list[0].isdigit()
def get_length(self):
return len(self.__expression)
def get_int(self):
if len(self.__expression) == 1:
return int(self.__expression[0])
def get_operator(self):
if len(self.__expression) > 1 :
return self.__expression[1]
def get_exprlist(self):
return self.__expression
3rd file: parse.py
class ParseInput(object):
def __init__(self, input_string=''):
self.input_string = input_string
def parse_to_list(self):
if self.input_string == '':
print('No Valid Input!')
return None
newString = ''
for char in self.input_string:
if char == '(':
newString += char + ' '
elif char == ')':
newString += ' ' + char
else:
newString += char
return newString.split()
4th file:calculator.py
from expr import *
class Calculator(object):
def __init__(self):
pass
def calculate(self, expression):
return self.calc_expression(expression)
def calc_expression(self, expression):
if not expression:
print('Sorry, you need to load expression!')
return
if expression.get_length() == 1:
return expression.get_int()
operator = expression.get_operator()
if operator == 'add':
return self.calc_add(expression)
if operator == 'multiply':
return self.calc_mul(expression)
def calc_add(self, expression):
base = 0
for subexpr in expression.get_subexprs(expression.get_exprlist()):
base += self.calc_expression(Expression(subexpr))
return base
def calc_mul(self, expression):
base = 1
for subexpr in expression.get_subexprs(expression.get_exprlist()):
base *= self.calc_expression(Expression(subexpr))
return base
The requirement says:
calc.py
Main file to run this calculator engine. Runs the engine in command line, with one valid argument as input.
Example:
$ python calc.py "123"
$ python calc.py "(add 12 12)"
However, I don't see any input expression taking input from the user in calc.py. Also I did the following in Python shell and it gives me the following error.
>>> import calc
>>> calc.py "(add 12 12)"
File "<stdin>", line 1
calc.py "(add 12 12)"
^^^^^^^^^^^^^
SyntaxError: invalid syntax
I want to know which function to invoke and how to invoke that in Python shell?
Update:
When I tried it in the command prompt, it gives me the following error:

Why do I get a "ValueError: I/O operation on closed file" with a file that has not been closed yet?

I am getting the error
line 9, in hasMoreCommands
if self.asmfile.readline():
ValueError: I/O operation on closed file.
This is line 9 from this file:
class Parser:
def __init__(self, asmfile):
try:
self.asmfile = open(asmfile,'r')
self.currentCommand = '' #initially there is no current command
except FileNotFoundError:
print("Wrong path")
def hasMoreCommands(self):
if self.asmfile.readline():
return True
return False
def advance(self):
self.currentCommand = self.asmfile.readline()
#property
def commandType(self):
self.currentCommand = self.currentCommand.strip() #remove any leading or trailing whitespace
#currentCommand is a comment or white line, not an instruction
if self.currentCommand[0] == '/':
return None
elif not self.currentCommand.strip():
return None
elif self.currentCommand[0] == '#':
return 'A_COMMAND'
else:
return 'C_COMMAND'
#property
def symbol(self):
if self.commandType == 'A_COMMAND':
return self.currentCommand.strip('#')
else:
return None
#property
def dest(self):
if self.commandType == 'C_COMMAND':
if '=' in self.currentCommand:
return self.currentCommand.split('=')[0]
else:
return 'null'
#property
def comp(self):
if self.commandType == 'C_COMMAND':
if '=' in self.currentCommand and ';' in self.currentCommand:
fields = self.currentCommand.split('=')
return fields[1].split(';')[0]
elif '=' in self.currentCommand:
return self.currentCommand.split('=')[1]
elif ';' in self.currentCommand:
return self.currentCommand.split(';')[0]
#property
def jump(self):
if self.commandType == 'C_COMMAND':
if ';' not in self.currentCommand:
return 'null'
else:
return self.currentCommand.split(';')[1]
The main file is this:
import sys
import ParserL as pl
import CodeL as cl
asmfilename = sys.argv[1]
hackfilename = asmfilename.split('.')[0] + ".hack"
hackfile = open(hackfilename, "w")
# create a parser object, tied to the .asm file input
parser = pl.Parser(asmfilename)
# create a code object which will translate a symbol input to it
code = cl.Code()
while parser.hasMoreCommands():
parser.advance()
# if line read is blank or a comment
if parser.commandType == None:
continue
elif parser.commandType == 'A_COMMAND':
#parser.symbol is the decimal value to be converted in binary
value = "{0:b}".format(parser.symbol)
numZeroes = 16 - len(value)
for i in range(numZeroes):
hackfile.write("0")
hackfile.write(value + "\n")
elif parser.commandType == 'C_COMMAND':
# symbolic values of the fields of the C command
comp_symb = parser.comp
dest_symb = parser.dest
jump_symb = parser.jump
#binary representation of the fields of the C command
comp_bin = code.comp(comp_symb)
dest_bin = code.dest(dest_symb)
jump_bin = code.jump(jump_symb)
C_bin = '111' + comp_bin + dest_bin + jump_bin
hackfile.write(C_bin + "\n")
parser.asmfile.close()
hackfile.close()
I am really closing the file towards the end after exiting the while loop, so I am not sure why I am getting this error!
I did not use with since I was not sure how to make it fit in the code.
Also, I apologize for the messy/ugly code, still figuring Python out!

Recursive Hexadecimal Conversion Python 3

I've made a hexadecimal converter to practice recursion/recursive thinking. I, however, The recurssion doesn't appear to be happening as the functions seems to just output the result of 9 as of current.The code is as follows:
import math
curr=0
def convert(x):
L=len(x)
L-=1
sol=0
if L == 0:
return 0
else:
if x[curr]==["A","a"]:
v=10
elif x[curr]==["B","b"]:
v=11
elif x[curr]==["C","c"]:
v=12
elif x[curr]==["D","d"]:
v=13
elif x[curr]==["E","e"]:
v=14
elif x[curr]==["F","f"]:
v=15
else:
v=int(x[curr])
sol+=((v)*(16**(L-1)))
return sol + convert(x[curr+1])
def main():
print(convert('98A'))
main()
You were setting L = len(x) everytime you call the function. Here is one solution:
import math
def convert(x, L):
c = len(x) - 1
sol=0
if L > c:
return 0
else:
if (x[L]=="A" or x[L]=="a"):
v=10
elif (x[L]=="B" or x[L]=="b"):
v=11
elif (x[L]=="C" or x[L]=="c"):
v=12
elif (x[L]=="D" or x[L]=="d"):
v=13
elif (x[L]=="E" or x[L]=="e"):
v=14
elif (x[L]=="F" or x[L]=="f"):
v=15
else:
v=int(x[L])
sol+=((v)*(16**(c - L)))
print(sol)
return sol + convert(x, L + 1)
def main():
print(convert('98A', 0))
main()
You can use something like this:
class HexMap:
# mapping char to int
d = { hex(n)[2:]:n for n in range(16)}
def convert(x):
s = 0
# use reverse string and sum up - no need for recursion
for i,c in enumerate(x.lower()[::-1]):
s += HexMap.d[c]*16**i
return s
def main():
print(convert('98A'))
main()
Output:
2442
Recursive version:
# class HexMap: see above
def convert(x):
def convert(x,fak):
if not x:
return 0
else:
return HexMap.d[x[-1]]*16**fak + convert(x[:-1],fak+1)
return convert(x.lower(),0)
def main():
print(convert('98A'))
main()
Same output.

How to check if token is a float?

So I need to modify the following code so that the methods PostfixEval() and infixToPostfix() can take floats, as well as integers with more than one digit. I've tried isinstance(token,float) == True. Maybe I'm not using it correctly.
def infixToPostfix(infixexpr):
prec = {}
prec["*"] = 3
prec["/"] = 3
prec["+"] = 2
prec["-"] = 2
prec["("] = 1
opStack = Stack()
postfixList = []
tokenList = infixexpr.split()
for token in tokenList:
if token in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" or isinstance(token,int) == True :
postfixList.append(token)
elif token == '(':
opStack.push(token)
elif token == ')':
topToken = opStack.pop()
while topToken != '(':
postfixList.append(topToken)
topToken = opStack.pop()
else:
while (not opStack.isEmpty()) and \
(prec[opStack.peek()] >= prec[token]):
postfixList.append(opStack.pop())
opStack.push(token)
while not opStack.isEmpty():
postfixList.append(opStack.pop())
return " ".join(postfixList)
and
def postfixEval(postfixExpr): # also fix this to do floats
operandStack = Stack()
tokenList = postfixExpr.split()
for token in tokenList:
if isinstance(token,int) == True:
operandStack.push(int(token))
else:
operand2 = operandStack.pop()
operand1 = operandStack.pop()
result = doMath(token,operand1,operand2)
operandStack.push(result)
return operandStack.pop()
tokenList = infixexpr.split() creates a list of strings of which none could be a float. You could make a function to cast to float returning True if you could cast to float.
def is_float(s):
try:
float(s)
return True
except ValueError:
return False
Then:
lett_set = set("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
if token in lett_set or isfloat(token)
You can also return the float and use it in your other function:
def is_float(s):
try:
return float(s)
except ValueError:
return None
for token in tokenList:
test = is_float(token)
if test is not None: # catch potential 0
operandStack.push(test)
You can use the second version in both functions. You mention float in your title so I presume you can have floats which would fail trying to cast to int.
On a side note isinstance(token,int) == True etc.. can simpy be written isinstance(token,int), that will be True or False so any if isinstance(token,int) will be evaluated correctly

Evaluating infix expression with two stacks in python

This is my first time asking a question on here, and I am only doing this because I have spent the past week trying to figure this out and haven't been able to. I found similar questions, but the results did not help me. I have to take an infix expression and calculate the results using two stacks, one for the operator and one for the numbers. An example would be 6 - ( 5 - 3 ) * ( 4 + 2 ) = -6 or 3 * 11 / 8 + 5 – 4 * 7 = -18.875. I just cannot figure out how to get this to work. Currently my code is this:
class NumStack:
def __init__(self):
"""Create an empty stack."""
self._data = [] #nonpublic list instance
def __len__(self):
"""Return the number of elements in the stack."""
return len(self._data)
def is_empty(self):
"""Return True if the stack is empty."""
return len(self._data) == 0
def push(self,e):
"""Add element e to the top of the stack."""
self._data.append(e) #new item stored at end of list
print(self._data)
def top(self):
"""Return (but do not remove) the element at the top of the stack.
Raise Empty exception if the stack is empty"""
if self.is_empty():
return
return self._data[-1] #the last item in the list
def pop(self):
"""Remove and return the element from the top of the stack (i.e, LIFO)
Raise Empty exception if the stack is empty."""
if self.is_empty():
return "empty"
return self._data.pop() #remove last item from list
def str(self):
return self._data
class OperatorStack:
def __init__(self):
"""Create an empty stack."""
self._data = [] #nonpublic list instance
def __len__(self):
"""Return the number of elements in the stack."""
return len(self._data)
def is_empty(self):
"""Return True if the stack is empty."""
length = len(self._data)
if length == 0:
return True
else:
return False
def push(self,e):
"""Add element e to the top of the stack."""
self._data.append(e) #new item stored at end of list
print(self._data)
def top(self):
"""Return (but do not remove) the element at the top of the stack.
Raise Empty exception if the stack is empty"""
if self.is_empty():
return
return self._data[-1] #the last item in the list
def pop(self):
"""Remove and return the element from the top of the stack (i.e, LIFO)
Raise Empty exception if the stack is empty."""
length = len(self)
if length == 0:
print("list is empty")
else:
if self.is_empty():
return
return self._data.pop()
def str(self):
return self._data
def main():
expression = str(input("Enter an expression: "))
expression = expression.split()
print(expression)
N = NumStack()
O = OperatorStack()
new = []
NewOP = []
NewNum = [0,0]
for e in expression:
if e == '(' or e == ')' or e == '+' or e == '-' or e == '*' or e == '/':
O.push(e)
else:
N.push(e)
while O.is_empty() == False or N.is_empty() == False:
TmpOp = O.top()
if TmpOp == ')':
O.pop()
elif TmpOp == '(':
O.pop()
if TmpOp != '(' and TmpOp != ')':
new.append(N.pop())
new.append(O.pop())
print(TmpOp)
while TmpOp == ')':
if N.top() != "empty":
NewNum[1] = N.pop()
if N.top() != "empty":
NewNum[0] = N.top()
print(NewNum[0],NewNum[1])
if O.pop() == '+':
num = float(NewNum[1]) + float(NewNum[0])
new.append(num)
print(num)
O.pop()
break
elif O.pop() == '-':
num = float(NewNum[0]) - float(NewNum[1])
new.append(num)
print(num)
O.pop()
break
elif O.pop() == '*':
num = NewNum[1]*NewNum[0]
new.append(num)
print(num)
# O.pop()
break
elif O.pop() == '/':
num = NewNum[1]/NewNum[0]
new.append(num)
print(num)
# O.pop()
break
if O.top() == ')':
O.pop()
break
if O.__len__() == 0 and N.__len__() == 0:
break
continue
while TmpOp != ')' and TmpOp != '(':
new.append(N.pop())
new.append(O.pop())
print(new)
if O.__len__() == 0 and N.__len__() == 0:
break
print(new)
main()
I believe my classes to be correct, I just cannot find a way of extracting the needed information correctly. I am trying to pop the items into a list and when I get to a parenthesis I go ahead and perform the calculation. If I could just get the correct numbers into my list then I know I can get it to work. I just need to get the "new" to contain the correct numbers. With the problem: "6 - ( 5 - 3 ) * ( 4 + 2 )" I should get [6.0, '*', 2.0, '-', 6]. It is not coming out to that. I really appreciate any help that can be given.

Categories