Add support for not using spaces, align to sample input, optimizations
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
3 + 5 - -2 - 2
|
||||
x = 3 + 5 - -2 - 2
|
||||
y = x - (x - 2)
|
||||
y
|
||||
ans = (17 - (5 - 20)) - (1 - 11)
|
||||
ans
|
||||
|
||||
ans = ans - (-42 - ans)
|
||||
ans
|
||||
(17-(5-20))-(1-11)
|
||||
+27
-26
@@ -7,6 +7,8 @@
|
||||
|
||||
# System Imports
|
||||
import sys
|
||||
import re
|
||||
|
||||
class Interpreter:
|
||||
def __init__(this):
|
||||
# Init basic local variables
|
||||
@@ -26,6 +28,8 @@ class Interpreter:
|
||||
if this.inputRaw != "": this.processAssignments(this.inputRaw)
|
||||
except EOFError:
|
||||
break
|
||||
except KeyboardInterrupt:
|
||||
break
|
||||
|
||||
def processAssignments(this, inputString):
|
||||
# First Step - Determine if assignment operator present
|
||||
@@ -37,9 +41,7 @@ class Interpreter:
|
||||
return
|
||||
# If there are, we save to the variable, not print
|
||||
assignmentSplit = inputString.split("=") # First Arg: variable, Second Arg: expression
|
||||
assignmentSplit[0] = assignmentSplit[0][:-1] # Remove trailing space in variable
|
||||
assignmentSplit[1] = assignmentSplit[1][1:] # Remove leading space in expression
|
||||
this.variables[assignmentSplit[0]] = this.processParenthesis(assignmentSplit[1])
|
||||
this.variables[assignmentSplit[0].strip()] = this.processParenthesis(assignmentSplit[1].strip())
|
||||
this.inputRaw = " " # Reset input to forgo the \n
|
||||
else:
|
||||
# If there are no operators, string is set to be evaluated
|
||||
@@ -48,7 +50,6 @@ class Interpreter:
|
||||
def processParenthesis(this,inputString):
|
||||
# Second Step - Determine if expression contains parenthesis
|
||||
# Recursively designed function to evaluate parenthesis from left to right, inner to outer until no more remain
|
||||
# print(inputString)
|
||||
if inputString.count('(') == 0:
|
||||
# No parenthesis or all parenthesis evaluated
|
||||
return this.evaluate(inputString)
|
||||
@@ -70,32 +71,32 @@ class Interpreter:
|
||||
def evaluate(this,inputString):
|
||||
# Evalute the "cleaned" expression
|
||||
# Stripped out all the assignment operators and parenthesis
|
||||
expressionMap = inputString.split(" ")
|
||||
# Proper type conversion / verification
|
||||
expressionMap = list(filter(None, re.split('([^a-zA-Z0-9])', inputString.replace(" ", ""))))
|
||||
# Varible substitution
|
||||
for i in range(len(expressionMap)):
|
||||
# If there is a variable in the expression, substitute the current value in the proper list slot
|
||||
if expressionMap[i] in this.variables:
|
||||
expressionMap[i] = int(this.variables[expressionMap[i]])
|
||||
elif expressionMap[i][:1] == "-" and len(expressionMap[i]) != 1 and expressionMap[i][1:] in this.variables:
|
||||
expressionMap[i] = int("-"+this.variables[expressionMap[i][1:]])
|
||||
elif expressionMap[i] != '+' and expressionMap[i] != '-':
|
||||
# Verifying all operands are proper ints
|
||||
if expressionMap[i] in this.variables: expressionMap[i] = this.variables[expressionMap[i]]
|
||||
total = 0
|
||||
# If there is math to be done, do math
|
||||
if len(expressionMap) > 1:
|
||||
# Move around the expression looking to bind operators to operations
|
||||
for i in range(len(expressionMap)-1):
|
||||
# If we are at the start of the line, or there is an operation that is not followed by an operation, bind
|
||||
if (expressionMap[i] == "+" or expressionMap[i] == "-") and (expressionMap[i+1] != "+" and expressionMap[i+1] != "-") or i == 0:
|
||||
try:
|
||||
expressionMap[i] = int(expressionMap[i])
|
||||
# int allows + and - to be bound to an integer and reflected in its positivity/negation. By doing this, all elements of the string can simple be added
|
||||
total+=(int(expressionMap[i]+expressionMap[i+1])) if (expressionMap[i] == "+" or expressionMap[i] == "-") and (expressionMap[i+1] != "+" and expressionMap[i+1] != "-") else (int(expressionMap[i]))
|
||||
except:
|
||||
# throw an error if something in the string is not an operation or a int
|
||||
Interpreter.throwError("evaluate",f"Unknown symbol '{expressionMap[i]}'. '{expressionMap[i]}' is not a valid input or an undefined variable.")
|
||||
return "" # empty string for formatting
|
||||
# After all items in list are either ints or operations, perform operations
|
||||
# Properly formatting list has the following structure
|
||||
# [operand, operation, operand, operation, operand, ...]
|
||||
# Therefore, operating from left to right, take the first set of three (two operands, one operations)
|
||||
# and store the result in list slot 0
|
||||
# Remove list slots 1 and 2, and shift the rest of the list down so the next set (one operation, one operand) is in the slot (del)
|
||||
# When there only remains one (operand) with the result stored, convert back to string and return
|
||||
while len(expressionMap) > 1:
|
||||
expressionMap[0] = expressionMap[0] + expressionMap[2] if expressionMap[1] == "+" else expressionMap[0] - expressionMap[2]
|
||||
del expressionMap[1:3]
|
||||
return str(expressionMap[0])
|
||||
return ""
|
||||
# If there is a - and a - (double negation), swap next operator to a + and carry on
|
||||
# Swapping next operation to a + is the same as subtracting a negative, you add. this flips the sign of the next operator and ignores the current negation
|
||||
# A combination + and - is ignored as the negation will be bound to the int and the plus will be discarded
|
||||
elif expressionMap[i] == "-" and expressionMap[i+1] == "-":
|
||||
expressionMap[i+1] = '+'
|
||||
else: #simple math, jsut return what's there
|
||||
total = expressionMap[0]
|
||||
return str(total)
|
||||
|
||||
PMPVInterpreter = Interpreter()
|
||||
PMPVInterpreter.startCommandLine()
|
||||
Reference in New Issue
Block a user