Make access node more generic
This commit is contained in:
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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
15
smnp/ast/node/operator.py
Normal 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
|
||||||
@@ -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):
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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())
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user