Working proof of concept of multiple left associative operators

This commit is contained in:
Bartłomiej Pluta
2019-07-10 15:02:17 +02:00
parent 823c5cb18f
commit 0a7d29d4a1
15 changed files with 138 additions and 58 deletions

View File

@@ -27,7 +27,7 @@ class AccessNode(ExpressionNode):
self[1] = value
@classmethod
def _parse(cls, input):
def accessParser(cls):
def createNode(left, right):
node = AccessNode(right.pos)
node.left = left
@@ -35,22 +35,22 @@ class AccessNode(ExpressionNode):
return node
return Parser.leftAssociativeOperatorParser(
cls._literalParser(),
cls._accessLiteralParser(),
TokenType.DOT,
cls._parseAccessingProperty(),
createNode=createNode
)(input)
)
@classmethod
def _literalParser(cls):
pass
def _accessLiteralParser(cls):
raise RuntimeError(f"_accessLiteralParser() is not implemented in {cls.__name__} class")
@staticmethod
def _parseAccessingProperty():
from smnp.ast.node.identifier import IdentifierNode
return Parser.oneOf(
IdentifierNode._literalParser(),
IdentifierNode.identifierParser(),
IdentifierNode._functionCallParser(),
exception=lambda input: SyntaxException(f"Expected property name or method call, found '{input.current().rawValue}'", input.currentPos())
)

View File

@@ -1,13 +1,33 @@
from smnp.ast.node.access import AccessNode
from smnp.ast.node.literal import LiteralNode
from smnp.ast.node.relation import RelationOperatorNode
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class BoolLiteralNode(LiteralNode, AccessNode):
class BoolLiteralNode(LiteralNode, AccessNode, RelationOperatorNode):
def __init__(self, pos):
super().__init__(pos)
del self.children[1]
@classmethod
def _getTokenType(cls):
return TokenType.BOOL
return TokenType.BOOL
@classmethod
def _parse(cls, input):
x = Parser.oneOf(
cls.relationParser(),
cls.accessParser(),
cls.literalParser()
)(input)
return x
@classmethod
def _accessLiteralParser(cls):
return cls.literalParser()
@classmethod
def _relationLiteralParser(cls):
return cls.literalParser()

View File

@@ -50,22 +50,15 @@ class ExpressionNode(Node):
@classmethod
def _expressionParser(cls):
from smnp.ast.node.integer import IntegerLiteralNode
from smnp.ast.node.string import StringLiteralNode
from smnp.ast.node.note import NoteLiteralNode
from smnp.ast.node.bool import BoolLiteralNode
from smnp.ast.node.identifier import IdentifierNode
from smnp.ast.node.list import ListNode
from smnp.ast.node.map import MapNode
from smnp.ast.node.type import TypeNode
return Parser.oneOf(
IntegerLiteralNode.parse,
StringLiteralNode.parse,
NoteLiteralNode.parse,
#IntegerLiteralNode.parse,
#StringLiteralNode.parse,
#NoteLiteralNode.parse,
BoolLiteralNode.parse,
IdentifierNode.parse,
MapNode.parse,
ListNode.parse,
TypeNode.parse,
#IdentifierNode.parse,
#MapNode.parse,
#ListNode.parse,
#TypeNode.parse,
)

View File

@@ -56,7 +56,7 @@ class ImportNode(Node):
Parser.terminalParser(TokenType.IMPORT),
TypeNode.parse,
Parser.doAssert(Parser.terminalParser(TokenType.FROM), "'from <source> as <variable name>'"),
Parser.doAssert(StringLiteralNode._literalParser(), "source as a string"),
Parser.doAssert(StringLiteralNode.literalParser(), "source as a string"),
Parser.doAssert(Parser.terminalParser(TokenType.AS), "'as <variable name>'"),
Parser.doAssert(IdentifierNode.identifierParser(), "variable name"),
createNode=createNode
@@ -71,6 +71,6 @@ class ImportNode(Node):
return Parser.allOf(
Parser.terminalParser(TokenType.IMPORT),
Parser.doAssert(StringLiteralNode._literalParser(), "source as a string"),
Parser.doAssert(StringLiteralNode.literalParser(), "source as a string"),
createNode=createNode
)

