Make access node more generic

This commit is contained in:
Bartłomiej Pluta
2019-07-10 16:51:11 +02:00
parent 823c5cb18f
commit 88b245dc05
15 changed files with 71 additions and 42 deletions

View File

@@ -1,14 +1,14 @@
from smnp.ast.node.expression import ExpressionNode 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.ast.parser import Parser
from smnp.error.syntax import SyntaxException from smnp.error.syntax import SyntaxException
from smnp.token.type import TokenType from smnp.token.type import TokenType
class AccessNode(ExpressionNode): class LeftAssociativeOperatorNode(ExpressionNode):
def __init__(self, pos): def __init__(self, pos):
super().__init__(pos) super().__init__(pos)
self.children.append(IgnoredNode(pos)) self.children = [NoneNode(), NoneNode(), NoneNode()]
@property @property
def left(self): def left(self):
@@ -19,18 +19,27 @@ class AccessNode(ExpressionNode):
self[0] = value self[0] = value
@property @property
def right(self): def operator(self):
return self[1] return self[1]
@operator.setter
def operator(self, value):
self[1] = value
@property
def right(self):
return self[2]
@right.setter @right.setter
def right(self, value): def right(self, value):
self[1] = value self[2] = value
@classmethod @classmethod
def _parse(cls, input): def _parse(cls, input):
def createNode(left, right): def createNode(left, operator, right):
node = AccessNode(right.pos) node = LeftAssociativeOperatorNode(right.pos)
node.left = left node.left = left
node.operator = operator
node.right = right node.right = right
return node return node

View File

@@ -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.ast.node.literal import LiteralNode
from smnp.token.type import TokenType from smnp.token.type import TokenType
class BoolLiteralNode(LiteralNode, AccessNode): class BoolLiteralNode(LiteralNode, LeftAssociativeOperatorNode):
def __init__(self, pos): def __init__(self, pos):
super().__init__(pos) super().__init__(pos)
del self.children[1] self.children = [None]
@classmethod @classmethod
def _getTokenType(cls): def _getTokenType(cls):

View File

@@ -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.assignment import AssignmentNode
from smnp.ast.node.expression import ExpressionNode from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.invocation import FunctionCallNode, ArgumentsListNode from smnp.ast.node.invocation import FunctionCallNode, ArgumentsListNode
@@ -6,10 +6,10 @@ from smnp.ast.parser import Parser
from smnp.token.type import TokenType from smnp.token.type import TokenType
class IdentifierNode(AccessNode): class IdentifierNode(LeftAssociativeOperatorNode):
def __init__(self, pos): def __init__(self, pos):
super().__init__(pos) super().__init__(pos)
del self.children[1] self.children = [None]
@classmethod @classmethod
def _literalParser(cls): def _literalParser(cls):

View File

@@ -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.ast.parser import Parser
from smnp.token.type import TokenType from smnp.token.type import TokenType
class IntegerLiteralNode(AccessNode): class IntegerLiteralNode(LeftAssociativeOperatorNode):
def __init__(self, pos): def __init__(self, pos):
super().__init__(pos) super().__init__(pos)
del self.children[1] self.children = [None]
@classmethod @classmethod
def _literalParser(cls): def _literalParser(cls):

View File

@@ -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.expression import ExpressionNode
from smnp.ast.node.iterable import abstractIterableParser from smnp.ast.node.iterable import abstractIterableParser
from smnp.ast.node.model import Node from smnp.ast.node.model import Node
from smnp.ast.node.none import NoneNode
from smnp.ast.parser import Parser from smnp.ast.parser import Parser
from smnp.token.type import TokenType from smnp.token.type import TokenType
@@ -14,9 +15,10 @@ class ArgumentsListNode(Node):
Parser.doAssert(ExpressionNode.parse, "expression"))(input) Parser.doAssert(ExpressionNode.parse, "expression"))(input)
class FunctionCallNode(AccessNode): class FunctionCallNode(LeftAssociativeOperatorNode):
def __init__(self, pos): def __init__(self, pos):
super().__init__(pos) super().__init__(pos)
self.children = [NoneNode(), NoneNode()]
@property @property
def name(self): def name(self):

View File

@@ -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.expression import ExpressionNode
from smnp.ast.node.iterable import abstractIterableParser from smnp.ast.node.iterable import abstractIterableParser
from smnp.ast.parser import Parser from smnp.ast.parser import Parser
from smnp.token.type import TokenType from smnp.token.type import TokenType
class ListNode(AccessNode): class ListNode(LeftAssociativeOperatorNode):
@classmethod @classmethod
def _literalParser(cls): def _literalParser(cls):

View File

@@ -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.bool import BoolLiteralNode
from smnp.ast.node.expression import ExpressionNode from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.integer import IntegerLiteralNode from smnp.ast.node.integer import IntegerLiteralNode
@@ -31,7 +31,7 @@ class MapEntry(ExpressionNode):
def value(self, value): def value(self, value):
self[1] = value self[1] = value
class MapNode(AccessNode): class MapNode(LeftAssociativeOperatorNode):
@classmethod @classmethod
def _literalParser(cls): def _literalParser(cls):

View File

