py-calc/parser_.py
2026-04-10 16:39:57 +02:00

174 lines
4.1 KiB
Python

from ParserError import ParserError
from tokens import TokenType
from nodes import *
class Parser:
def __init__(self, tokens):
self.tokens = iter(tokens)
self.advance()
def raise_error(self):
raise ParserError("Invalid syntax")
def advance(self):
try:
self.current_token = next(self.tokens)
except StopIteration:
self.current_token = None
def parse(self):
if self.current_token == None:
return None
result = self.level1_operators()
if self.current_token != None:
self.raise_error()
return result
# Takes care of (+ -)
def level1_operators(self):
result = self.level2_operators()
while self.current_token != None and self.current_token.type in (TokenType.PLUS, TokenType.MINUS):
if self.current_token.type == TokenType.PLUS:
self.advance()
result = AddNode(result, self.level2_operators())
elif self.current_token.type == TokenType.MINUS:
self.advance()
result = SubtractNode(result, self.level2_operators())
return result
def level2_operators(self):
result = self.level3_operators()
while self.current_token != None and self.current_token.type in (TokenType.MULTIPLY, TokenType.DIVIDE):
if self.current_token.type == TokenType.MULTIPLY:
self.advance()
result = MultiplyNode(result, self.level3_operators())
elif self.current_token.type == TokenType.DIVIDE:
self.advance()
result = DivideNode(result, self.level3_operators())
return result
def level3_operators(self):
result = self.level4_operators()
while self.current_token != None and self.current_token.type == TokenType.POWER:
self.advance()
result = PowerNode(result, self.level4_operators())
return result
def level4_operators(self):
result = self.level5_operators()
while self.current_token != None and self.current_token.type in (TokenType.MODULE, TokenType.FACTORIAL):
if self.current_token.type == TokenType.MODULE:
self.advance()
result = ModuleNode(result, self.level5_operators())
elif self.current_token.type == TokenType.FACTORIAL:
self.advance()
result = FactorialNode(self.level5_operators(result))
return result
def level5_operators(self, num=None):
if num != None:
result = num
else:
result = self.level6_operators()
while self.current_token != None and self.current_token.type in (TokenType.AVERAGE, TokenType.MAXIMUM, TokenType.MINIMUM):
if self.current_token.type == TokenType.AVERAGE:
self.advance()
result = AverageNode(result, self.level6_operators())
elif self.current_token.type == TokenType.MAXIMUM:
self.advance()
result = MaximumNode(result, self.level6_operators())
elif self.current_token.type == TokenType.MINIMUM:
self.advance()
result = MinimumNode(result, self.level6_operators())
return result
def level6_operators(self):
token = self.current_token
if token.type == TokenType.LBRACKET:
self.advance()
result = self.level1_operators()
if self.current_token.type != TokenType.RBRACKET:
self.raise_error()
self.advance()
return result
elif token.type == TokenType.NUMBER:
self.advance()
return NumberNode(token.value)
elif token.type == TokenType.PLUS:
self.advance()
return PlusNode(self.level6_operators())
elif token.type == TokenType.MINUS:
self.advance()
return MinusNode(self.level6_operators())
elif token.type == TokenType.NEGATE:
self.advance()
return NegateNode(self.level6_operators())
return None
@staticmethod
def strip_str(level1_operators : str):
"""removes all unnecessery characters from level1_operatorsession
Args:s
level1_operators (str): the level1_operatorsession that will be stripped
Raises:
ParserError: Error if parsing failed
Returns:
str: The level1_operatorsession without the unnecessery characters
"""
try:
temp_list = level1_operators.split()
level1_operators = ''.join(temp_list)
level1_operators = level1_operators.replace('\\n', '')
level1_operators = level1_operators.replace('\\t', '')
return level1_operators
except Exception as e:
raise ParserError("Error during parsing: {e}")