Add support for custom functions

This commit is contained in:
Bartłomiej Pluta
2019-07-06 00:20:36 +02:00
parent 2ecc86a9b2
commit f11b3b67f2
8 changed files with 168 additions and 6 deletions

View File

@@ -13,7 +13,7 @@ def main():
lines = [line.rstrip('\n') for line in source.readlines()]
tokens = tokenize(lines)
print(tokens)
ast = Program.parse(tokens)
ast.node.print()

View File

@@ -0,0 +1,67 @@
from smnp.newast.node.block import BlockNode
from smnp.newast.node.identifier import IdentifierNode
from smnp.newast.node.iterable import abstractIterableParser
from smnp.newast.node.model import Node
from smnp.newast.node.none import NoneNode
from smnp.newast.node.statement import StatementNode
from smnp.newast.node.variable import TypedVariableNode
from smnp.newast.parser import Parser
from smnp.token.type import TokenType
class ArgumentsDeclarationNode(Node):
@classmethod
def _parse(cls, input):
raise RuntimeError("This class is not supposed to be automatically called")
class FunctionDefinition(StatementNode):
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 _parse(cls, input):
def createNode(function, name, arguments, body):
node = FunctionDefinition(function.pos)
node.name = name
node.arguments = arguments
node.body = body
return node
return Parser.allOf(
Parser.terminalParser(TokenType.FUNCTION),
IdentifierNode.identifierParser(),
cls._argumentsDeclarationParser(),
BlockNode.parse,
createNode=createNode
)(input)
@staticmethod
def _argumentsDeclarationParser():
return abstractIterableParser(ArgumentsDeclarationNode, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN, TypedVariableNode.parser())

View File

@@ -17,7 +17,7 @@ class IdentifierNode(AccessNode):
return Parser.oneOf(
IdentifierNode._functionCallParser(),
IdentifierNode._assignmentParser(),
IdentifierNode._identifierParser()
IdentifierNode.identifierParser()
)
@staticmethod
@@ -29,7 +29,7 @@ class IdentifierNode(AccessNode):
return node
return Parser.allOf(
IdentifierNode._identifierParser(),
IdentifierNode.identifierParser(),
Parser.terminalParser(TokenType.ASSIGN),
ExpressionNode.parse,
createNode=createNode
@@ -44,11 +44,11 @@ class IdentifierNode(AccessNode):
return node
return Parser.allOf(
IdentifierNode._identifierParser(),
IdentifierNode.identifierParser(),
ArgumentsListNode.parse,
createNode=createNode
)
@staticmethod
def _identifierParser():
def identifierParser():
return Parser.terminalParser(TokenType.IDENTIFIER, lambda val, pos: IdentifierNode.withValue(val, pos))

32
smnp/newast/node/ret.py Normal file
View File

@@ -0,0 +1,32 @@
from smnp.newast.node.expression import ExpressionNode
from smnp.newast.node.none import NoneNode
from smnp.newast.node.statement import StatementNode
from smnp.newast.parser import Parser
from smnp.token.type import TokenType
class ReturnNode(StatementNode):
def __init__(self, pos):
super().__init__(pos)
self.children.append(NoneNode())
@property
def value(self):
return self[0]
@value.setter
def value(self, value):
self[0] = value
@classmethod
def _parse(cls, input):
def createNode(ret, value):
node = ReturnNode(ret.pos)
node.value = value
return node
return Parser.allOf(
Parser.terminalParser(TokenType.RETURN),
ExpressionNode.parse,
createNode=createNode
)(input)

View File

@@ -7,9 +7,13 @@ class StatementNode(Node):
@classmethod
def _parse(cls, input):
from smnp.newast.node.block import BlockNode
from smnp.newast.node.function import FunctionDefinition
from smnp.newast.node.expression import ExpressionNode
from smnp.newast.node.ret import ReturnNode
return Parser.oneOf(
BlockNode.parse,
FunctionDefinition.parse,
ReturnNode.parse,
ExpressionNode.parse
)(input)

13
smnp/newast/node/type.py Normal file
View File

@@ -0,0 +1,13 @@
from smnp.newast.node.access import AccessNode
from smnp.newast.node.literal import LiteralNode
from smnp.token.type import TokenType
class TypeNode(LiteralNode, AccessNode):
def __init__(self, pos):
super().__init__(pos)
del self.children[1]
@classmethod
def _getTokenType(cls):
return TokenType.TYPE

View File

@@ -0,0 +1,46 @@
from smnp.newast.node.expression import ExpressionNode
from smnp.newast.node.identifier import IdentifierNode
from smnp.newast.node.none import NoneNode
from smnp.newast.node.type import TypeNode
from smnp.newast.parser import Parser
from smnp.token.type import TokenType
class TypedVariableNode(ExpressionNode):
def __init__(self, pos):
super().__init__(pos)
self.children.append(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
@classmethod
def parser(cls):
def createNode(type, variable):
node = TypedVariableNode(type.pos)
node.type = type
node.variable = variable
return node
return Parser.allOf(
Parser.terminalParser(TokenType.TYPE, lambda val, pos: TypeNode.withValue(val, pos)),
IdentifierNode.identifierParser(),
createNode=createNode
)
@classmethod
def _parse(cls, input):
#TODO
raise RuntimeError("Not implemented yet. There is still required work to correctly build AST related to IdentifierNode")

View File

@@ -2,4 +2,4 @@ from smnp.token.tools import tokenizeKeyword
from smnp.token.type import TokenType
def tokenizeFunction(input, current, line):
return tokenizeKeyword(TokenType.FUNCTION, 'library', input, current, line)
return tokenizeKeyword(TokenType.FUNCTION, 'function', input, current, line)