View File

@@ -1,12 +1,18 @@
from smnp.ast.node.access import AccessNode
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class IntegerLiteralNode(AccessNode):
class IntegerLiteralNode(ExpressionNode):
def __init__(self, pos):
super().__init__(pos)
del self.children[1]
#TODO del self.children[1]
# TODO: To Remove
@classmethod
def _parse(cls, input):
return cls._literalParser()(input)
@classmethod
def _literalParser(cls):

View File

@@ -1,11 +1,15 @@
from smnp.ast.node.access import AccessNode
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(ExpressionNode):
# TODO: To Remove
@classmethod
def _parse(cls, input):
return cls._literalParser()(input)
@classmethod
def _literalParser(cls):

View File

@@ -13,6 +13,6 @@ class LiteralNode(ExpressionNode):
return value
@classmethod
def _literalParser(cls):
def literalParser(cls):
createNode = lambda val, pos: cls.withValue(cls._processValue(val), pos)
return Parser.terminalParser(cls._getTokenType(), createNode)

View File

@@ -1,12 +1,17 @@
from smnp.ast.node.access import AccessNode
from smnp.ast.node.literal import LiteralNode
from smnp.token.type import TokenType
class NoteLiteralNode(LiteralNode, AccessNode):
class NoteLiteralNode(LiteralNode):
def __init__(self, pos):
super().__init__(pos)
del self.children[1]
#TODO del self.children[1]
# TODO: To Remove
@classmethod
def _parse(cls, input):
return cls.literalParser()(input)
@classmethod
def _getTokenType(cls):

50
smnp/ast/node/relation.py Normal file
View File

@@ -0,0 +1,50 @@
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.ignore import IgnoredNode
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class RelationOperatorNode(ExpressionNode):
def __init__(self, pos):
super().__init__(pos)
self.children.append(IgnoredNode(pos))
@property
def left(self):
return self[0]
@left.setter
def left(self, value):
self[0] = value
@property
def right(self):
return self[1]
@right.setter
def right(self, value):
self[1] = value
@classmethod
def relationParser(cls):
def createNode(left, right):
node = RelationOperatorNode(right.pos)
node.left = left
node.right = right
return node
return Parser.leftAssociativeOperatorParser(
cls._relationLiteralParser(),
TokenType.EQUAL,
cls._parseRelationProperty(),
createNode=createNode
)
@classmethod
def _relationLiteralParser(cls):
raise RuntimeError(f"_relationLiteralParser() is not implemented in {cls.__name__} class")
@staticmethod
def _parseRelationProperty():
# TODO doAssert
return ExpressionNode.parse

View File

@@ -1,12 +1,17 @@
from smnp.ast.node.access import AccessNode
from smnp.ast.node.literal import LiteralNode
from smnp.token.type import TokenType
class StringLiteralNode(LiteralNode, AccessNode):
class StringLiteralNode(LiteralNode):
def __init__(self, pos):
super().__init__(pos)
del self.children[1]
#TODO del self.children[1]
# TODO: To Remove
@classmethod
def _parse(cls, input):
return cls.literalParser()(input)
@classmethod
def _getTokenType(cls):

View File

@@ -41,6 +41,7 @@ class Parser:
value = parser(input)
if value.result:
return value
input.reset(snap)
if exception is not None:
if callable(exception):
@@ -96,12 +97,15 @@ class Parser:
def leftAssociativeOperatorParser(leftParser, operatorTokenType, rightParser, createNode):
def parse(input):
left = leftParser(input)
oneAtLeast = False
if left.result:
while Parser.terminalParser(operatorTokenType)(input).result:
oneAtLeast = True
right = rightParser(input)
left = ParseResult.OK(createNode(left.node, right.node))
return left
if oneAtLeast:
return left
return ParseResult.FAIL()