Files
smnp-py/smnp/ast/node/function.py
2019-07-13 23:08:35 +02:00

166 lines
3.9 KiB
Python

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)