From acd9a42e1b6c9be69aeb92dca84e28968f383df1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Pluta?= Date: Fri, 5 Jul 2019 18:07:26 +0200 Subject: [PATCH] Create abstract iterable parser --- smnp/newast/node/iterable.py | 114 +++++++++++++++++++++++++++++++++++ smnp/newast/node/list.py | 96 +---------------------------- smnp/runtime/tools.py | 31 ++++++++++ 3 files changed, 147 insertions(+), 94 deletions(-) create mode 100644 smnp/newast/node/iterable.py diff --git a/smnp/newast/node/iterable.py b/smnp/newast/node/iterable.py new file mode 100644 index 0000000..eeb34e8 --- /dev/null +++ b/smnp/newast/node/iterable.py @@ -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) \ No newline at end of file diff --git a/smnp/newast/node/list.py b/smnp/newast/node/list.py index 53ddf87..5a936e9 100644 --- a/smnp/newast/node/list.py +++ b/smnp/newast/node/list.py @@ -1,102 +1,10 @@ from smnp.newast.node.expression import ExpressionNode -from smnp.newast.node.model import Node -from smnp.newast.node.none import NoneNode -from smnp.newast.parser import Parser +from smnp.newast.node.iterable import abstractIterableParser 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): - 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( - 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 - ) + return abstractIterableParser(ListNode, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN, ExpressionNode.parse)(input) diff --git a/smnp/runtime/tools.py b/smnp/runtime/tools.py index 75ca159..f8c3539 100644 --- a/smnp/runtime/tools.py +++ b/smnp/runtime/tools.py @@ -11,3 +11,34 @@ def _flatListNode(listItemNode, list = []): list.append(value) _flatListNode(next, 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 \ No newline at end of file