Do some refactor with multiple left associative operators

This commit is contained in:
Bartłomiej Pluta
2019-07-10 15:25:00 +02:00
parent 0a7d29d4a1
commit e008be7952
6 changed files with 52 additions and 27 deletions

View File

@@ -1,5 +1,5 @@
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
@@ -8,7 +8,7 @@ from smnp.token.type import TokenType
class AccessNode(ExpressionNode): class AccessNode(ExpressionNode):
def __init__(self, pos): def __init__(self, pos):
super().__init__(pos) super().__init__(pos)
self.children.append(IgnoredNode(pos)) self.children = [ NoneNode(), NoneNode() ]
@property @property
def left(self): def left(self):
@@ -28,29 +28,29 @@ class AccessNode(ExpressionNode):
@classmethod @classmethod
def accessParser(cls): def accessParser(cls):
def createNode(left, right): def createNode(left, operator, right):
node = AccessNode(right.pos) node = AccessNode(right.pos)
node.left = left node.left = left
node.right = right node.right = right
return node return node
return Parser.leftAssociativeOperatorParser( return Parser.leftAssociativeOperatorParser(
cls._accessLiteralParser(), cls._accessLhs(),
TokenType.DOT, TokenType.DOT,
cls._parseAccessingProperty(), cls._accessRhs(),
createNode=createNode createNode=createNode
) )
@classmethod @classmethod
def _accessLiteralParser(cls): def _accessLhs(cls):
raise RuntimeError(f"_accessLiteralParser() is not implemented in {cls.__name__} class") raise RuntimeError(f"_accessLhs() is not implemented in {cls.__name__} class")
@staticmethod @staticmethod
def _parseAccessingProperty(): def _accessRhs():
from smnp.ast.node.identifier import IdentifierNode from smnp.ast.node.identifier import IdentifierNode
return Parser.oneOf( return Parser.oneOf(
IdentifierNode.functionCallParser(),
IdentifierNode.identifierParser(), IdentifierNode.identifierParser(),
IdentifierNode._functionCallParser(),
exception=lambda input: SyntaxException(f"Expected property name or method call, found '{input.current().rawValue}'", input.currentPos()) exception=lambda input: SyntaxException(f"Expected property name or method call, found '{input.current().rawValue}'", input.currentPos())
) )

View File

@@ -17,7 +17,6 @@ class BoolLiteralNode(LiteralNode, AccessNode, RelationOperatorNode):
@classmethod @classmethod
def _parse(cls, input): def _parse(cls, input):
x = Parser.oneOf( x = Parser.oneOf(
cls.relationParser(), cls.relationParser(),
cls.accessParser(), cls.accessParser(),
cls.literalParser() cls.literalParser()
@@ -25,9 +24,9 @@ class BoolLiteralNode(LiteralNode, AccessNode, RelationOperatorNode):
return x return x
@classmethod @classmethod
def _accessLiteralParser(cls): def _accessLhs(cls):
return cls.literalParser() return cls.literalParser()
@classmethod @classmethod
def _relationLiteralParser(cls): def _relationLhs(cls):
return cls.literalParser() return cls.literalParser()

View File

@@ -14,7 +14,7 @@ class IdentifierNode(AccessNode):
@classmethod @classmethod
def _literalParser(cls): def _literalParser(cls):
return Parser.oneOf( return Parser.oneOf(
IdentifierNode._functionCallParser(), IdentifierNode.functionCallParser(),
IdentifierNode._assignmentParser(), IdentifierNode._assignmentParser(),
IdentifierNode.identifierParser() IdentifierNode.identifierParser()
) )
@@ -35,7 +35,7 @@ class IdentifierNode(AccessNode):
) )
@staticmethod @staticmethod
def _functionCallParser(): def functionCallParser():
def createNode(name, arguments): def createNode(name, arguments):
node = FunctionCallNode(name.pos) node = FunctionCallNode(name.pos)
node.name = name node.name = name

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,5 +1,5 @@
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.token.type import TokenType from smnp.token.type import TokenType
@@ -7,7 +7,7 @@ from smnp.token.type import TokenType
class RelationOperatorNode(ExpressionNode): class RelationOperatorNode(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):
@@ -18,33 +18,42 @@ class RelationOperatorNode(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 relationParser(cls): def relationParser(cls):
def createNode(left, right): def createNode(left, operator, right):
node = RelationOperatorNode(right.pos) node = RelationOperatorNode(right.pos)
node.left = left node.left = left
node.operator = operator
node.right = right node.right = right
return node return node
return Parser.leftAssociativeOperatorParser( return Parser.leftAssociativeOperatorParser(
cls._relationLiteralParser(), cls._relationLhs(),
TokenType.EQUAL, TokenType.EQUAL,
cls._parseRelationProperty(), cls._relationRhs(),
createNode=createNode createNode=createNode
) )
@classmethod @classmethod
def _relationLiteralParser(cls): def _relationLhs(cls):
raise RuntimeError(f"_relationLiteralParser() is not implemented in {cls.__name__} class") raise RuntimeError(f"_relationLhs() is not implemented in {cls.__name__} class")
@staticmethod @staticmethod
def _parseRelationProperty(): def _relationRhs():
# TODO doAssert # TODO doAssert
return ExpressionNode.parse return ExpressionNode.parse

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
@@ -99,11 +100,12 @@ class Parser:
left = leftParser(input) left = leftParser(input)
oneAtLeast = False oneAtLeast = False
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:
oneAtLeast = True oneAtLeast = True
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)(input)
if oneAtLeast: if oneAtLeast:
return left return left