Add support for assignments, function calls and pure identifiers

This commit is contained in:
Bartłomiej Pluta
2019-07-10 23:19:46 +02:00
parent 24b1012c7c
commit 18884eb5d9
10 changed files with 210 additions and 133 deletions

View File

@@ -1,53 +1,119 @@
from smnp.ast.node.assignment import AssignmentNode
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.invocation import FunctionCallNode, ArgumentsListNode
from smnp.ast.node.operator import LeftAssociativeOperatorNode
from smnp.ast.node.atom import Atom
from smnp.ast.node.expression import MaxPrecedenceExpressionParser
from smnp.ast.node.iterable import abstractIterableParser
from smnp.ast.node.model import Node
from smnp.ast.node.none import NoneNode
from smnp.ast.node.operator import BinaryOperator, Operator
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class IdentifierNode(LeftAssociativeOperatorNode):
class Identifier(Atom):
pass
class FunctionCall(Node):
def __init__(self, pos):
super().__init__(pos)
self.children = [None]
self.children = [NoneNode(), NoneNode()]
@property
def name(self):
return self[0]
@name.setter
def name(self, value):
self[0] = value
@property
def arguments(self):
return self[1]
@arguments.setter
def arguments(self, value):
self[1] = value
@classmethod
def _lhsParser(cls):
return Parser.oneOf(
IdentifierNode._functionCallParser(),
IdentifierNode._assignmentParser(),
IdentifierNode.identifierParser()
)
def withChildren(cls, name, arguments):
node = cls(name.pos)
node.name = name
node.arguments = arguments
return node
@staticmethod
def _assignmentParser():
def createNode(target, assignment, value):
node = AssignmentNode(assignment.pos)
node.target = target
node.value = value
return node
return Parser.allOf(
IdentifierNode.identifierParser(),
Parser.terminalParser(TokenType.ASSIGN),
Parser.doAssert(ExpressionNode.parse, "expression"),
createNode=createNode
)
class ArgumentsList(Node):
pass
@staticmethod
def _functionCallParser():
def createNode(name, arguments):
node = FunctionCallNode(name.pos)
node.name = name
node.arguments = arguments
return node
return Parser.allOf(
IdentifierNode.identifierParser(),
ArgumentsListNode.parse,
createNode=createNode
)
class Assignment(BinaryOperator):
pass
@staticmethod
def identifierParser():
return Parser.terminalParser(TokenType.IDENTIFIER, lambda val, pos: IdentifierNode.withValue(val, pos))
def IdentifierParser(input):
identifierLiteralParser = Parser.terminalParser(TokenType.IDENTIFIER, createNode=lambda val, pos: Identifier.withValue(val, pos))
functionCallParser = Parser.allOf(
identifierLiteralParser,
abstractIterableParser(ArgumentsList, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN, MaxPrecedenceExpressionParser),
createNode=lambda name, arguments: FunctionCall.withChildren(name, arguments)
)
assignmentParser = Parser.allOf(
identifierLiteralParser,
Parser.terminalParser(TokenType.ASSIGN, lambda val, pos: Operator.withValue(val, pos)),
MaxPrecedenceExpressionParser,
createNode=lambda identifier, assign, expr: Assignment.withValues(identifier, assign, expr)
)
return Parser.oneOf(
assignmentParser,
functionCallParser,
identifierLiteralParser
)(input)
#
# def __init__(self, pos):
# super().__init__(pos)
# self.children = [None]
#
# @classmethod
# def _lhsParser(cls):
# return Parser.oneOf(
# IdentifierNode._functionCallParser(),
# IdentifierNode._assignmentParser(),
# IdentifierNode.identifierParser()
# )
#
# @staticmethod
# def _assignmentParser():
# def createNode(target, assignment, value):
# node = AssignmentNode(assignment.pos)
# node.target = target
# node.value = value
# return node
#
# return Parser.allOf(
# IdentifierNode.identifierParser(),
# Parser.terminalParser(TokenType.ASSIGN),
# Parser.doAssert(ExpressionNode.parse, "expression"),
# createNode=createNode
# )
#
# @staticmethod
# def _functionCallParser():
# def createNode(name, arguments):
# node = FunctionCallNode(name.pos)
# node.name = name
# node.arguments = arguments
# return node
#
# return Parser.allOf(
# IdentifierNode.identifierParser(),
# ArgumentsListNode.parse,
# createNode=createNode
# )
#
# @staticmethod
# def identifierParser():
# return Parser.terminalParser(TokenType.IDENTIFIER, lambda val, pos: IdentifierNode.withValue(val, pos))