Last active
July 1, 2020 17:28
-
-
Save jatinsharrma/e64bfbe225d9d97d770873d4700e5765 to your computer and use it in GitHub Desktop.
Mathematical Expression Evaluator : For Calculator Application
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#-------------------------------------------------------------------- | |
#--------------Mathematical Expresion Evaluater---------------------- | |
#-------------------------------------------------------------------- | |
'''Logic: | |
this program makes use of the operator precedence parser concept. | |
(An operator precedence parser is a Compiler Design Concept) | |
There are checkpoint you can uncomment those to see how code is running | |
It can try to delete wrong litreals and evaluate the expression. (You have to do some modification where literal function is called to make use of this feature) | |
You can uncomment the print statements to see where program is corrrecting epression. | |
''' | |
stack = [] # Main stack which saves all literals generated | |
numeral = False # If true : Seen Number/Decimal Previously else : Seen an Operator Previously | |
decimal = False # if true : Used decimal in current number else: no decimal used in current number | |
parflag = False # if true : Seen a closing bracket else : No closing bracket encountered | |
parCount = 0 # keep count of starting brackets. // Note : Not a full proof plan to check bracket matching | |
wrongFlag = False # If true : Means wrong expression else: expression is right | |
negativeFlag = False # if true we have seen a negative sign after an operator else no negative sign | |
# Evaluates the expression | |
def operatorPrecedence(a): | |
stack1 = ["$"] | |
stack2 = [] | |
i = 0 | |
if parCount == 0: | |
while i!= len(a): | |
#print(a[i],stack1,stack2) | |
if str(a[i]) not in "/+-*()": | |
stack2.append(float(a[i])) | |
else: | |
if a[i] == "(": | |
stack1.append(a[i]) | |
elif a[i] == ")": | |
if "(" not in stack1 : | |
wrongFlag = True | |
return "Wrong" | |
if stack1[0] != "(": | |
while stack1[-1] != "(": | |
calculateAndDelete(a,stack1,stack2) | |
stack1.pop() | |
else: | |
previous = stack1[-1] | |
if precedence(previous,a[i]): | |
stack1.append(a[i]) | |
else: | |
calculateAndDelete(a,stack1,stack2) | |
stack1.append(a[i]) | |
i+=1 | |
#print(stack2,stack1) | |
while len(stack1) > 1: | |
calculateAndDelete(a,stack1,stack2) | |
#print(stack2,stack1) | |
return stack2[-1] if stack2 else 0 | |
else: | |
print("wrong") | |
wrongFlag = True | |
# Tell the precedence // Note here * and / are of same precedence. I haven't implemented Leght to right precedence | |
def precedence(op1,op2): | |
if op1 in "+-" and op2 in "*/": | |
return True | |
if op1 in "$(" and op2 in "+-*/": | |
return True | |
return False | |
# Calculated the sub expression and return to operatorPrecedence function | |
def operation(operant1, operant2, operator): | |
if operator == "*": return operant1 * operant2 | |
if operator == "+": return operant1 + operant2 | |
if operator == "-": return operant1 - operant2 | |
if operator == "/": return operant1 / operant2 | |
# Evalutes the smaller expresion using operation function and also pops out literals which are used to evaluate | |
def calculateAndDelete(a,b,c): | |
operant2 = c.pop() | |
operant1 = c.pop() | |
operator = b.pop() | |
c.append(operation(operant1, operant2, operator)) | |
# Divides the input into the literals | |
def literals2(a): | |
global numeral | |
global stack | |
global parCount | |
global parflag | |
global decimal | |
global wrongFlag | |
global negativeFlag | |
if a: | |
# When we have seen no number or an operator and no closing bracket previously | |
if not(numeral or parflag): | |
if a == ("(") : | |
stack.append(a) | |
parCount += 1 | |
elif a ==(")") and not parCount: | |
#print("wrong 1 ") | |
wrongFlag = True | |
elif a == ("-") and not negativeFlag: | |
stack.append(a) | |
numeral = True | |
negativeFlag = True | |
elif not (a in "+-*/)."): | |
stack.append(a) | |
numeral = True | |
parflag = False | |
negativeFlag = False | |
elif a == "." and not decimal: | |
stack.append("0.") | |
numeral = True | |
decimal = True | |
else: | |
#print("Wrong 2 ") | |
wrongFlag = True | |
# When we have seen one/more numeral or no operator and no closing bracket before | |
elif numeral and not parflag: | |
if a == ")" and parCount: | |
stack.append(a) | |
parflag = True | |
numeral = False | |
decimal = False | |
parCount -= 1 | |
elif not (a in "-+/*()."): | |
stack.append(stack.pop() + a) | |
negativeFlag = False | |
elif a == "." and not decimal: | |
decimal = True | |
stack.append(stack.pop() + a) | |
elif a == "-" and negativeFlag: | |
pass | |
#print("Wrong 7") | |
elif a in "-+/*" and not negativeFlag: | |
stack.append(a) | |
numeral = False | |
parflag + False | |
decimal = False | |
else: | |
#print("wrong 3") | |
wrongFlag = True | |
# When we have not seen any numeral or an operator and closing bracket | |
elif not numeral and parflag: | |
if a in "+-*/": | |
stack.append(a) | |
parflag = False | |
elif a == ")" and parCount: | |
parCount -= 1 | |
stack.append(a) | |
else: | |
#print("wrong 4") | |
wrongFlag = True | |
#print(numeral,parflag,negativeFlag) | |
else: | |
#print("Wrong 5") | |
wrongFlag = True | |
# just a calling function | |
a = "--11++(-2)+3" | |
for i in a: | |
literals2(i) | |
# if wrongFlag == True: | |
# break | |
print(stack) | |
if (numeral or parflag) and not wrongFlag: | |
print(operatorPrecedence(stack)) | |
else: | |
print("Wrong 6") | |
#--------------------------------------------------------------------- | |
#-------------Sample Output with checkpoint uncommented--------------- | |
#--------------------------------------------------------------------- | |
''' | |
Finding literals | |
True False | |
['1'] | |
False False | |
['1', '+'] | |
True False | |
['1', '+', '1'] | |
True False | |
['1', '+', '11'] | |
False False | |
['1', '+', '11', '+'] | |
False False | |
['1', '+', '11', '+', '('] | |
True False | |
['1', '+', '11', '+', '(', '1'] | |
False True | |
['1', '+', '11', '+', '(', '1', ')'] | |
Evalutaing Expression | |
1 ['$'] [] | |
+ ['$'] [1.0] | |
11 ['$', '+'] [1.0] | |
+ ['$', '+'] [1.0, 11.0] | |
( ['$', '+'] [12.0] | |
1 ['$', '+', '('] [12.0] | |
) ['$', '+', '('] [12.0, 1.0] | |
[12.0, 1.0] ['$', '+'] | |
[13.0] ['$'] | |
13.0 | |
''' | |
#----------------------------------------------------------------- | |
#------------Just a initial try for finding literals ------------- | |
#------------------It do not work with decimals------------------- | |
#----------------------------------------------------------------- | |
#operator = False | |
# def literals(a): | |
# global stack | |
# global operator | |
# global numeral | |
# global parCount | |
# global parflag | |
# if operator == False and numeral == False: | |
# if a == "(": | |
# stack.append(a) | |
# parCount += 1 | |
# elif a not in "/+*" and not parflag: | |
# stack.append(a) | |
# numeral = True | |
# parflag = False | |
# elif a == ")" and parflag and parCount: | |
# stack.append(a) | |
# parflag = True | |
# parCount -= 1 | |
# elif a in "+-/*" and parflag: | |
# stack.append(a) | |
# operator = True | |
# else: | |
# print("wrong expression") | |
# elif numeral == True and operator == False: | |
# if parCount and a ==")": | |
# stack.append(a) | |
# numeral = False | |
# parflag = True | |
# parCount -= 1 | |
# elif parCount == 0 and a == ")": | |
# print("wrong") | |
# elif a == "(": | |
# print("wromg") | |
# elif a not in "/+-*": | |
# stack.append(stack.pop() + a) | |
# numeral = True | |
# else: | |
# stack.append(a) | |
# numeral = False | |
# operator = True | |
# parflag = False | |
# elif numeral == False and operator == True: | |
# if a == "(": | |
# stack.append(a) | |
# parCount += 1 | |
# elif a == ")": | |
# print("wrong") | |
# elif a not in "/+*": | |
# stack.append(a) | |
# numeral = True | |
# operator = False | |
# parflag =True | |
# else : | |
# print("wrong expression") | |
# #print(operatorPrecedence([1,"+","(",3,"*",4,")"])) | |
# #print(operatorPrecedence([1, "*", ")",3, ")","+",5,"(" ,")","/",4])) | |
# print(operatorPrecedence([1, "*",3, "+","(",5,"*" ,6,")","/",4])) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment