diff --git a/compiler/parser.py b/compiler/parser.py index ff967b7..43c9bdd 100644 --- a/compiler/parser.py +++ b/compiler/parser.py @@ -91,19 +91,21 @@ class Parser: raise UnexpectedTokenError(self.token, "variable identifier") @tracer.trace_method - def binary_op(self, operand_func: Callable[[], Value], operators: Dict[Tokens, Value]): - operand = operand_func() + def binary_op(self, operand_func: Callable[[bool], Value], operators: Dict[Tokens, Value], mandatory: bool = True): + operand = operand_func(mandatory) + if not operand and mandatory: + raise UnexpectedTokenError(operand, "operand") while operator := self.accept(*list(operators.keys())): node_type = operators[operator.kind] - operand2 = operand_func() + operand2 = operand_func(True) operand = node_type(operand, operand2) logger.debug(f"{node_type.__name__} of the following operands: {operand} and {operand2}") return operand @tracer.trace_method - def factor(self) -> Value: + def factor(self, mandatory: bool = False) -> Value: if self.accept(Tokens.Parens_Left): v = self.expression() self.expect(Tokens.Parens_Right) @@ -112,42 +114,44 @@ class Parser: return num elif variable := self.variable(): return variable - else: + elif mandatory: raise UnexpectedTokenError(self.token, "parenthesized expression, number or variable") @tracer.trace_method - def term(self) -> Value: + def term(self, mandatory: bool = False) -> Value: return self.binary_op(self.factor, operators={ Tokens.Op_Multiply: Product, Tokens.Op_Divide: Division, - }) + }, mandatory=mandatory) @tracer.trace_method - def summation(self) -> Sum: + def summation(self, mandatory: bool = True) -> Sum: return self.binary_op(self.term, operators={ Tokens.Op_Plus: Sum, Tokens.Op_Minus: Sub, - }) + }, mandatory=mandatory) @tracer.trace_method def assignment(self, mandatory: bool = False) -> Assignment: if ident := self.identifier(mandatory): self.expect(Tokens.Equal) - expr = self.expression() + expr = self.expression(mandatory=True) return Assignment(ident, expr) elif mandatory: raise UnexpectedTokenError(self.token, "assignment") @tracer.trace_method - def expression(self) -> Value: - if self.peek_several(Tokens.Identifier, Tokens.Equal): - return Expression(self.assignment()) - else: - return Expression(self.summation()) + def expression(self, mandatory: bool = False) -> Value: + if self.peek_several(Tokens.Identifier, Tokens.Equal) and (assignment := self.assignment(mandatory)): + return Expression(assignment) + elif summation := self.summation(mandatory): + return Expression(summation) + elif mandatory: + raise UnexpectedTokenError(self.token, "expression") @tracer.trace_method def root(self) -> Node: - return self.expression() + return self.expression(mandatory=True) def parse(self) -> Node: try: