Files
smnp-py/smnp/ast/node/iterable.py
2019-07-06 21:43:43 +02:00

131 lines
3.6 KiB
Python

from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.ignore import IgnoredNode
from smnp.ast.node.model import Node, ParseResult
from smnp.ast.node.none import NoneNode
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
def abstractIterableParser(iterableNodeType, openTokenType, closeTokenType, itemParser):
class AbstractIterableTailNode(ExpressionNode):
def __init__(self, pos):
super().__init__(pos)
self.children.append(NoneNode())
@property
def next(self):
return self[1]
@next.setter
def next(self, value):
self[1] = value
@classmethod
def _parse(cls, input):
return Parser.oneOf(
AbstractIterableTailNode._parser1(),
AbstractIterableTailNode._parser2(),
)(input)
@staticmethod
def _parser1():
return Parser.terminalParser(closeTokenType)
@staticmethod
def _parser2():
def createNode(comma, expr, iterableTail):
node = AbstractIterableTailNode(expr.pos)
node.value = expr
node.next = iterableTail
return node
return Parser.allOf(
Parser.terminalParser(TokenType.COMMA, doAssert=True),
itemParser,
AbstractIterableTailNode.parse,
createNode=createNode
)
class AbstractIterableNode(ExpressionNode):
def __init__(self, pos):
super().__init__(pos)
self.children.append(NoneNode())
@property
def next(self):
return self[1]
@next.setter
def next(self, value):
self[1] = value
@classmethod
def _parse(cls, input):
return Parser.oneOf(
AbstractIterableNode._parser1(),
AbstractIterableNode._parser2()
)(input)
@staticmethod
def _parser1():
def emptyIterable(openToken, closeToken):
node = AbstractIterableNode(openToken.pos)
node.value = openToken
node.next = closeToken
return node
return Parser.allOf(
Parser.terminalParser(openTokenType),
Parser.terminalParser(closeTokenType),
createNode=emptyIterable
)
@staticmethod
def _parser2():
def createNode(openParen, expr, iterableTail):
node = AbstractIterableNode(openParen.pos)
node.value = expr
node.next = iterableTail
return node
return Parser.allOf(
Parser.terminalParser(openTokenType, lambda val, pos: Node(pos)),
itemParser,
AbstractIterableTailNode.parse,
createNode=createNode
)
return toFlatDesiredNode(iterableNodeType, AbstractIterableNode.parse)
def toFlatDesiredNode(iterableNodeType, parser):
def parse(input):
result = parser(input)
if result.result:
value = flattenList(result.node)
node = iterableNodeType(result.node.pos)
node.children.clear()
for v in value:
node.append(v)
return ParseResult.OK(node)
return ParseResult.FAIL()
return parse
def flattenList(node, output=None):
if output is None:
output = []
if type(node.value) != IgnoredNode:
output.append(node.value)
if type(node.next) != IgnoredNode:
flattenList(node.next, output)
return output