@@ -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.ast.node.literal import LiteralNode
from smnp.token.type import TokenType from smnp.token.type import TokenType
class NoteLiteralNode(LiteralNode, AccessNode): class NoteLiteralNode(LiteralNode, LeftAssociativeOperatorNode):
def __init__(self, pos): def __init__(self, pos):
super().__init__(pos) super().__init__(pos)
del self.children[1] self.children = [None]
@classmethod @classmethod
def _getTokenType(cls): def _getTokenType(cls):

15
smnp/ast/node/operator.py Normal file
View File

@@ -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

View File

@@ -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.ast.node.literal import LiteralNode
from smnp.token.type import TokenType from smnp.token.type import TokenType
class StringLiteralNode(LiteralNode, AccessNode): class StringLiteralNode(LiteralNode, LeftAssociativeOperatorNode):
def __init__(self, pos): def __init__(self, pos):
super().__init__(pos) super().__init__(pos)
del self.children[1] self.children = [None]
@classmethod @classmethod
def _getTokenType(cls): def _getTokenType(cls):

View File

@@ -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.iterable import abstractIterableParser
from smnp.ast.node.model import Node from smnp.ast.node.model import Node
from smnp.ast.parser import Parser from smnp.ast.parser import Parser
@@ -24,7 +24,7 @@ class TypeSpecifiers(Node):
pass pass
class TypeNode(AccessNode): class TypeNode(LeftAssociativeOperatorNode):
def __init__(self, pos): def __init__(self, pos):
super().__init__(pos) super().__init__(pos)

View File

@@ -1,6 +1,7 @@
from smnp.ast.node.ignore import IgnoredNode from smnp.ast.node.ignore import IgnoredNode
from smnp.ast.node.model import ParseResult, Node from smnp.ast.node.model import ParseResult, Node
from smnp.ast.node.none import NoneNode from smnp.ast.node.none import NoneNode
from smnp.ast.node.operator import OperatorNode
from smnp.error.syntax import SyntaxException from smnp.error.syntax import SyntaxException
@@ -97,10 +98,11 @@ class Parser:
def parse(input): def parse(input):
left = leftParser(input) left = leftParser(input)
if left.result: 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) 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 left
return ParseResult.FAIL() return ParseResult.FAIL()

View File

@@ -8,7 +8,7 @@ from smnp.program.interpreter import Interpreter
def main(): def main():
try: try:
stdLibraryEnv = loadStandardLibrary() 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: except SmnpException as e:
print(e.message()) print(e.message())

View File

@@ -9,15 +9,15 @@ from smnp.token.tokenizer import tokenize
class Interpreter: class Interpreter:
@staticmethod @staticmethod
def interpretString(string, printTokens=False, printAst=False, baseEnvironment=None): def interpretString(string, printTokens=False, printAst=False, execute=True, baseEnvironment=None):
return Interpreter._interpret(string.splitlines(), printTokens, printAst, baseEnvironment) return Interpreter._interpret(string.splitlines(), printTokens, printAst, execute, baseEnvironment)
@staticmethod @staticmethod
def interpretFile(file, printTokens=False, printAst=False, baseEnvironment=None): def interpretFile(file, printTokens=False, printAst=False, execute=True, baseEnvironment=None):
return Interpreter._interpret(readLines(file), printTokens, printAst, baseEnvironment) return Interpreter._interpret(readLines(file), printTokens, printAst, execute, baseEnvironment)
@staticmethod @staticmethod
def _interpret(lines, printTokens=False, printAst=False, baseEnvironment=None): def _interpret(lines, printTokens=False, printAst=False, execute=True, baseEnvironment=None):
environment = createEnvironment() environment = createEnvironment()
if baseEnvironment is not None: if baseEnvironment is not None:
environment.extend(baseEnvironment) environment.extend(baseEnvironment)
@@ -31,7 +31,8 @@ class Interpreter:
if printAst: if printAst:
ast.print() ast.print()
evaluate(ast, environment) if execute:
evaluate(ast, environment)
return environment return environment
except RuntimeException as e: except RuntimeException as e:

View File

@@ -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.assignment import AssignmentNode
from smnp.ast.node.asterisk import AsteriskNode from smnp.ast.node.asterisk import AsteriskNode
from smnp.ast.node.bool import BoolLiteralNode from smnp.ast.node.bool import BoolLiteralNode
@@ -39,7 +39,7 @@ def expressionEvaluator(doAssert=False):
Evaluator.forNodes(TypeEvaluator.evaluate, TypeNode), Evaluator.forNodes(TypeEvaluator.evaluate, TypeNode),
Evaluator.forNodes(IdentifierEvaluator.evaluate, IdentifierNode), Evaluator.forNodes(IdentifierEvaluator.evaluate, IdentifierNode),
Evaluator.forNodes(ListEvaluator.evaluate, ListNode), Evaluator.forNodes(ListEvaluator.evaluate, ListNode),
Evaluator.forNodes(AccessEvaluator.evaluate, AccessNode), Evaluator.forNodes(AccessEvaluator.evaluate, LeftAssociativeOperatorNode),
Evaluator.forNodes(AssignmentEvaluator.evaluate, AssignmentNode), Evaluator.forNodes(AssignmentEvaluator.evaluate, AssignmentNode),
Evaluator.forNodes(AsteriskEvaluator.evaluate, AsteriskNode), Evaluator.forNodes(AsteriskEvaluator.evaluate, AsteriskNode),
Evaluator.forNodes(MapEvaluator.evaluate, MapNode) Evaluator.forNodes(MapEvaluator.evaluate, MapNode)