parser: make many visitors handle non-mandatory traversals

This commit is contained in:
Antoine Viallon 2023-05-12 01:32:07 +02:00
parent 4ef1e63ee4
commit 2b9943cdbf
Signed by: aviallon
GPG key ID: D126B13AB555E16F

View file

@ -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: