class NodeStatementGoto: NodeStatement;
class NodeStatementIf: NodeStatement;
class NodeStatementEnd: NodeStatement;
+class NodeStatementGosub: NodeStatement;
+class NodeStatementReturn: NodeStatement;
class NodeExpression: Node;
class NodeExpressionOr: NodeExpression;
class NodeExpressionAnd: NodeExpression;
class EndException(Exception):
pass
+class ReturnException(Exception):
+ pass
+
class Context:
def __init__(self, program = None, variables = None, i = 0, j = 1):
self.program = program if program is not None else NodeProgram()
self.execute()
except EndException:
pass
+ except ReturnException:
+ raise Exception(
+ f'?RETURN WITHOUT GOSUB ERROR IN {self.line_number():d}'
+ )
def line_number(self):
assert self.i < len(self.program.children)
else:
self.i += 1
self.j = 1
+ raise EndException()
+
+ def goto(self, target):
+ for i in range(len(self.program.children)):
+ if target == self.program.children[i].children[0].int_value:
+ self.i = i
+ self.j = 1
+ break
+ else:
+ raise Exception(f'?UNDEF\'D STATEMENT ERROR IN {self.line_number():d}')
def factory(tag, *args, **kwargs):
return tag_to_class[tag](*args, **kwargs)
print()
@method(NodeStatementGoto)
def execute(self, context):
- target = self.children[0].int_value
- for i in range(len(context.program.children)):
- if target == context.program.children[i].children[0].int_value:
- context.i = i
- context.j = 1
- break
- else:
- raise Exception(f'?UNDEF\'D STATEMENT ERROR IN {context.line_number():d}')
+ context.goto(self.children[0].int_value)
@method(NodeStatementIf)
def execute(self, context):
value = self.children[0].evaluate(context)
@method(NodeStatementEnd)
def execute(self, context):
raise EndException()
+@method(NodeStatementGosub)
+def execute(self, context):
+ i = context.i
+ j = context.j
+ context.goto(self.children[0].int_value)
+ try:
+ context.execute()
+ except ReturnException:
+ pass
+ context.i = i
+ context.j = j
+@method(NodeStatementReturn)
+def execute(self, context):
+ raise ReturnException()
del execute
@method(NodeExpression)