parser: make many visitors handle non-mandatory traversals
This commit is contained in:
parent
4ef1e63ee4
commit
2b9943cdbf
1 changed files with 20 additions and 16 deletions
|
|
@ -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:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue