from smnp.ast.node.block import BlockParser from smnp.ast.node.expression import ExpressionParser from smnp.ast.node.identifier import IdentifierLiteralParser from smnp.ast.node.iterable import abstractIterableParser from smnp.ast.node.model import Node from smnp.ast.node.none import NoneNode from smnp.ast.node.type import TypeParser, Type from smnp.ast.parser import Parser from smnp.token.type import TokenType class ArgumentsDeclaration(Node): pass class Argument(Node): def __init__(self, pos): super().__init__(pos) self.children = [NoneNode(), NoneNode(), False, NoneNode()] @property def type(self): return self[0] @type.setter def type(self, value): self[0] = value @property def variable(self): return self[1] @variable.setter def variable(self, value): self[1] = value @property def vararg(self): return self[2] @vararg.setter def vararg(self, value): self[2] = value @property def optionalValue(self): return self[3] @optionalValue.setter def optionalValue(self, value): self[3] = value class VarargNode(Node): pass class FunctionDefinition(Node): def __init__(self, pos): super().__init__(pos) self.children = [NoneNode(), NoneNode(), NoneNode()] @property def name(self): return self[0] @name.setter def name(self, value): self[0] = value @property def arguments(self): return self[1] @arguments.setter def arguments(self, value): self[1] = value @property def body(self): return self[2] @body.setter def body(self, value): self[2] = value @classmethod def withValues(cls, name, arguments, body): node = cls(name.pos) node.name = name node.arguments = arguments node.body = body return node 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 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 ArgumentParser(input): return Parser.oneOf( OptionalArgumentParser, RegularArgumentParser, name="function argument" )(input) def ArgumentsDeclarationParser(input): return abstractIterableParser( ArgumentsDeclaration, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN, Parser.doAssert(ArgumentParser, "function/method argument") )(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)