diff options
Diffstat (limited to 'ql/ast/visitors/reference_visitor.py')
| -rw-r--r-- | ql/ast/visitors/reference_visitor.py | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/ql/ast/visitors/reference_visitor.py b/ql/ast/visitors/reference_visitor.py new file mode 100644 index 0000000..5cbbcc7 --- /dev/null +++ b/ql/ast/visitors/reference_visitor.py @@ -0,0 +1,86 @@ +from multimethods import multimethod + +from ql.ast.nodes.expressions.binary_operators.binary_operator import BinaryOperatorNode +from ql.ast.nodes.expressions.literals.literal import LiteralNode +from ql.ast.nodes.expressions.unary_operators.unary_operator import UnaryOperatorNode +from ql.ast.nodes.expressions.variable import VariableNode +from ql.ast.nodes.statements.form_statement import FormNode +from ql.ast.nodes.statements.if_statement import IfNode +from ql.ast.nodes.statements.question_statement import QuestionNode + + +class ReferenceVisitor: + def __init__(self): + self.__current_block = [] + self.__current_scope = {} + + @property + def identifier_scopes(self): + return self.__current_scope + + @multimethod(FormNode) + def visit(self, node): + self.__current_scope = { + 'content': [], + 'children': [], + } + self.__current_block = [] + + for child in node.block: + child.accept(self) + + self.__current_scope['content'] = self.__current_block + + @multimethod(IfNode) + def visit(self, node): + node.condition.accept(self) + + self.__current_scope['content'] += self.__current_block + previous_scope = self.__current_scope + previous_block = self.__current_block + self.__current_block = [] + self.__current_scope = { + 'content': [], + 'children': [], + } + + for child in node.block: + child.accept(self) + + self.__current_scope['content'] = self.__current_block + previous_scope['children'].append(self.__current_scope) + self.__current_block = previous_block + self.__current_scope = previous_scope + + @multimethod(QuestionNode) + def visit(self, node): + self.__current_block.append(dict({ + 'name': node.identifier, + 'type': node.answer_type, + 'line': node.metadata.line, + })) + + if node.computed: + node.answer.accept(self) + + @multimethod(BinaryOperatorNode) + def visit(self, node): + node.left_expression.accept(self) + node.right_expression.accept(self) + + @multimethod(UnaryOperatorNode) + def visit(self, node): + node.expression.accept(self) + + @multimethod(VariableNode) + def visit(self, node): + name = node.identifier + self.__current_block.append({ + 'name': name, + 'type': [], + 'line': node.metadata.line, + }) + + @multimethod(LiteralNode) + def visit(self, node): + pass |