From 88b245dc053f572af6149b97c7cf7052c1bba5a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Pluta?= Date: Wed, 10 Jul 2019 16:51:11 +0200 Subject: [PATCH] Make access node more generic --- smnp/ast/node/access.py | 23 ++++++++++++++++------- smnp/ast/node/bool.py | 6 +++--- smnp/ast/node/identifier.py | 6 +++--- smnp/ast/node/integer.py | 6 +++--- smnp/ast/node/invocation.py | 6 ++++-- smnp/ast/node/list.py | 4 ++-- smnp/ast/node/map.py | 4 ++-- smnp/ast/node/note.py | 6 +++--- smnp/ast/node/operator.py | 15 +++++++++++++++ smnp/ast/node/string.py | 6 +++--- smnp/ast/node/type.py | 4 ++-- smnp/ast/parser.py | 8 +++++--- smnp/main.py | 2 +- smnp/program/interpreter.py | 13 +++++++------ smnp/runtime/evaluators/expression.py | 4 ++-- 15 files changed, 71 insertions(+), 42 deletions(-) create mode 100644 smnp/ast/node/operator.py diff --git a/smnp/ast/node/access.py b/smnp/ast/node/access.py index 8ef0f51..66ee2c3 100644 --- a/smnp/ast/node/access.py +++ b/smnp/ast/node/access.py @@ -1,14 +1,14 @@ from smnp.ast.node.expression import ExpressionNode -from smnp.ast.node.ignore import IgnoredNode +from smnp.ast.node.none import NoneNode from smnp.ast.parser import Parser from smnp.error.syntax import SyntaxException from smnp.token.type import TokenType -class AccessNode(ExpressionNode): +class LeftAssociativeOperatorNode(ExpressionNode): def __init__(self, pos): super().__init__(pos) - self.children.append(IgnoredNode(pos)) + self.children = [NoneNode(), NoneNode(), NoneNode()] @property def left(self): @@ -19,18 +19,27 @@ class AccessNode(ExpressionNode): self[0] = value @property - def right(self): + def operator(self): return self[1] + @operator.setter + def operator(self, value): + self[1] = value + + @property + def right(self): + return self[2] + @right.setter def right(self, value): - self[1] = value + self[2] = value @classmethod def _parse(cls, input): - def createNode(left, right): - node = AccessNode(right.pos) + def createNode(left, operator, right): + node = LeftAssociativeOperatorNode(right.pos) node.left = left + node.operator = operator node.right = right return node diff --git a/smnp/ast/node/bool.py b/smnp/ast/node/bool.py index 6e6b6d1..a45f2de 100644 --- a/smnp/ast/node/bool.py +++ b/smnp/ast/node/bool.py @@ -1,12 +1,12 @@ -from smnp.ast.node.access import AccessNode +from smnp.ast.node.access import LeftAssociativeOperatorNode from smnp.ast.node.literal import LiteralNode from smnp.token.type import TokenType -class BoolLiteralNode(LiteralNode, AccessNode): +class BoolLiteralNode(LiteralNode, LeftAssociativeOperatorNode): def __init__(self, pos): super().__init__(pos) - del self.children[1] + self.children = [None] @classmethod def _getTokenType(cls): diff --git a/smnp/ast/node/identifier.py b/smnp/ast/node/identifier.py index 0edd0ab..66d0716 100644 --- a/smnp/ast/node/identifier.py +++ b/smnp/ast/node/identifier.py @@ -1,4 +1,4 @@ -from smnp.ast.node.access import AccessNode +from smnp.ast.node.access import LeftAssociativeOperatorNode from smnp.ast.node.assignment import AssignmentNode from smnp.ast.node.expression import ExpressionNode from smnp.ast.node.invocation import FunctionCallNode, ArgumentsListNode @@ -6,10 +6,10 @@ from smnp.ast.parser import Parser from smnp.token.type import TokenType -class IdentifierNode(AccessNode): +class IdentifierNode(LeftAssociativeOperatorNode): def __init__(self, pos): super().__init__(pos) - del self.children[1] + self.children = [None] @classmethod def _literalParser(cls): diff --git a/smnp/ast/node/integer.py b/smnp/ast/node/integer.py index fccb86d..bb4275d 100644 --- a/smnp/ast/node/integer.py +++ b/smnp/ast/node/integer.py @@ -1,12 +1,12 @@ -from smnp.ast.node.access import AccessNode +from smnp.ast.node.access import LeftAssociativeOperatorNode from smnp.ast.parser import Parser from smnp.token.type import TokenType -class IntegerLiteralNode(AccessNode): +class IntegerLiteralNode(LeftAssociativeOperatorNode): def __init__(self, pos): super().__init__(pos) - del self.children[1] + self.children = [None] @classmethod def _literalParser(cls): diff --git a/smnp/ast/node/invocation.py b/smnp/ast/node/invocation.py index f9ab2f3..bee76b2 100644 --- a/smnp/ast/node/invocation.py +++ b/smnp/ast/node/invocation.py @@ -1,7 +1,8 @@ -from smnp.ast.node.access import AccessNode +from smnp.ast.node.access import LeftAssociativeOperatorNode from smnp.ast.node.expression import ExpressionNode from smnp.ast.node.iterable import abstractIterableParser from smnp.ast.node.model import Node +from smnp.ast.node.none import NoneNode from smnp.ast.parser import Parser from smnp.token.type import TokenType @@ -14,9 +15,10 @@ class ArgumentsListNode(Node): Parser.doAssert(ExpressionNode.parse, "expression"))(input) -class FunctionCallNode(AccessNode): +class FunctionCallNode(LeftAssociativeOperatorNode): def __init__(self, pos): super().__init__(pos) + self.children = [NoneNode(), NoneNode()] @property def name(self): diff --git a/smnp/ast/node/list.py b/smnp/ast/node/list.py index 0316918..f4d1951 100644 --- a/smnp/ast/node/list.py +++ b/smnp/ast/node/list.py @@ -1,11 +1,11 @@ -from smnp.ast.node.access import AccessNode +from smnp.ast.node.access import LeftAssociativeOperatorNode from smnp.ast.node.expression import ExpressionNode from smnp.ast.node.iterable import abstractIterableParser from smnp.ast.parser import Parser from smnp.token.type import TokenType -class ListNode(AccessNode): +class ListNode(LeftAssociativeOperatorNode): @classmethod def _literalParser(cls): diff --git a/smnp/ast/node/map.py b/smnp/ast/node/map.py index c5f29d6..7a2f90b 100644 --- a/smnp/ast/node/map.py +++ b/smnp/ast/node/map.py @@ -1,4 +1,4 @@ -from smnp.ast.node.access import AccessNode +from smnp.ast.node.access import LeftAssociativeOperatorNode from smnp.ast.node.bool import BoolLiteralNode from smnp.ast.node.expression import ExpressionNode from smnp.ast.node.integer import IntegerLiteralNode @@ -31,7 +31,7 @@ class MapEntry(ExpressionNode): def value(self, value): self[1] = value -class MapNode(AccessNode): +class MapNode(LeftAssociativeOperatorNode): @classmethod def _literalParser(cls): diff --git a/smnp/ast/node/note.py b/smnp/ast/node/note.py index e4c02b0..47489ed 100644 --- a/smnp/ast/node/note.py +++ b/smnp/ast/node/note.py @@ -1,12 +1,12 @@ -from smnp.ast.node.access import AccessNode +from smnp.ast.node.access import LeftAssociativeOperatorNode from smnp.ast.node.literal import LiteralNode from smnp.token.type import TokenType -class NoteLiteralNode(LiteralNode, AccessNode): +class NoteLiteralNode(LiteralNode, LeftAssociativeOperatorNode): def __init__(self, pos): super().__init__(pos) - del self.children[1] + self.children = [None] @classmethod def _getTokenType(cls): diff --git a/smnp/ast/node/operator.py b/smnp/ast/node/operator.py new file mode 100644 index 0000000..c23f320 --- /dev/null +++ b/smnp/ast/node/operator.py @@ -0,0 +1,15 @@ +from smnp.ast.node.model import Node + + +class OperatorNode(Node): + def __init__(self, pos): + super().__init__(pos) + self.children = [None] + + @property + def value(self): + return self[0] + + @value.setter + def value(self, value): + self[0] = value \ No newline at end of file diff --git a/smnp/ast/node/string.py b/smnp/ast/node/string.py index 4034d3d..3df2fe8 100644 --- a/smnp/ast/node/string.py +++ b/smnp/ast/node/string.py @@ -1,12 +1,12 @@ -from smnp.ast.node.access import AccessNode +from smnp.ast.node.access import LeftAssociativeOperatorNode from smnp.ast.node.literal import LiteralNode from smnp.token.type import TokenType -class StringLiteralNode(LiteralNode, AccessNode): +class StringLiteralNode(LiteralNode, LeftAssociativeOperatorNode): def __init__(self, pos): super().__init__(pos) - del self.children[1] + self.children = [None] @classmethod def _getTokenType(cls): diff --git a/smnp/ast/node/type.py b/smnp/ast/node/type.py index 847f27b..691db17 100644 --- a/smnp/ast/node/type.py +++ b/smnp/ast/node/type.py @@ -1,4 +1,4 @@ -from smnp.ast.node.access import AccessNode +from smnp.ast.node.access import LeftAssociativeOperatorNode from smnp.ast.node.iterable import abstractIterableParser from smnp.ast.node.model import Node from smnp.ast.parser import Parser @@ -24,7 +24,7 @@ class TypeSpecifiers(Node): pass -class TypeNode(AccessNode): +class TypeNode(LeftAssociativeOperatorNode): def __init__(self, pos): super().__init__(pos) diff --git a/smnp/ast/parser.py b/smnp/ast/parser.py index bad5af7..f6a2903 100644 --- a/smnp/ast/parser.py +++ b/smnp/ast/parser.py @@ -1,6 +1,7 @@ from smnp.ast.node.ignore import IgnoredNode from smnp.ast.node.model import ParseResult, Node from smnp.ast.node.none import NoneNode +from smnp.ast.node.operator import OperatorNode from smnp.error.syntax import SyntaxException @@ -97,10 +98,11 @@ class Parser: def parse(input): left = leftParser(input) if left.result: - while Parser.terminalParser(operatorTokenType)(input).result: + operator = Parser.terminalParser(operatorTokenType, lambda val, pos: OperatorNode.withChildren([val], pos))(input) + while operator.result: right = rightParser(input) - left = ParseResult.OK(createNode(left.node, right.node)) - + left = ParseResult.OK(createNode(left.node, operator.node, right.node)) + operator = Parser.terminalParser(operatorTokenType, lambda val, pos: OperatorNode.withChildren([val], pos))(input) return left return ParseResult.FAIL() diff --git a/smnp/main.py b/smnp/main.py index 0dc20ac..214e397 100644 --- a/smnp/main.py +++ b/smnp/main.py @@ -8,7 +8,7 @@ from smnp.program.interpreter import Interpreter def main(): try: stdLibraryEnv = loadStandardLibrary() - Interpreter.interpretFile(sys.argv[1], printTokens=False, printAst=True, baseEnvironment=stdLibraryEnv) + Interpreter.interpretFile(sys.argv[1], printTokens=False, printAst=True, execute=False, baseEnvironment=stdLibraryEnv) except SmnpException as e: print(e.message()) diff --git a/smnp/program/interpreter.py b/smnp/program/interpreter.py index fdd33e0..7bbe79e 100644 --- a/smnp/program/interpreter.py +++ b/smnp/program/interpreter.py @@ -9,15 +9,15 @@ from smnp.token.tokenizer import tokenize class Interpreter: @staticmethod - def interpretString(string, printTokens=False, printAst=False, baseEnvironment=None): - return Interpreter._interpret(string.splitlines(), printTokens, printAst, baseEnvironment) + def interpretString(string, printTokens=False, printAst=False, execute=True, baseEnvironment=None): + return Interpreter._interpret(string.splitlines(), printTokens, printAst, execute, baseEnvironment) @staticmethod - def interpretFile(file, printTokens=False, printAst=False, baseEnvironment=None): - return Interpreter._interpret(readLines(file), printTokens, printAst, baseEnvironment) + def interpretFile(file, printTokens=False, printAst=False, execute=True, baseEnvironment=None): + return Interpreter._interpret(readLines(file), printTokens, printAst, execute, baseEnvironment) @staticmethod - def _interpret(lines, printTokens=False, printAst=False, baseEnvironment=None): + def _interpret(lines, printTokens=False, printAst=False, execute=True, baseEnvironment=None): environment = createEnvironment() if baseEnvironment is not None: environment.extend(baseEnvironment) @@ -31,7 +31,8 @@ class Interpreter: if printAst: ast.print() - evaluate(ast, environment) + if execute: + evaluate(ast, environment) return environment except RuntimeException as e: diff --git a/smnp/runtime/evaluators/expression.py b/smnp/runtime/evaluators/expression.py index 7dc0e51..b78615a 100644 --- a/smnp/runtime/evaluators/expression.py +++ b/smnp/runtime/evaluators/expression.py @@ -1,4 +1,4 @@ -from smnp.ast.node.access import AccessNode +from smnp.ast.node.access import LeftAssociativeOperatorNode from smnp.ast.node.assignment import AssignmentNode from smnp.ast.node.asterisk import AsteriskNode from smnp.ast.node.bool import BoolLiteralNode @@ -39,7 +39,7 @@ def expressionEvaluator(doAssert=False): Evaluator.forNodes(TypeEvaluator.evaluate, TypeNode), Evaluator.forNodes(IdentifierEvaluator.evaluate, IdentifierNode), Evaluator.forNodes(ListEvaluator.evaluate, ListNode), - Evaluator.forNodes(AccessEvaluator.evaluate, AccessNode), + Evaluator.forNodes(AccessEvaluator.evaluate, LeftAssociativeOperatorNode), Evaluator.forNodes(AssignmentEvaluator.evaluate, AssignmentNode), Evaluator.forNodes(AsteriskEvaluator.evaluate, AsteriskNode), Evaluator.forNodes(MapEvaluator.evaluate, MapNode)