138 lines
4.4 KiB
Python
138 lines
4.4 KiB
Python
import ptoken as token
|
|
|
|
def get_tokens_from_expression_string(expression_string):
|
|
|
|
#Takes user input of an actuarial formula and parses the formula to id its components.
|
|
#:return: tokens (List of objects of CToken class).
|
|
|
|
tokens = [] # List of objects of CToken class
|
|
tmp = ""
|
|
parsing_number = False
|
|
symbols_dic = {} # Dictionary to keep track of the no. of times each variable appears.
|
|
variable_is_negative = False
|
|
|
|
for i in range(0, len(expression_string)):
|
|
c = expression_string[i]
|
|
if c == '.' or c.isdigit():
|
|
if c == '.' and tmp.count('.') == 1:
|
|
raise SyntaxError("Invalid grammar, to many periods in number. Found at position " + str (i) + ".")
|
|
if len(tokens) > 1:
|
|
lookBehind = tokens[-1]
|
|
if lookBehind.type == token.TokenType.exp_end:
|
|
tokens.append(token.Token("^", token.TokenType.power))
|
|
if (i + 1) == len(expression_string):
|
|
tokens.append(token.Token(tmp + c, token.TokenType.constant))
|
|
parsing_number = True
|
|
tmp = tmp + c
|
|
continue
|
|
|
|
elif c == '-' and not parsing_number:
|
|
if expression_string[i + 1] == '.' or expression_string[i + 1].isdigit():
|
|
if token.TokenType.get_operator(tokens[-1].value) != token.TokenType.unknown:#tokens[-1].type == token.TokenType
|
|
#print(tokens[-1].value)
|
|
#tokens.append(token.Token('+', token.TokenType.add))
|
|
parsing_number = True
|
|
tmp = "-"
|
|
elif tokens[-1].type == token.TokenType.exp_start:
|
|
parsing_number = True
|
|
tmp = "-"
|
|
elif tokens[-1].type == token.TokenType.exp_end:
|
|
tokens.append(token.Token(c, token.TokenType.get_operator(c)))
|
|
parsing_number = False
|
|
tmp = ""
|
|
elif expression_string[i + 1].isalpha():
|
|
#Must be a variable.
|
|
if tokens[-1].type == token.TokenType.exp_start:
|
|
variable_is_negative = True
|
|
else:
|
|
tokens.append(token.Token(c, token.TokenType.get_operator(c)))
|
|
parsing_number = False
|
|
tmp = ""
|
|
|
|
elif c == '(':
|
|
if parsing_number:
|
|
tokens.append(token.Token(tmp, token.TokenType.constant))
|
|
tokens.append(token.Token("*", token.TokenType.multiply))
|
|
tokens.append(token.Token("(", token.TokenType.exp_start))
|
|
parsing_number = False
|
|
tmp = ""
|
|
continue
|
|
elif c == ')':
|
|
if parsing_number:
|
|
tokens.append(token.Token(tmp, token.TokenType.constant))
|
|
tokens.append(token.Token(")", token.TokenType.exp_end))
|
|
parsing_number = False
|
|
tmp = ""
|
|
continue
|
|
elif token.TokenType.get_operator(c) != token.TokenType.unknown:
|
|
if parsing_number:
|
|
tokens.append(token.Token(tmp, token.TokenType.constant))
|
|
tokens.append(token.Token(c, token.TokenType.get_operator(c)))
|
|
parsing_number = False
|
|
tmp = ""
|
|
continue
|
|
elif c != ' ':
|
|
if len(tokens) > 1:
|
|
lookBehind = tokens[-1]
|
|
if lookBehind.type == token.TokenType.exp_end:
|
|
tokens.append(token.Token("^", token.TokenType.power))
|
|
|
|
if (i + 1) < len(expression_string):
|
|
lookAHead = expression_string[i + 1]
|
|
if lookAHead == '(':
|
|
tokens.append(token.Token(c, token.TokenType.variable))
|
|
tokens.append(token.Token("*", token.TokenType.multiply))
|
|
tmp = ""
|
|
parsing_number = False
|
|
continue
|
|
if parsing_number:
|
|
tokens.append(token.Token(tmp, token.TokenType.constant))
|
|
tokens.append(token.Token("*", token.TokenType.multiply))
|
|
if c in symbols_dic.keys():
|
|
symbols_dic[c] += 1
|
|
else:
|
|
symbols_dic[c] = 1
|
|
tokens.append(token.Token(c + str(symbols_dic[c]), token.TokenType.variable, variable_is_negative))
|
|
variable_is_negative = False
|
|
parsing_number = False
|
|
tmp = ""
|
|
|
|
return tokens
|
|
|
|
def peek_list(tokens):
|
|
if tokens:
|
|
return tokens[-1]
|
|
else:
|
|
raise IndexError("The token list is empty.", tokens)
|
|
|
|
def replace_variables(tokens, new_constants):
|
|
newTokenList = []
|
|
for t in tokens:
|
|
if t.type == token.TokenType.variable:
|
|
if not t.is_negative_variable:
|
|
newTokenList.append(token.Token(new_constants.pop(0), token.TokenType.constant))
|
|
else:
|
|
newTokenList.append(token.Token(new_constants.pop(0) * -1, token.TokenType.constant))
|
|
else:
|
|
newTokenList.append(token.Token(t.value, t.type))
|
|
|
|
return newTokenList
|
|
|
|
def print_token_list(tokens):
|
|
for tk in tokens:
|
|
if tk.type == token.TokenType.variable:
|
|
if tk.is_negative_variable:
|
|
print("-%s " %(tk.value), end = "")
|
|
else:
|
|
print("%s " %(tk.value), end ="")
|
|
else:
|
|
print("%s " %(tk.value), end = "")
|
|
print()
|
|
|
|
def stringify_token_list(tokens):
|
|
text = ''
|
|
for tk in tokens:
|
|
text += str(tk.value)
|
|
text += '\n'
|
|
return text
|