Files
calc_engine/parser.py
T

119 lines
2.9 KiB
Python

import ptoken as token
import tokenizer
import uuid
from collections import deque
class Op:
def __init__(self, left, op, right):
self.left = left
self.op = op
self.right = right
def __str__(self):
return "%s (%s) and (%s)" %(token.TokenType.get_operator_verb(self.op), self.left, self.right)
class Num:
def __init__(self, token):
self.value = token.value
def __str__(self):
return self.value
class Variable:
def __init__(self, token):
self.symbol = token.value
self.value = None
def __str__(self):
if self.value == None:
return self.symbol
else:
return str(self.value)
class Parser:
def __init__(self, tokens):
if len(tokens) == 0:
raise ValueError("Token list can't be empty")
self.variables = {}
self.tokens = tokens
self.current_token = None
self.advance_current_token()
self.ast = self.generate_ast()
def advance_current_token(self):
if len(self.tokens) > 0:
self.current_token = self.tokens.popleft()
def factor(self):
if self.current_token.type == token.TokenType.constant:
node = Num(self.current_token)
self.advance_current_token()
return node
elif self.current_token.type == token.TokenType.variable:
node = Variable(self.current_token)
self.variables[self.current_token.value] = node
self.advance_current_token()
return node
elif self.current_token.type == token.TokenType.exp_start:
self.advance_current_token() # (
node = self.topLevel()
self.advance_current_token() # )
return node
def lowLevel(self):
node = self.factor()
while self.current_token.type == token.TokenType.power:
tmp = self.current_token
self.advance_current_token()
node = Op(left=node, op=tmp.type, right=self.factor())
return node
def midLevel(self):
node = self.lowLevel()
while self.current_token.type in (token.TokenType.multiply, token.TokenType.divide):
tmp = self.current_token
self.advance_current_token()
node = Op(left=node, op=tmp.type, right=self.lowLevel())
return node
def topLevel(self):
node = self.midLevel()
while self.current_token.type in (token.TokenType.add, token.TokenType.subtract):
tmp = self.current_token
self.advance_current_token()
node = Op(left=node, op=tmp.type, right=self.midLevel())
return node
def generate_ast(self):
return self.topLevel()
def update_variable(self, symbol, value):
if symbol in self.variables:
self.variables[symbol].value = float(value)
else:
raise ValueError("Variable value must be a number.", value)
def update_variables(self, variables):
if len(variables) == 0:
return
for symbol in variables:
if symbol in self.variables:
self.variables[symbol].value = float(variables[symbol])
else:
raise ValueError("Variable value must be a number.")
def get_variable_value_pairs(self):
keys = {}
for symbol in self.variables:
keys[symbol] = self.variables[symbol].value
return keys