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")
|
raise UnexpectedTokenError(self.token, "variable identifier")
|
||||||
|
|
||||||
@tracer.trace_method
|
@tracer.trace_method
|
||||||
def binary_op(self, operand_func: Callable[[], Value], operators: Dict[Tokens, Value]):
|
def binary_op(self, operand_func: Callable[[bool], Value], operators: Dict[Tokens, Value], mandatory: bool = True):
|
||||||
operand = operand_func()
|
operand = operand_func(mandatory)
|
||||||
|
if not operand and mandatory:
|
||||||
|
raise UnexpectedTokenError(operand, "operand")
|
||||||
|
|
||||||
while operator := self.accept(*list(operators.keys())):
|
while operator := self.accept(*list(operators.keys())):
|
||||||
node_type = operators[operator.kind]
|
node_type = operators[operator.kind]
|
||||||
operand2 = operand_func()
|
operand2 = operand_func(True)
|
||||||
operand = node_type(operand, operand2)
|
operand = node_type(operand, operand2)
|
||||||
logger.debug(f"{node_type.__name__} of the following operands: {operand} and {operand2}")
|
logger.debug(f"{node_type.__name__} of the following operands: {operand} and {operand2}")
|
||||||
|
|
||||||
return operand
|
return operand
|
||||||
|
|
||||||
@tracer.trace_method
|
@tracer.trace_method
|
||||||
def factor(self) -> Value:
|
def factor(self, mandatory: bool = False) -> Value:
|
||||||
if self.accept(Tokens.Parens_Left):
|
if self.accept(Tokens.Parens_Left):
|
||||||
v = self.expression()
|
v = self.expression()
|
||||||
self.expect(Tokens.Parens_Right)
|
self.expect(Tokens.Parens_Right)
|
||||||
|
|
@ -112,42 +114,44 @@ class Parser:
|
||||||
return num
|
return num
|
||||||
elif variable := self.variable():
|
elif variable := self.variable():
|
||||||
return variable
|
return variable
|
||||||
else:
|
elif mandatory:
|
||||||
raise UnexpectedTokenError(self.token, "parenthesized expression, number or variable")
|
raise UnexpectedTokenError(self.token, "parenthesized expression, number or variable")
|
||||||
|
|
||||||
@tracer.trace_method
|
@tracer.trace_method
|
||||||
def term(self) -> Value:
|
def term(self, mandatory: bool = False) -> Value:
|
||||||
return self.binary_op(self.factor, operators={
|
return self.binary_op(self.factor, operators={
|
||||||
Tokens.Op_Multiply: Product,
|
Tokens.Op_Multiply: Product,
|
||||||
Tokens.Op_Divide: Division,
|
Tokens.Op_Divide: Division,
|
||||||
})
|
}, mandatory=mandatory)
|
||||||
|
|
||||||
@tracer.trace_method
|
@tracer.trace_method
|
||||||
def summation(self) -> Sum:
|
def summation(self, mandatory: bool = True) -> Sum:
|
||||||
return self.binary_op(self.term, operators={
|
return self.binary_op(self.term, operators={
|
||||||
Tokens.Op_Plus: Sum,
|
Tokens.Op_Plus: Sum,
|
||||||
Tokens.Op_Minus: Sub,
|
Tokens.Op_Minus: Sub,
|
||||||
})
|
}, mandatory=mandatory)
|
||||||
|
|
||||||
@tracer.trace_method
|
@tracer.trace_method
|
||||||
def assignment(self, mandatory: bool = False) -> Assignment:
|
def assignment(self, mandatory: bool = False) -> Assignment:
|
||||||
if ident := self.identifier(mandatory):
|
if ident := self.identifier(mandatory):
|
||||||
self.expect(Tokens.Equal)
|
self.expect(Tokens.Equal)
|
||||||
expr = self.expression()
|
expr = self.expression(mandatory=True)
|
||||||
return Assignment(ident, expr)
|
return Assignment(ident, expr)
|
||||||
elif mandatory:
|
elif mandatory:
|
||||||
raise UnexpectedTokenError(self.token, "assignment")
|
raise UnexpectedTokenError(self.token, "assignment")
|
||||||
|
|
||||||
@tracer.trace_method
|
@tracer.trace_method
|
||||||
def expression(self) -> Value:
|
def expression(self, mandatory: bool = False) -> Value:
|
||||||
if self.peek_several(Tokens.Identifier, Tokens.Equal):
|
if self.peek_several(Tokens.Identifier, Tokens.Equal) and (assignment := self.assignment(mandatory)):
|
||||||
return Expression(self.assignment())
|
return Expression(assignment)
|
||||||
else:
|
elif summation := self.summation(mandatory):
|
||||||
return Expression(self.summation())
|
return Expression(summation)
|
||||||
|
elif mandatory:
|
||||||
|
raise UnexpectedTokenError(self.token, "expression")
|
||||||
|
|
||||||
@tracer.trace_method
|
@tracer.trace_method
|
||||||
def root(self) -> Node:
|
def root(self) -> Node:
|
||||||
return self.expression()
|
return self.expression(mandatory=True)
|
||||||
|
|
||||||
def parse(self) -> Node:
|
def parse(self) -> Node:
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue