Create abstract iterable parser

This commit is contained in:
Bartłomiej Pluta
2019-07-05 18:07:26 +02:00
parent ed73aa1ad1
commit acd9a42e1b
3 changed files with 147 additions and 94 deletions

View File

@@ -0,0 +1,114 @@
from smnp.newast.node.expression import ExpressionNode
from smnp.newast.node.model import Node, ParseResult
from smnp.newast.node.none import NoneNode
from smnp.newast.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),
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 v, pos: Node(pos)),
itemParser,
AbstractIterableTailNode.parse,
createNode=createNode
)
def toDesiredType(parser):
def parse(input):
result = parser(input)
if result.result:
node = iterableNodeType(result.node.pos)
node.children.clear()
node.children.extend([ result.node.value, result.node.next ])
return ParseResult.OK(node)
return ParseResult.FAIL()
return parse
return toDesiredType(AbstractIterableNode.parse)

View File

@@ -1,102 +1,10 @@
from smnp.newast.node.expression import ExpressionNode from smnp.newast.node.expression import ExpressionNode
from smnp.newast.node.model import Node from smnp.newast.node.iterable import abstractIterableParser
from smnp.newast.node.none import NoneNode
from smnp.newast.parser import Parser
from smnp.token.type import TokenType from smnp.token.type import TokenType
class ListTailNode(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(
ListTailNode._parser1(),
ListTailNode._parser2(),
)(input)
# listTail := ']'
@staticmethod
def _parser1():
return Parser.terminalParser(TokenType.CLOSE_PAREN)
# listTail := ',' expr listTail
@staticmethod
def _parser2():
def createNode(comma, expr, listTail):
node = ListTailNode(expr.pos)
node.value = expr
node.next = listTail
return node
return Parser.allOf(
Parser.terminalParser(TokenType.COMMA),
ExpressionNode.parse,
ListTailNode.parse,
createNode=createNode
)
class ListNode(ExpressionNode): class ListNode(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 @classmethod
def _parse(cls, input): def _parse(cls, input):
return Parser.oneOf( return abstractIterableParser(ListNode, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN, ExpressionNode.parse)(input)
ListNode._parser1(),
ListNode._parser2()
)(input)
# list := '[' ']'
@staticmethod
def _parser1():
def emptyList(openParen, closeParen):
node = ListNode(openParen.pos)
node.value = openParen
node.next = closeParen
return node
return Parser.allOf(
Parser.terminalParser(TokenType.OPEN_PAREN),
Parser.terminalParser(TokenType.CLOSE_PAREN),
createNode=emptyList
)
# '[' expr listTail
@staticmethod
def _parser2():
def createNode(openParen, expr, listTail):
node = ListNode(openParen.pos)
node.value = expr
node.next = listTail
return node
return Parser.allOf(
Parser.terminalParser(TokenType.OPEN_PAREN, lambda v, pos: Node(pos)),
ExpressionNode.parse,
ListTailNode.parse,
createNode=createNode
)

View File

@@ -11,3 +11,34 @@ def _flatListNode(listItemNode, list = []):
list.append(value) list.append(value)
_flatListNode(next, list) _flatListNode(next, list)
return list return list
# NEW AST
# def toFlatList(parser):
# def decoratedParser(input):
# result = parser(input)
#
# if result.result:
# value = flattenList(result.node)
# node = iterableNodeType()
# for v in value:
# node.append(v)
# return ParseResult.OK(node)
#
# return ParseResult.FAIL()
#
# return decoratedParser
#
#
# 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