Ad
Code
Diff
  • def parse(expr):
    
        class State:
            current = expr[0]
            tokens = []
    
        def exp():
            result = term()
            while State.current in ('+', '-'):
                if State.current == '+':
                    next_token()
                    result += term()
                if State.current == '-':
                    next_token()
                    result -= term()
            return result
    
        def factor():
            result = None
            if State.current[0].isdigit() or State.current[-1].isdigit():
                result = float(State.current)
                next_token()
            elif State.current is '(':
                next_token()
                result = exp()
                next_token()
            return result
    
        def next_token():
            State.tokens = State.tokens[1:]
            State.current = State.tokens[0] if len(State.tokens) > 0 else None
    
        def term():
            result = factor()
            while State.current in ('*', '/'):
                if State.current == '*':
                    next_token()
                    result *= term()
                if State.current == '/':
                    next_token()
                    result /= term()
            return result
    
        for i in range(len(expr)):
            if expr[i].isdigit() and i > 0 and (State.tokens[-1].isdigit() or State.tokens[-1][-1] is '.'):
                State.tokens[-1] += expr[i]
            elif expr[i] is '.' and i > 0 and State.tokens[-1].isdigit():
                State.tokens[-1] += expr[i]
            else:
                State.tokens.append(expr[i])
    
        return exp()
    
    • def parse(expr): #The main parser
    • ps = 0 #Number of open parentheses
    • cval = 0 #Current value
    • op = "+" #Current operation
    • accum = "" #Accumulating value
    • for i in range(len(expr)):
    • c = expr[i]
    • if c in ["+","-"] and not ps: #Operation not inside parens
    • if op=="+": #Addition
    • cval+=parse_fact(accum)
    • else: #Subtraction
    • cval-=parse_fact(accum)
    • accum = "" #Reset the value
    • op = c #New operation once that was calculated
    • else:
    • if c=="(": ps+=1 #Open paren
    • if c==")": ps-=1 #Close paren
    • accum+=c #Add a character to accumulating value
    • if op=="+": #Do the operation one more time
    • cval+=parse_fact(accum)
    • else:
    • cval-=parse_fact(accum)
    • return cval
    • def parse_fact(term):
    • ps = 0
    • cval = 1
    • op = "*"
    • accum = ""
    • for i in range(len(term)):
    • c = term[i]
    • if c in ["*","/"] and not ps:
    • if op=="*":
    • cval*=parse_val(accum)
    • else:
    • cval/=parse_val(accum)
    • accum = ""
    • op = c
    • else:
    • if c=="(": ps+=1
    • if c==")": ps-=1
    • accum+=c
    • if op=="*":
    • cval*=parse_val(accum)
    • else:
    • cval/=parse_val(accum)
    • return cval
    • def parse_val(val):
    • if val[0] == "(": #Parenthetical expression
    • return parse(val[1:-1]) #Cut off parentheses and reevaluate
    • else:
    • return float(val) #Not parenthetical
    • def parse(expr):
    • class State:
    • current = expr[0]
    • tokens = []
    • def exp():
    • result = term()
    • while State.current in ('+', '-'):
    • if State.current == '+':
    • next_token()
    • result += term()
    • if State.current == '-':
    • next_token()
    • result -= term()
    • return result
    • def factor():
    • result = None
    • if State.current[0].isdigit() or State.current[-1].isdigit():
    • result = float(State.current)
    • next_token()
    • elif State.current is '(':
    • next_token()
    • result = exp()
    • next_token()
    • return result
    • def next_token():
    • State.tokens = State.tokens[1:]
    • State.current = State.tokens[0] if len(State.tokens) > 0 else None
    • def term():
    • result = factor()
    • while State.current in ('*', '/'):
    • if State.current == '*':
    • next_token()
    • result *= term()
    • if State.current == '/':
    • next_token()
    • result /= term()
    • return result
    • for i in range(len(expr)):
    • if expr[i].isdigit() and i > 0 and (State.tokens[-1].isdigit() or State.tokens[-1][-1] is '.'):
    • State.tokens[-1] += expr[i]
    • elif expr[i] is '.' and i > 0 and State.tokens[-1].isdigit():
    • State.tokens[-1] += expr[i]
    • else:
    • State.tokens.append(expr[i])
    • return exp()