Refactored some code to try and make it more inline with best pratices. Renamed parser as it conflicted with a standard Python library.
This commit is contained in:
+130
@@ -0,0 +1,130 @@
|
||||
from base_unit import Token, TokenType
|
||||
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)" %(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.bak = deque()
|
||||
self.variables = {}
|
||||
self.tokens = tokens
|
||||
self.current_token = None
|
||||
self.advance_current_token()
|
||||
self.ast = self.generate_ast()
|
||||
|
||||
|
||||
def get_tokens(self):
|
||||
new_list = []
|
||||
|
||||
for t in self.bak:
|
||||
if t.type == TokenType.variable:
|
||||
if t.value in self.variables:
|
||||
new_list.append(Token(self.variables[t.value], TokenType.constant))
|
||||
else:
|
||||
new_list.append(Token(t.value, t.type))
|
||||
return new_list
|
||||
|
||||
def advance_current_token(self):
|
||||
|
||||
if len(self.tokens) > 0:
|
||||
if self.current_token != None: self.bak.append(self.current_token)
|
||||
self.current_token = self.tokens.popleft()
|
||||
|
||||
def factor(self):
|
||||
if self.current_token.type == TokenType.constant:
|
||||
node = Num(self.current_token)
|
||||
self.advance_current_token()
|
||||
return node
|
||||
elif self.current_token.type == 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 == 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 == 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 (TokenType.multiply, 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 (TokenType.add, 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
|
||||
Reference in New Issue
Block a user