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 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 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 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 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 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 BlockParser(input): return Parser.loop( Parser.terminal(TokenType.OPEN_CURLY), Parser.doAssert(StatementParser, f"statement or '{TokenType.CLOSE_CURLY.key}'"), Parser.terminal(TokenType.CLOSE_CURLY), createNode=lambda open, statements, close: Block.withChildren( statements, open.pos))(input)
def MethodsDeclarationParser(input): return Parser.loop( Parser.terminal(TokenType.OPEN_CURLY), Parser.doAssert(FunctionDefinitionParser, f"method definition or '{TokenType.CLOSE_CURLY.key}'"), Parser.terminal(TokenType.CLOSE_CURLY), createNode=lambda open, methods, close: Block.withChildren( methods, open.pos), name="methods block")(input)
def ListParser(input): from smnp.ast.node.expression import ExpressionParser return abstractIterableParser( List, TokenType.OPEN_SQUARE, TokenType.CLOSE_SQUARE, Parser.doAssert(ExpressionParser, "expression") )(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 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 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 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 ArgumentsDeclarationParser(input): return abstractIterableParser( ArgumentsDeclaration, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN, Parser.doAssert(ArgumentParser, "function/method argument"))(input)