diff --git a/in.txt b/in.txt new file mode 100644 index 0000000..33893dc --- /dev/null +++ b/in.txt @@ -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) diff --git a/interpreter.py b/interpreter.py index 8ba459e..397f9c8 100644 --- a/interpreter.py +++ b/interpreter.py @@ -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 - 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 - try: - expressionMap[i] = int(expressionMap[i]) - except: - 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]) + expressionMap = list(filter(None, re.split('([^a-zA-Z0-9])', inputString.replace(" ", "")))) + # Varible substitution + for i in range(len(expressionMap)): + 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: + # 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 "" + # 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() \ No newline at end of file diff --git a/out.txt b/out.txt new file mode 100644 index 0000000..954d773 --- /dev/null +++ b/out.txt @@ -0,0 +1,10 @@ +8 + + +2 + +42 + + +126 +42