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 LiteralParser(input): return Parser.oneOf(IntegerParser, FloatParser, StringParser, NoteParser, BoolParser, TypeLiteralParser, name="literal")(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 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 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 StatementParser(input): from smnp.ast.node.block import BlockParser from smnp.ast.node.condition import IfElseStatementParser from smnp.ast.node.expression import ExpressionParser from smnp.ast.node.ret import ReturnParser from smnp.ast.node.throw import ThrowParser return withSemicolon( Parser.oneOf( IfElseStatementParser, ExpressionParser, # Must be above BlockParser because of Map's syntax with curly braces BlockParser, ReturnParser, ThrowParser, name="statement" ), optional=True)(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 parse(input): root = Program() # Start Symbol startSymbolParser = Parser.oneOf( ImportParser, FunctionDefinitionParser, ExtendParser, StatementParser, exception=lambda inp: SyntaxException( f"Invalid statement: {inp.currentToEndOfLine()}", inp.current().pos), name="start symbol") while input.hasCurrent(): result = startSymbolParser(input) if result.result: root.append(result.node) return ParseResult.OK(root)
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)
def ArgumentParser(input): return Parser.oneOf(OptionalArgumentParser, RegularArgumentParser, name="function argument")(input)
def abstractIterableTailParser(input): return Parser.oneOf( closeIterable, nextItem, )(input)
def abstractIterableParser(input): return Parser.oneOf(emptyIterable, openIterable)(input)
def ExpressionParser(input): return Parser.oneOf(LoopParser, ExpressionWithoutLoopParser)(input)