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.node.term import TermParser from smnp.ast.parser import Parser from smnp.token.type import TokenType class Sum(BinaryOperator): pass class Relation(BinaryOperator): pass class And(BinaryOperator): pass class Or(BinaryOperator): pass class Loop(BinaryOperator): def __init__(self, pos): super().__init__(pos) self.children.extend([NoneNode(), NoneNode()]) @property def parameters(self): return self[3] @parameters.setter def parameters(self, value): self[3] = value @property def filter(self): return self[4] @filter.setter def filter(self, value): self[4] = value @classmethod def loop(cls, left, parameters, operator, right, filter): node = cls(left.pos) node.left = left node.parameters = parameters node.operator = operator node.right = right node.filter = filter return node class LoopParameters(Node): pass def ExpressionWithoutLoopParser(input): expr1 = Parser.leftAssociativeOperatorParser( TermParser, [TokenType.PLUS, TokenType.MINUS], TermParser, lambda left, op, right: Sum.withValues(left, op, right) ) expr2 = Parser.leftAssociativeOperatorParser( expr1, [TokenType.RELATION, TokenType.OPEN_ANGLE, TokenType.CLOSE_ANGLE], expr1, lambda left, op, right: Relation.withValues(left, op, right) ) expr3 = Parser.leftAssociativeOperatorParser( expr2, [TokenType.AND], expr2, lambda left, op, right: And.withValues(left, op, right) ) return Parser.leftAssociativeOperatorParser( expr3, [TokenType.OR], expr3, lambda left, op, right: Or.withValues(left, op, right) )(input) def LoopParser(input): from smnp.ast.node.identifier import IdentifierLiteralParser from smnp.ast.node.iterable import abstractIterableParser from smnp.ast.node.statement import StatementParser loopParameters = Parser.allOf( Parser.terminal(TokenType.AS), Parser.oneOf( Parser.wrap(IdentifierLiteralParser, lambda id: LoopParameters.withChildren([id], id.pos)), abstractIterableParser(LoopParameters, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN, IdentifierLiteralParser) ), createNode=lambda asKeyword, parameters: parameters, name="loop parameters" ) loopFilter = Parser.allOf( Parser.terminal(TokenType.PERCENT), Parser.doAssert(ExpressionWithoutLoopParser, "filter as bool expression"), createNode=lambda percent, expr: expr, name="loop filter" ) return Parser.allOf( ExpressionWithoutLoopParser, Parser.optional(loopParameters), Parser.terminal(TokenType.DASH, createNode=Operator.withValue), StatementParser, Parser.optional(loopFilter), createNode=Loop.loop, name="dash-loop" )(input) def ExpressionParser(input): return Parser.oneOf( LoopParser, ExpressionWithoutLoopParser )(input)