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.CARET, createNode=Operator.withValue), StatementParser, Parser.optional(loopFilter), createNode=Loop.loop, name="caret-loop")(input)
def ExtendParser(input): simpleExtend = Parser.allOf( Parser.terminal(TokenType.EXTEND), TypeParser, Parser.terminal(TokenType.AS), IdentifierLiteralParser, Parser.terminal(TokenType.WITH), Parser.doAssert( Parser.wrap( FunctionDefinitionParser, lambda method: Block.withChildren([method], method.pos)), "method definition"), createNode=lambda extend, type, _, variable, __, methods: Extend. withValues(extend.pos, type, variable, methods), name="simple extend") multiExtend = Parser.allOf( Parser.terminal(TokenType.EXTEND), Parser.doAssert(TypeParser, "type being extended"), Parser.terminal(TokenType.AS, doAssert=True), Parser.doAssert(IdentifierLiteralParser, "variable name"), Parser.doAssert( MethodsDeclarationParser, f"block with methods definitions or '{TokenType.WITH.key}' keyword" ), createNode=lambda extend, type, _, variable, methods: Extend. withValues(extend.pos, type, variable, methods), name="multiple extend") return Parser.oneOf(simpleExtend, multiExtend, name="extend")(input)
def IfElseStatementParser(input): ifStatementParser = Parser.allOf( Parser.terminal(TokenType.IF), Parser.terminal(TokenType.OPEN_PAREN), ExpressionParser, Parser.terminal(TokenType.CLOSE_PAREN), StatementParser, createNode=lambda _, __, condition, ___, ifStatement: IfElse.createNode(ifStatement, condition), name="if statement" ) ifElseStatementParser = Parser.allOf( Parser.terminal(TokenType.IF), Parser.terminal(TokenType.OPEN_PAREN, doAssert=True), Parser.doAssert(ExpressionParser, "expression"), Parser.terminal(TokenType.CLOSE_PAREN, doAssert=True), Parser.doAssert(StatementParser, "statement"), Parser.terminal(TokenType.ELSE), Parser.doAssert(StatementParser, "statement"), createNode=lambda _, __, condition, ___, ifStatement, ____, elseStatement: IfElse.createNode(ifStatement, condition, elseStatement), name="if-else statement" ) return Parser.oneOf( ifElseStatementParser, ifStatementParser, name="if-else/if statement" )(input)
def ImportParser(input): return Parser.allOf( Parser.terminal(TokenType.IMPORT), Parser.doAssert(StringParser, "import source as string"), createNode=lambda imp, source: Import.withValue(source), name="import" )(input)
def ReturnParser(input): return Parser.allOf( Parser.terminal(TokenType.RETURN), Parser.optional(ExpressionParser), createNode=lambda ret, val: Return.withValue(val, ret.pos), name="return" )(input)
def withSemicolon(parser, optional=False, doAssert=False): semicolonParser = Parser.optional(Parser.terminal(TokenType.SEMICOLON)) if optional else Parser.terminal( TokenType.SEMICOLON, doAssert=doAssert) return Parser.allOf( parser, semicolonParser, createNode=lambda stmt, semicolon: stmt, name="semicolon" + "?" if optional else "" )
def emptyIterable(input): def createNode(open, close): node = AbstractIterable(open.pos) node.value = open node.next = close return node return Parser.allOf(Parser.terminal(openTokenType), Parser.terminal(closeTokenType), createNode=createNode)(input)
def FunctionDefinitionParser(input): return Parser.allOf(Parser.terminal(TokenType.FUNCTION), Parser.doAssert(IdentifierLiteralParser, "function/method name"), Parser.doAssert(ArgumentsDeclarationParser, "function/method arguments"), Parser.doAssert(BlockParser, "function/method body"), createNode=lambda _, name, args, body: FunctionDefinition.withValues(name, args, body), name="function definition")(input)
def IdentifierParser(input): functionCallParser = Parser.allOf( IdentifierLiteralParser, abstractIterableParser(ArgumentsList, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN, Parser.doAssert(ExpressionParser, "expression")), createNode=lambda name, arguments: FunctionCall.withChildren(name, arguments) ) assignmentParser = Parser.allOf( IdentifierLiteralParser, Parser.terminal(TokenType.ASSIGN, createNode=Operator.withValue), Parser.doAssert(ExpressionParser, "expression"), createNode=lambda identifier, assign, expr: Assignment.withValues(identifier, assign, expr) ) return Parser.oneOf( assignmentParser, functionCallParser, IdentifierLiteralParser )(input)
def openIterable(input): def createNode(open, item, tail): node = AbstractIterable(open.pos) node.value = item node.next = tail return node return Parser.allOf(Parser.terminal(openTokenType), itemParser, abstractIterableTailParser, createNode=createNode)(input)
def TypeParser(input): typeWithSpecifier = Parser.allOf( TypeLiteralParser, Parser.many(TypesListParser, createNode=TypeSpecifiers.withChildren), createNode=lambda type, specifiers: Type.withValues( type.pos, type, specifiers), name="type with specifiers?") return Parser.oneOf(typeWithSpecifier, TypesListParser, name="mult. types or type with specifier")(input)
def nextItem(input): def createNode(comma, item, tail): node = AbstractIterableTail(item.pos) node.value = item node.next = tail return node return Parser.allOf(Parser.doAssert( Parser.terminal(TokenType.COMMA), f"'{TokenType.COMMA.key}' or '{closeTokenType.key}'"), itemParser, abstractIterableTailParser, createNode=createNode)(input)
def UnitParser(input): minusOperator = Parser.allOf(Parser.terminal( TokenType.MINUS, createNode=Operator.withValue), Parser.doAssert(AtomParser, "atom"), createNode=MinusOperator.withValues, name="minus") atom2 = Parser.oneOf(minusOperator, AtomParser, name="atom2") return Parser.leftAssociativeOperatorParser( atom2, [TokenType.DOT], Parser.doAssert(atom2, "atom"), createNode=lambda left, op, right: Access.withValues(left, op, right), name="unit")(input)
def MapParser(input): from smnp.ast.node.expression import ExpressionParser keyParser = Parser.oneOf(LiteralParser, IdentifierLiteralParser) valueParser = ExpressionParser mapEntryParser = Parser.allOf(keyParser, Parser.terminal( TokenType.ARROW, createNode=Operator.withValue), Parser.doAssert(valueParser, "expression"), createNode=MapEntry.withValues) return abstractIterableParser(Map, TokenType.OPEN_CURLY, TokenType.CLOSE_CURLY, mapEntryParser)(input)
def OptionalArgumentParser(input): def createNode(type, variable, _, optional): pos = type.pos if isinstance(type, Type) else variable.pos node = Argument(pos) node.type = type node.variable = variable node.optionalValue = optional return node return Parser.allOf(Parser.optional(TypeParser), Parser.doAssert(IdentifierLiteralParser, "argument name"), Parser.terminal(TokenType.ASSIGN), Parser.doAssert(ExpressionParser, "expression"), createNode=createNode, name="optional function argument")(input)
def RegularArgumentParser(input): def createNode(type, variable, vararg): pos = type.pos if isinstance(type, Type) else variable.pos node = Argument(pos) node.type = type node.variable = variable node.vararg = vararg is True return node return Parser.allOf(Parser.optional(TypeParser), Parser.doAssert(IdentifierLiteralParser, "argument name"), Parser.optional( Parser.terminal(TokenType.DOTS, lambda val, pos: True)), createNode=createNode, name="regular function argument")(input)
def AtomParser(input): from smnp.ast.node.identifier import IdentifierParser from smnp.ast.node.list import ListParser from smnp.ast.node.map import MapParser from smnp.ast.node.expression import ExpressionParser parentheses = Parser.allOf(Parser.terminal(TokenType.OPEN_PAREN), Parser.doAssert(ExpressionParser, "expression"), Parser.terminal(TokenType.CLOSE_PAREN), createNode=lambda open, expr, close: expr, name="grouping parentheses") return Parser.oneOf(parentheses, LiteralParser, IdentifierParser, ListParser, MapParser, name="atom")(input)
def FactorParser(input): powerFactor = Parser.leftAssociativeOperatorParser( UnitParser, [TokenType.DOUBLE_ASTERISK], UnitParser, lambda left, op, right: Power.withValues(left, op, right), name="power operator" ) notOperator = Parser.allOf( Parser.terminal(TokenType.NOT, Operator.withValue), powerFactor, createNode=NotOperator.withValues, name="not" ) return Parser.oneOf( notOperator, powerFactor, name="factor" )(input)