5 Commits

Author SHA1 Message Date
Bartłomiej Pluta
a1bc422fba Fix accessing properties and methods in identifiers with EQUAL 2019-07-10 16:25:06 +02:00
Bartłomiej Pluta
98d710ac97 Add equal ('==') operator to strings 2019-07-10 16:02:39 +02:00
Bartłomiej Pluta
d6fb101337 Add equal ('==') operator to both identifiers and bools 2019-07-10 15:58:37 +02:00
Bartłomiej Pluta
e008be7952 Do some refactor with multiple left associative operators 2019-07-10 15:26:35 +02:00
Bartłomiej Pluta
0a7d29d4a1 Working proof of concept of multiple left associative operators 2019-07-10 15:02:17 +02:00
44 changed files with 1173 additions and 1476 deletions

56
smnp/ast/node/access.py Normal file
View File

@@ -0,0 +1,56 @@
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.none import NoneNode
from smnp.ast.parser import Parser
from smnp.error.syntax import SyntaxException
from smnp.token.type import TokenType
class AccessNode(ExpressionNode):
def __init__(self, pos):
super().__init__(pos)
self.children = [ NoneNode(), NoneNode() ]
@property
def left(self):
return self[0]
@left.setter
def left(self, value):
self[0] = value
@property
def right(self):
return self[1]
@right.setter
def right(self, value):
self[1] = value
@classmethod
def accessParser(cls):
def createNode(left, operator, right):
node = AccessNode(right.pos)
node.left = left
node.right = right
return node
return Parser.leftAssociativeOperatorParser(
cls._accessLhs(),
TokenType.DOT,
cls._accessRhs(),
createNode=createNode
)
@classmethod
def _accessLhs(cls):
raise RuntimeError(f"_accessLhs() is not implemented in {cls.__name__} class")
@staticmethod
def _accessRhs():
from smnp.ast.node.identifier import IdentifierNode
return Parser.oneOf(
IdentifierNode.functionCallParser(),
IdentifierNode.identifierParser(),
exception=lambda input: SyntaxException(f"Expected property name or method call, found '{input.current().rawValue}'", input.currentPos())
)

View File

@@ -0,0 +1,28 @@
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.none import NoneNode
class AssignmentNode(ExpressionNode):
def __init__(self, pos):
super().__init__(pos)
self.children.append(NoneNode())
@property
def target(self):
return self[0]
@target.setter
def target(self, value):
self[0] = value
@property
def value(self):
return self[1]
@value.setter
def value(self, value):
self[1] = value
@classmethod
def _parse(cls, input):
raise RuntimeError("This class is not supposed to be automatically called")

28
smnp/ast/node/asterisk.py Normal file
View File

@@ -0,0 +1,28 @@
from smnp.ast.node.none import NoneNode
from smnp.ast.node.statement import StatementNode
class AsteriskNode(StatementNode):
def __init__(self, pos):
super().__init__(pos)
self.children = [NoneNode(), NoneNode()]
@property
def iterator(self):
return self[0]
@iterator.setter
def iterator(self, value):
self[0] = value
@property
def statement(self):
return self[1]
@statement.setter
def statement(self, value):
self[1] = value
@classmethod
def _parse(cls, input):
raise RuntimeError("This class is not supposed to be automatically called")

View File

@@ -1,103 +0,0 @@
from smnp.ast.node.model import Node
from smnp.ast.parser import Parsers
from smnp.token.type import TokenType
from smnp.util.singleton import SingletonParser
class Atom(Node):
def __init__(self, pos):
super().__init__(pos)
self.children = [None]
@property
def value(self):
return self[0]
@value.setter
def value(self, value):
self[0] = value
@classmethod
def withValue(cls, value, pos):
node = cls(pos)
node.value = value
return node
class IntegerLiteral(Atom):
pass
class StringLiteral(Atom):
pass
class NoteLiteral(Atom):
pass
class BoolLiteral(Atom):
pass
class TypeLiteral(Atom):
pass
@SingletonParser
def IntegerParser():
return Parsers.oneOf(
Parsers.terminal(TokenType.INTEGER, lambda val, pos: IntegerLiteral.withValue(int(val), pos)),
Parsers.allOf(
Parsers.terminal(TokenType.MINUS),
Parsers.terminal(TokenType.INTEGER, lambda val, pos: IntegerLiteral.withValue(int(val), pos)),
createNode=lambda minus, integer: IntegerLiteral.withValue(-integer.value, minus.pos),
name="negativeInteger"
),
name="int"
)
@SingletonParser
def StringParser():
return Parsers.terminal(TokenType.STRING, createNode=StringLiteral.withValue)
@SingletonParser
def NoteParser():
return Parsers.terminal(TokenType.NOTE, createNode=NoteLiteral.withValue)
@SingletonParser
def BoolParser():
return Parsers.terminal(TokenType.BOOL, createNode=BoolLiteral.withValue)
@SingletonParser
def TypeParser():
return Parsers.terminal(TokenType.TYPE, createNode=TypeLiteral.withValue)
@SingletonParser
def LiteralParser():
return Parsers.oneOf(
IntegerParser(),
StringParser(),
NoteParser(),
BoolParser(),
TypeParser(),
name="literal"
)
@SingletonParser
def AtomParser():
from smnp.ast.node.identifier import IdentifierParser
return Parsers.oneOf(
LiteralParser(),
IdentifierParser(),
name="atom"
)

View File

@@ -1,19 +1,20 @@
from smnp.ast.node.model import Node
from smnp.ast.node.statement import StatementParser
from smnp.ast.node.statement import StatementNode
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class Block(Node):
pass
class BlockNode(StatementNode):
@classmethod
def _parse(cls, input):
def createNode(start, items, end):
node = BlockNode(start.pos)
node.children = items
return node
def BlockParser(input):
parser = Parser.loop(
Parser.terminalParser(TokenType.OPEN_CURLY),
Parser.doAssert(StatementParser, f"statement or '{TokenType.CLOSE_CURLY.key}'"),
Parser.terminalParser(TokenType.CLOSE_CURLY),
createNode=lambda open, statements, close: Block.withChildren(statements, open.pos)
)
return Parser(parser, "block", [parser])(input)
return Parser.loop(
Parser.terminalParser(TokenType.OPEN_CURLY),
Parser.doAssert(StatementNode.parse, f"statement or '{TokenType.CLOSE_CURLY.key}'"),
Parser.terminalParser(TokenType.CLOSE_CURLY),
createNode=createNode,
)(input)

32
smnp/ast/node/bool.py Normal file
View File

@@ -0,0 +1,32 @@
from smnp.ast.node.access import AccessNode
from smnp.ast.node.literal import LiteralNode
from smnp.ast.node.relation import RelationOperatorNode
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class BoolLiteralNode(LiteralNode, AccessNode, RelationOperatorNode):
def __init__(self, pos):
super().__init__(pos)
del self.children[1]
@classmethod
def _getTokenType(cls):
return TokenType.BOOL
@classmethod
def _parse(cls, input):
x = Parser.oneOf(
cls.accessParser(),
cls.relationParser(),
cls.literalParser()
)(input)
return x
@classmethod
def _accessLhs(cls):
return cls.literalParser()
@classmethod
def _relationLhs(cls):
return cls.literalParser()

View File

@@ -1,32 +0,0 @@
from smnp.ast.node.list import ListParser
from smnp.ast.node.operator import BinaryOperator
from smnp.ast.node.valuable import Valuable
from smnp.ast.parser import Parsers
from smnp.token.type import TokenType
from smnp.util.singleton import SingletonParser
class Chain(Valuable):
pass
@SingletonParser
def ChainParser():
from smnp.ast.node.atom import AtomParser
itemParser = Parsers.oneOf(
ListParser,
#MapParser,
AtomParser,
name="chainItem"
)
return Parsers.leftAssociativeOperatorParser(
itemParser,
[TokenType.DOT],
itemParser,
lambda left, op, right: Chain.withValue(BinaryOperator.withValues(left, op, right)),
name="chain"
)

View File

@@ -1,74 +0,0 @@
from smnp.ast.node.expression import MaxPrecedenceExpressionParser
from smnp.ast.node.model import Node
from smnp.ast.node.none import NoneNode
from smnp.ast.node.statement import StatementParser
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class IfElse(Node):
def __init__(self, pos):
super().__init__(pos)
self.children = [NoneNode(), NoneNode(), NoneNode()]
@property
def condition(self):
return self[0]
@condition.setter
def condition(self, value):
self[0] = value
@property
def ifNode(self):
return self[1]
@ifNode.setter
def ifNode(self, value):
self[1] = value
@property
def elseNode(self):
return self[2]
@elseNode.setter
def elseNode(self, value):
self[2] = value
@classmethod
def createNode(cls, ifNode, condition, elseNode=NoneNode()):
node = cls(ifNode.pos)
node.ifNode = ifNode
node.condition = condition
node.elseNode = elseNode
return node
def IfElseStatementParser(input):
ifStatementParser = Parser.allOf(
Parser.terminalParser(TokenType.IF),
Parser.terminalParser(TokenType.OPEN_PAREN),
MaxPrecedenceExpressionParser,
Parser.terminalParser(TokenType.CLOSE_PAREN),
StatementParser,
createNode=lambda _, __, condition, ___, ifStatement: IfElse.createNode(ifStatement, condition),
name="if statement"
)
ifElseStatementParser = Parser.allOf(
Parser.terminalParser(TokenType.IF),
Parser.terminalParser(TokenType.OPEN_PAREN),
MaxPrecedenceExpressionParser,
Parser.terminalParser(TokenType.CLOSE_PAREN),
StatementParser,
Parser.terminalParser(TokenType.ELSE),
StatementParser,
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)

View File

@@ -1,63 +1,66 @@
from smnp.ast.node.operator import BinaryOperator
from smnp.ast.node.term import TermParser
from smnp.ast.node.valuable import Valuable
from smnp.ast.node.asterisk import AsteriskNode
from smnp.ast.node.model import Node
from smnp.ast.node.none import NoneNode
from smnp.ast.node.statement import StatementNode
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class Expression(Valuable):
pass
class ExpressionNode(Node):
def __init__(self, pos):
super().__init__(pos, [NoneNode()])
@property
def value(self):
return self[0]
def ExpressionParser(input):
return Parser.leftAssociativeOperatorParser(
TermParser,
[TokenType.PLUS, TokenType.MINUS],
TermParser,
lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right))
)(input)
@value.setter
def value(self, v):
self[0] = v
def Expression2Parser(input):
return Parser.leftAssociativeOperatorParser(
ExpressionParser,
[TokenType.RELATION],
ExpressionParser,
lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right))
)(input)
@classmethod
def withValue(cls, val, pos):
node = cls(pos)
node.value = val
return node
@classmethod
def _parse(cls, input):
return Parser.oneOf(
cls._asteriskParser(),
cls._expressionParser(),
)(input)
def Expression3Parser(input):
return Parser.leftAssociativeOperatorParser(
Expression2Parser,
[TokenType.AND],
Expression2Parser,
lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right))
)(input)
@classmethod
def _asteriskParser(cls):
def createNode(iterator, asterisk, statement):
node = AsteriskNode(asterisk.pos)
node.iterator = iterator
node.statement = statement
return node
return Parser.allOf(
cls._expressionParser(),
Parser.terminalParser(TokenType.ASTERISK),
Parser.doAssert(StatementNode.parse, 'statement'),
createNode=createNode
)
def Expression4Parser(input):
from smnp.ast.node.condition import IfElse
exprParser = Parser.leftAssociativeOperatorParser(
Expression3Parser,
[TokenType.OR],
Expression3Parser,
lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right))
)
@classmethod
def _expressionParser(cls):
from smnp.ast.node.bool import BoolLiteralNode
ifElseExpression = Parser.allOf(
exprParser,
Parser.terminalParser(TokenType.IF),
Expression4Parser,
Parser.terminalParser(TokenType.ELSE),
Expression4Parser,
createNode=lambda ifNode, _, condition, __, elseNode: IfElse.createNode(ifNode, condition, elseNode)
)
return Parser.oneOf(
ifElseExpression,
exprParser,
)(input)
MaxPrecedenceExpressionParser = Expression4Parser
from smnp.ast.node.identifier import IdentifierNode
from smnp.ast.node.string import StringLiteralNode
return Parser.oneOf(
#IntegerLiteralNode.parse,
StringLiteralNode.parse,
#NoteLiteralNode.parse,
BoolLiteralNode.parse,
IdentifierNode.parse,
#MapNode.parse,
#ListNode.parse,
#TypeNode.parse,
)

View File

@@ -1,70 +1,70 @@
# from smnp.ast.node.block import BlockNode
# from smnp.ast.node.function import FunctionDefinitionNode
# from smnp.ast.node.identifier import IdentifierNode
# from smnp.ast.node.none import NoneNode
# from smnp.ast.node.statement import StatementNode
# from smnp.ast.node.type import TypeNode
# from smnp.ast.parser import Parser
# from smnp.token.type import TokenType
#
#
# class ExtendNode(StatementNode):
# def __init__(self, pos):
# super().__init__(pos)
# self.children = [NoneNode(), NoneNode(), 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 methods(self):
# return self[2]
#
# @methods.setter
# def methods(self, value):
# self[2] = value
#
# @classmethod
# def _parse(cls, input):
# def createNode(extend, type, asKeyword, variable, methods):
# node = ExtendNode(extend.pos)
# node.type = type
# node.variable = variable
# node.methods = methods
# return node
#
# return Parser.allOf(
# Parser.terminalParser(TokenType.EXTEND),
# Parser.doAssert(TypeNode.parse, "type being extended"),
# Parser.terminalParser(TokenType.AS, doAssert=True),
# Parser.doAssert(IdentifierNode.identifierParser(), "variable name"),
# Parser.doAssert(cls._methodsDeclarationsParser(), "methods declarations"),
# createNode=createNode
# )(input)
#
# @classmethod
# def _methodsDeclarationsParser(cls):
# def createNode(openBracket, items, closeBracket):
# node = BlockNode(openBracket.pos)
# node.children = items
# return node
#
# return Parser.loop(
# Parser.terminalParser(TokenType.OPEN_CURLY),
# Parser.doAssert(FunctionDefinitionNode.parse, f"method declaration or '{TokenType.CLOSE_CURLY.key}'"),
# Parser.terminalParser(TokenType.CLOSE_CURLY),
# createNode=createNode
# )
from smnp.ast.node.block import BlockNode
from smnp.ast.node.function import FunctionDefinitionNode
from smnp.ast.node.identifier import IdentifierNode
from smnp.ast.node.none import NoneNode
from smnp.ast.node.statement import StatementNode
from smnp.ast.node.type import TypeNode
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class ExtendNode(StatementNode):
def __init__(self, pos):
super().__init__(pos)
self.children = [NoneNode(), NoneNode(), 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 methods(self):
return self[2]
@methods.setter
def methods(self, value):
self[2] = value
@classmethod
def _parse(cls, input):
def createNode(extend, type, asKeyword, variable, methods):
node = ExtendNode(extend.pos)
node.type = type
node.variable = variable
node.methods = methods
return node
return Parser.allOf(
Parser.terminalParser(TokenType.EXTEND),
Parser.doAssert(TypeNode.parse, "type being extended"),
Parser.terminalParser(TokenType.AS, doAssert=True),
Parser.doAssert(IdentifierNode.identifierParser(), "variable name"),
Parser.doAssert(cls._methodsDeclarationsParser(), "methods declarations"),
createNode=createNode
)(input)
@classmethod
def _methodsDeclarationsParser(cls):
def createNode(openBracket, items, closeBracket):
node = BlockNode(openBracket.pos)
node.children = items
return node
return Parser.loop(
Parser.terminalParser(TokenType.OPEN_CURLY),
Parser.doAssert(FunctionDefinitionNode.parse, f"method declaration or '{TokenType.CLOSE_CURLY.key}'"),
Parser.terminalParser(TokenType.CLOSE_CURLY),
createNode=createNode
)

View File

@@ -1,64 +0,0 @@
from smnp.ast.node.chain import ChainParser
from smnp.ast.node.operator import BinaryOperator, Operator, UnaryOperator
from smnp.ast.node.valuable import Valuable
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class Factor(Valuable):
pass
class NotOperator(UnaryOperator):
pass
class Loop(BinaryOperator):
pass
def FactorParser(input):
from smnp.ast.node.expression import MaxPrecedenceExpressionParser
from smnp.ast.node.statement import StatementParser
powerFactor = Parser.leftAssociativeOperatorParser(
ChainParser,
[TokenType.DOUBLE_ASTERISK],
ChainParser,
lambda left, op, right: Factor.withValue(BinaryOperator.withValues(left, op, right)),
name="power operator"
)
exprFactor = Parser.allOf(
Parser.terminalParser(TokenType.OPEN_PAREN),
MaxPrecedenceExpressionParser,
Parser.terminalParser(TokenType.CLOSE_PAREN),
createNode=lambda open, expr, close: expr,
name="grouping parentheses"
)
factorParser = Parser.oneOf(
powerFactor,
exprFactor,
name="basic factor"
)
notOperator = Parser.allOf(
Parser.terminalParser(TokenType.NOT, Operator.withValue),
factorParser,
createNode=NotOperator.withValues,
name="not"
)
loopFactor = Parser.allOf(
factorParser,
Parser.terminalParser(TokenType.DASH, createNode=Operator.withValue),
StatementParser,
createNode=Loop.withValues,
name="dash-loop"
)
return Parser.oneOf(
loopFactor,
notOperator,
factorParser
)(input)

View File

@@ -1,128 +1,128 @@
# from smnp.ast.node.block import BlockNode
# from smnp.ast.node.expression import ExpressionNode
# from smnp.ast.node.identifier import IdentifierNode
# 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.statement import StatementNode
# from smnp.ast.node.type import TypeNode, TypeSpecifier
# from smnp.ast.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 VarargNode(Node):
# pass
#
#
# class ArgumentDefinitionNode(ExpressionNode):
# def __init__(self, pos):
# super().__init__(pos)
# self.children.extend([NoneNode(), False])
#
# @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
#
#
# @classmethod
# def parser(cls):
# def createNode(type, variable, dots):
# node = ArgumentDefinitionNode(type.pos)
# node.type = type
# node.variable = variable
# node.vararg = isinstance(dots, VarargNode)
# return node
#
# return Parser.allOf(
# Parser.optional(Parser.oneOf(
# TypeNode.parse,
# TypeSpecifier.parse
# )),
# Parser.doAssert(IdentifierNode.identifierParser(), "variable name"),
# Parser.optional(Parser.terminalParser(TokenType.DOTS, lambda val, pos: VarargNode(pos))),
# 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")
#
#
#
# class FunctionDefinitionNode(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 = FunctionDefinitionNode(function.pos)
# node.name = name
# node.arguments = arguments
# node.body = body
# return node
#
# return Parser.allOf(
# Parser.terminalParser(TokenType.FUNCTION),
# Parser.doAssert(IdentifierNode.identifierParser(), "function name"),
# Parser.doAssert(cls._argumentsDeclarationParser(), "arguments list"),
# Parser.doAssert(BlockNode.parse, "function body"),
# createNode=createNode
# )(input)
#
# @staticmethod
# def _argumentsDeclarationParser():
# return abstractIterableParser(ArgumentsDeclarationNode, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN, ArgumentDefinitionNode.parser())
from smnp.ast.node.block import BlockNode
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.identifier import IdentifierNode
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.statement import StatementNode
from smnp.ast.node.type import TypeNode, TypeSpecifier
from smnp.ast.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 VarargNode(Node):
pass
class ArgumentDefinitionNode(ExpressionNode):
def __init__(self, pos):
super().__init__(pos)
self.children.extend([NoneNode(), False])
@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
@classmethod
def parser(cls):
def createNode(type, variable, dots):
node = ArgumentDefinitionNode(type.pos)
node.type = type
node.variable = variable
node.vararg = isinstance(dots, VarargNode)
return node
return Parser.allOf(
Parser.optional(Parser.oneOf(
TypeNode.parse,
TypeSpecifier.parse
)),
Parser.doAssert(IdentifierNode.identifierParser(), "variable name"),
Parser.optional(Parser.terminalParser(TokenType.DOTS, lambda val, pos: VarargNode(pos))),
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")
class FunctionDefinitionNode(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 = FunctionDefinitionNode(function.pos)
node.name = name
node.arguments = arguments
node.body = body
return node
return Parser.allOf(
Parser.terminalParser(TokenType.FUNCTION),
Parser.doAssert(IdentifierNode.identifierParser(), "function name"),
Parser.doAssert(cls._argumentsDeclarationParser(), "arguments list"),
Parser.doAssert(BlockNode.parse, "function body"),
createNode=createNode
)(input)
@staticmethod
def _argumentsDeclarationParser():
return abstractIterableParser(ArgumentsDeclarationNode, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN, ArgumentDefinitionNode.parser())

View File

@@ -1,75 +1,73 @@
from smnp.ast.node.atom import Atom
from smnp.ast.node.model import Node
from smnp.ast.node.none import NoneNode
from smnp.ast.node.operator import BinaryOperator, Operator
from smnp.ast.parser import Parsers
from smnp.ast.node.access import AccessNode
from smnp.ast.node.assignment import AssignmentNode
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.invocation import FunctionCallNode, ArgumentsListNode
from smnp.ast.node.relation import RelationOperatorNode
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
from smnp.util.singleton import SingletonParser
class Identifier(Atom):
pass
class FunctionCall(Node):
class IdentifierNode(AccessNode, RelationOperatorNode):
def __init__(self, pos):
super().__init__(pos)
self.children = [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
del self.children[1]
@classmethod
def withChildren(cls, name, arguments):
node = cls(name.pos)
node.name = name
node.arguments = arguments
return node
def _parse(cls, input):
return Parser.oneOf(
cls.relationParser(),
cls.accessParser(),
cls.literalParser()
)(input)
@classmethod
def _accessLhs(cls):
return cls.literalParser()
class ArgumentsList(Node):
pass
@classmethod
def _relationLhs(cls):
return Parser.oneOf(
cls.accessParser(),
cls.literalParser()
)
@classmethod
def literalParser(cls):
return Parser.oneOf(
IdentifierNode.functionCallParser(),
IdentifierNode._assignmentParser(),
IdentifierNode.identifierParser()
)
class Assignment(BinaryOperator):
pass
@staticmethod
def _assignmentParser():
def createNode(target, assignment, value):
node = AssignmentNode(assignment.pos)
node.target = target
node.value = value
return node
return Parser.allOf(
IdentifierNode.identifierParser(),
Parser.terminalParser(TokenType.ASSIGN),
Parser.doAssert(ExpressionNode.parse, "expression"),
createNode=createNode
)
@SingletonParser
def IdentifierParser():
identifierLiteralParser = Parsers.terminal(TokenType.IDENTIFIER, createNode=Identifier.withValue)
@staticmethod
def functionCallParser():
def createNode(name, arguments):
node = FunctionCallNode(name.pos)
node.name = name
node.arguments = arguments
return node
functionCallParser = Parsers.allOf(
identifierLiteralParser,
#abstractIterableParser(ArgumentsList, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN, MaxPrecedenceExpressionParser),
createNode=lambda name, arguments: FunctionCall.withChildren(name, arguments),
name="functionCall"
)
return Parser.allOf(
IdentifierNode.identifierParser(),
ArgumentsListNode.parse,
createNode=createNode
)
assignmentParser = Parsers.allOf(
identifierLiteralParser,
Parsers.terminal(TokenType.ASSIGN, createNode=Operator.withValue),
#MaxPrecedenceExpressionParser,
createNode=lambda identifier, assign, expr: Assignment.withValues(identifier, assign, expr),
name="assignment"
)
return Parsers.oneOf(
assignmentParser,
functionCallParser,
identifierLiteralParser,
name="idExpr"
)
@staticmethod
def identifierParser():
return Parser.terminalParser(TokenType.IDENTIFIER, lambda val, pos: IdentifierNode.withValue(val, pos))

View File

@@ -1,21 +1,16 @@
# from smnp.ast.node.identifier import Identifier
# from smnp.ast.node.model import Node
# from smnp.ast.node.none import NoneNode
# from smnp.ast.node.string import StringLiteralNode
# from smnp.ast.node.type import TypeNode
# from smnp.ast.parser import Parser
# from smnp.token.type import TokenType
#
from smnp.ast.node.atom import StringParser
from smnp.ast.node.identifier import IdentifierNode
from smnp.ast.node.model import Node
from smnp.ast.node.none import NoneNode
from smnp.ast.node.string import StringLiteralNode
from smnp.ast.node.type import TypeNode
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class Import(Node):
class ImportNode(Node):
def __init__(self, pos):
super().__init__(pos)
self.children = [None]
self.children = [NoneNode(), NoneNode(), NoneNode()]
@property
def source(self):
@@ -25,17 +20,57 @@ class Import(Node):
def source(self, value):
self[0] = value
@property
def type(self):
return self[1]
@type.setter
def type(self, value):
self[1] = value
@property
def variable(self):
return self[2]
@variable.setter
def variable(self, value):
self[2] = value
@classmethod
def withValue(cls, value):
node = cls(value.pos)
node.source = value
return node
def _parse(cls, input):
return Parser.oneOf(
cls._literalImportParser(),
cls._fileImportParser()
)(input)
@classmethod
def _literalImportParser(cls):
def createNode(importKeyword, type, fromKeyword, source, asKeyword, variable):
node = ImportNode(importKeyword.pos)
node.source = source
node.type = type
node.variable = variable
return node
def ImportParser(input):
return Parser.allOf(
Parser.terminalParser(TokenType.IMPORT),
StringParser,
createNode=lambda imp, source: Import.withValue(source),
name="import"
)(input)
return Parser.allOf(
Parser.terminalParser(TokenType.IMPORT),
TypeNode.parse,
Parser.doAssert(Parser.terminalParser(TokenType.FROM), "'from <source> as <variable name>'"),
Parser.doAssert(StringLiteralNode.literalParser(), "source as a string"),
Parser.doAssert(Parser.terminalParser(TokenType.AS), "'as <variable name>'"),
Parser.doAssert(IdentifierNode.identifierParser(), "variable name"),
createNode=createNode
)
@classmethod
def _fileImportParser(cls):
def createNode(importKeyword, source):
node = ImportNode(importKeyword.pos)
node.source = source
return node
return Parser.allOf(
Parser.terminalParser(TokenType.IMPORT),
Parser.doAssert(StringLiteralNode.literalParser(), "source as a string"),
createNode=createNode
)

37
smnp/ast/node/integer.py Normal file
View File

@@ -0,0 +1,37 @@
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class IntegerLiteralNode(ExpressionNode):
def __init__(self, pos):
super().__init__(pos)
#TODO del self.children[1]
# TODO: To Remove
@classmethod
def _parse(cls, input):
return cls._literalParser()(input)
@classmethod
def _literalParser(cls):
return Parser.oneOf(
cls._negativeIntegerParser(),
cls._positiveIntegerParser()
)
@classmethod
def _negativeIntegerParser(cls):
def createNode(minus, integer):
return IntegerLiteralNode.withValue(-integer.value, minus.pos)
return Parser.allOf(
Parser.terminalParser(TokenType.MINUS),
Parser.doAssert(cls._positiveIntegerParser(), "integer"),
createNode=createNode
)
@classmethod
def _positiveIntegerParser(cls):
return Parser.terminalParser(TokenType.INTEGER, lambda val, pos: IntegerLiteralNode.withValue(int(val), pos))

View File

@@ -0,0 +1,40 @@
from smnp.ast.node.access import AccessNode
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.iterable import abstractIterableParser
from smnp.ast.node.model import Node
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class ArgumentsListNode(Node):
@classmethod
def _parse(cls, input):
return abstractIterableParser(ArgumentsListNode, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN,
Parser.doAssert(ExpressionNode.parse, "expression"))(input)
class FunctionCallNode(AccessNode):
def __init__(self, pos):
super().__init__(pos)
@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
@classmethod
def _parse(cls, input):
raise RuntimeError("This class is not supposed to be automatically called")

View File

@@ -1,24 +1,17 @@
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.ignore import IgnoredNode
from smnp.ast.node.model import Node, ParseResult
from smnp.ast.node.none import NoneNode
from smnp.ast.parser import Parsers, DecoratorParser
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
def abstractIterableParser(iterableNodeType, openTokenType, closeTokenType, itemParser, name):
class AbstractIterable(Node):
def abstractIterableParser(iterableNodeType, openTokenType, closeTokenType, itemParser):
class AbstractIterableTailNode(ExpressionNode):
def __init__(self, pos):
super().__init__(pos)
self.children = [NoneNode(), NoneNode()]
@property
def value(self):
return self[0]
@value.setter
def value(self, value):
self[0] = value
self.children.append(NoneNode())
@property
def next(self):
@@ -28,77 +21,89 @@ def abstractIterableParser(iterableNodeType, openTokenType, closeTokenType, item
def next(self, value):
self[1] = value
class AbstractIterableTail(AbstractIterable):
pass
@classmethod
def _parse(cls, input):
return Parser.oneOf(
AbstractIterableTailNode._parser1(),
AbstractIterableTailNode._parser2(),
)(input)
def abstractIterableParser():
return Parsers.oneOf(
emptyIterable(),
openIterable(),
name=name
)
@staticmethod
def _parser1():
return Parser.terminalParser(closeTokenType)
def emptyIterable():
def createNode(open, close):
node = AbstractIterable(open.pos)
node.value = open
node.next = close
return node
@staticmethod
def _parser2():
def createNode(comma, expr, iterableTail):
node = AbstractIterableTailNode(expr.pos)
node.value = expr
node.next = iterableTail
return node
return Parsers.allOf(
Parsers.terminal(openTokenType),
Parsers.terminal(closeTokenType),
createNode=createNode,
name=name+"Empty"
)
return Parser.allOf(
Parser.terminalParser(TokenType.COMMA, doAssert=True),
itemParser,
AbstractIterableTailNode.parse,
createNode=createNode
)
def openIterable():
def createNode(open, item, tail):
node = AbstractIterable(open.pos)
node.value = item
node.next = tail
return node
class AbstractIterableNode(ExpressionNode):
def __init__(self, pos):
super().__init__(pos)
return Parsers.allOf(
Parsers.terminal(openTokenType),
itemParser,
abstractIterableTailParser(),
createNode=createNode,
name=name+"Open"
)
self.children.append(NoneNode())
def abstractIterableTailParser():
return Parsers.oneOf(
closeIterable(),
nextItem(),
name=name+"Tail"
)
@property
def next(self):
return self[1]
def nextItem():
def createNode(comma, item, tail):
node = AbstractIterableTail(item.pos)
node.value = item
node.next = tail
return node
@next.setter
def next(self, value):
self[1] = value
return Parsers.allOf(
Parsers.terminal(TokenType.COMMA, doAssert=True),
itemParser,
abstractIterableTailParser(),
name=name+"NextItem",
createNode=createNode
)
@classmethod
def _parse(cls, input):
return Parser.oneOf(
AbstractIterableNode._parser1(),
AbstractIterableNode._parser2()
)(input)
def closeIterable():
return Parsers.terminal(closeTokenType)
@staticmethod
def _parser1():
def emptyIterable(openToken, closeToken):
node = AbstractIterableNode(openToken.pos)
node.value = openToken
node.next = closeToken
return node
return Parser.allOf(
Parser.terminalParser(openTokenType),
Parser.terminalParser(closeTokenType),
createNode=emptyIterable
)
return abstractIterableParser()
#return toFlatDesiredNode(iterableNodeType, abstractIterableParser())
@staticmethod
def _parser2():
def createNode(openParen, expr, iterableTail):
node = AbstractIterableNode(openParen.pos)
node.value = expr
node.next = iterableTail
return node
return Parser.allOf(
Parser.terminalParser(openTokenType, lambda val, pos: Node(pos)),
itemParser,
AbstractIterableTailNode.parse,
createNode=createNode
)
return toFlatDesiredNode(iterableNodeType, AbstractIterableNode.parse)
def toFlatDesiredNode(iterableNodeType, parser):
def wrapper(result):
def parse(input):
result = parser(input)
if result.result:
value = flattenList(result.node)
node = iterableNodeType(result.node.pos)
@@ -109,7 +114,7 @@ def toFlatDesiredNode(iterableNodeType, parser):
return ParseResult.FAIL()
return DecoratorParser(wrapper, parser)
return parse
def flattenList(node, output=None):

View File

@@ -1,13 +1,17 @@
from smnp.ast.node.atom import AtomParser
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.iterable import abstractIterableParser
from smnp.ast.node.model import Node
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class List(Node):
pass
class ListNode(ExpressionNode):
# TODO: To Remove
@classmethod
def _parse(cls, input):
return cls._literalParser()(input)
def ListParser():
return abstractIterableParser(List, TokenType.OPEN_SQUARE, TokenType.CLOSE_SQUARE, AtomParser(), name="list")
#MaxPrecedenceExpressionParser)(input)
@classmethod
def _literalParser(cls):
return abstractIterableParser(ListNode, TokenType.OPEN_SQUARE, TokenType.CLOSE_SQUARE,
Parser.doAssert(ExpressionNode.parse, "expression"))

18
smnp/ast/node/literal.py Normal file
View File

@@ -0,0 +1,18 @@
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.parser import Parser
class LiteralNode(ExpressionNode):
@classmethod
def _getTokenType(cls):
pass
@classmethod
def _processValue(cls, value):
return value
@classmethod
def literalParser(cls):
createNode = lambda val, pos: cls.withValue(cls._processValue(val), pos)
return Parser.terminalParser(cls._getTokenType(), createNode)

View File

@@ -1,11 +1,19 @@
from smnp.ast.node.access import AccessNode
from smnp.ast.node.bool import BoolLiteralNode
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.integer import IntegerLiteralNode
from smnp.ast.node.iterable import abstractIterableParser
from smnp.ast.node.model import Node
from smnp.ast.node.operator import BinaryOperator, Operator
from smnp.ast.parser import Parsers
from smnp.ast.node.none import NoneNode
from smnp.ast.node.note import NoteLiteralNode
from smnp.ast.node.string import StringLiteralNode
from smnp.ast.node.type import TypeNode
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class MapEntry(BinaryOperator):
class MapEntry(ExpressionNode):
def __init__(self, pos):
super().__init__(pos)
self.children = [NoneNode(), NoneNode()]
@property
def key(self):
@@ -17,31 +25,39 @@ class MapEntry(BinaryOperator):
@property
def value(self):
return self[2]
return self[1]
@value.setter
def value(self, value):
self[2] = value
self[1] = value
class MapNode(AccessNode):
class Map(Node):
pass
@classmethod
def _literalParser(cls):
return abstractIterableParser(MapNode, TokenType.OPEN_CURLY, TokenType.CLOSE_CURLY, cls._entryParser())
@classmethod
def _entryParser(cls):
def createNode(key, arrow, value):
node = MapEntry(key.pos)
node.key = key
node.value = value
return node
def MapParser(input):
from smnp.ast.node.atom import LiteralParser
#from smnp.ast.node.expression import MaxPrecedenceExpressionParser
keyParser = LiteralParser
#valueParser = MaxPrecedenceExpressionParser
mapEntryParser = Parsers.allOf(
keyParser,
Parsers.terminal(TokenType.ARROW, createNode=Operator.withValue),
#valueParser,
createNode=MapEntry.withValues,
name="mapEntry"
)
return abstractIterableParser(Map, TokenType.OPEN_CURLY, TokenType.CLOSE_CURLY, mapEntryParser)
return Parser.allOf(
cls._keyParser(),
Parser.terminalParser(TokenType.ARROW),
ExpressionNode.parse,
createNode=createNode
)
@classmethod
def _keyParser(cls):
return Parser.oneOf(
IntegerLiteralNode._literalParser(),
StringLiteralNode._literalParser(),
NoteLiteralNode._literalParser(),
BoolLiteralNode._literalParser(),
TypeNode.parse
)

View File

@@ -47,7 +47,7 @@ class Node:
self._print(first=True)
def _print(self, prefix="", last=True, first=False):
print(prefix, '' if first else '└─' if last else '├─', self.__class__.__name__, f" (line {self.pos[0]+1}, col {self.pos[1]+1})", sep="")
print(prefix, '' if first else '└─' if last else '├─', self.__class__.__name__, sep="")
prefix += ' ' if last else ''
for i, child in enumerate(self.children):
last = i == len(self.children) - 1

18
smnp/ast/node/note.py Normal file
View File

@@ -0,0 +1,18 @@
from smnp.ast.node.literal import LiteralNode
from smnp.token.type import TokenType
class NoteLiteralNode(LiteralNode):
def __init__(self, pos):
super().__init__(pos)
#TODO del self.children[1]
# TODO: To Remove
@classmethod
def _parse(cls, input):
return cls.literalParser()(input)
@classmethod
def _getTokenType(cls):
return TokenType.NOTE

View File

@@ -1,136 +1,7 @@
from smnp.ast.node.model import Node
from smnp.ast.node.none import NoneNode
class UnaryOperator(Node):
def __init__(self, pos):
super().__init__(pos)
self.children=[NoneNode(), NoneNode()]
@property
def operator(self):
return self[0]
@operator.setter
def operator(self, value):
self[0] = value
@property
def value(self):
return self[1]
@value.setter
def value(self, value):
self[1] = value
@classmethod
def withValues(cls, operator, value):
node = cls(operator.pos)
node.operator = operator
node.value = value
return node
class BinaryOperator(Node):
def __init__(self, pos):
super().__init__(pos)
self.children = [NoneNode(), NoneNode(), NoneNode()]
@property
def left(self):
return self[0]
@left.setter
def left(self, value):
self[0] = value
@property
def operator(self):
return self[1]
@operator.setter
def operator(self, value):
self[1] = value
@property
def right(self):
return self[2]
@right.setter
def right(self, value):
self[2] = value
@classmethod
def withValues(cls, left, operator, right):
node = cls(operator.pos)
node.left = left
node.operator = operator
node.right = right
return node
#
# class LeftAssociativeOperatorNode(ExpressionNode):
# def __init__(self, pos):
# super().__init__(pos)
# self.children = [NoneNode(), NoneNode(), NoneNode()]
#
# @property
# def left(self):
# return self[0]
#
# @left.setter
# def left(self, value):
# self[0] = value
#
# @property
# def operator(self):
# return self[1]
#
# @operator.setter
# def operator(self, value):
# self[1] = value
#
# @property
# def right(self):
# return self[2]
#
# @right.setter
# def right(self, value):
# self[2] = value
#
# @classmethod
# def _parse(cls, input):
# def createNode(left, operator, right):
# node = LeftAssociativeOperatorNode(right.pos)
# node.left = left
# node.operator = operator
# node.right = right
# return node
#
# return Parser.leftAssociativeOperatorParser(
# cls._lhsParser(),
# TokenType.DOT,
# cls._rhsParser(),
# createNode=createNode
# )(input)
#
# @classmethod
# def _lhsParser(cls):
# raise RuntimeError(f"LHS parser is not implemented in {cls.__name__}")
#
# @staticmethod
# def _rhsParser():
# from smnp.ast.node.identifier import IdentifierNode
#
# return Parser.oneOf(
# # TODO!!!
# IdentifierNode._lhsParser(),
# IdentifierNode._functionCallParser(),
# exception=lambda input: SyntaxException(f"Expected property name or method call, found '{input.current().rawValue}'", input.currentPos())
# )
#
#
class Operator(Node):
class OperatorNode(Node):
def __init__(self, pos):
super().__init__(pos)
self.children = [None]
@@ -142,9 +13,3 @@ class Operator(Node):
@value.setter
def value(self, value):
self[0] = value
@classmethod
def withValue(cls, value, pos):
node = cls(pos)
node.value = value
return node

View File

@@ -1,44 +1,32 @@
from smnp.ast.node.imports import ImportParser
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.extend import ExtendNode
from smnp.ast.node.function import FunctionDefinitionNode
from smnp.ast.node.imports import ImportNode
from smnp.ast.node.model import Node, ParseResult
from smnp.ast.node.statement import StatementParser
from smnp.ast.node.statement import StatementNode
from smnp.ast.parser import Parser
from smnp.error.syntax import SyntaxException
class Program(Node):
def __init__(self):
super().__init__((-1, -1))
def parse(input):
root = Program()
while input.hasCurrent():
result = Parser.oneOf(
# Start Symbol
ImportParser,
StatementParser,
exception=RuntimeError("Nie znam tego wyrazenia")
)(input)
@classmethod
def _parse(cls, input):
def parseToken(input):
return Parser.oneOf(
FunctionDefinitionNode.parse,
ExtendNode.parse,
ExpressionNode.parse,
ImportNode.parse,
StatementNode.parse,
exception = SyntaxException(f"Invalid statement: {input.currentToEndOfLine()}", input.current().pos)
)(input)
if result.result:
root.append(result.node)
return ParseResult.OK(root)
ProgramParser = Parser(parse, name="program")
# @classmethod
# def _parse(cls, input):
# def parseToken(input):
# return Parser.oneOf(
# FunctionDefinitionNode.parse,
# ExtendNode.parse,
# ExpressionNode.parse,
# ImportNode.parse,
# StatementNode.parse,
# exception = SyntaxException(f"Invalid statement: {input.currentToEndOfLine()}", input.current().pos)
# )(input)
#
# root = Program()
# while input.hasCurrent():
# result = parseToken(input)
# if result.result:
# root.append(result.node)
# return ParseResult.OK(root)
root = Program()
while input.hasCurrent():
result = parseToken(input)
if result.result:
root.append(result.node)
return ParseResult.OK(root)

68
smnp/ast/node/relation.py Normal file
View File

@@ -0,0 +1,68 @@
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.none import NoneNode
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class RelationOperatorNode(ExpressionNode):
def __init__(self, pos):
super().__init__(pos)
self.children = [ NoneNode(), NoneNode(), NoneNode()]
@property
def left(self):
return self[0]
@left.setter
def left(self, value):
self[0] = value
@property
def operator(self):
return self[1]
@operator.setter
def operator(self, value):
self[1] = value
@property
def right(self):
return self[2]
@right.setter
def right(self, value):
self[2] = value
@classmethod
def relationParser(cls):
def createNode(left, operator, right):
node = RelationOperatorNode(right.pos)
node.left = left
node.operator = operator
node.right = right
return node
return Parser.leftAssociativeOperatorParser(
cls._relationLhs(),
TokenType.EQUAL,
cls._relationRhs(),
createNode=createNode
)
@classmethod
def _relationLhs(cls):
raise RuntimeError(f"_relationLhs() is not implemented in {cls.__name__} class")
@staticmethod
def _relationRhs():
from smnp.ast.node.bool import BoolLiteralNode
from smnp.ast.node.identifier import IdentifierNode
from smnp.ast.node.string import StringLiteralNode
return Parser.doAssert(Parser.oneOf(
BoolLiteralNode.accessParser(),
BoolLiteralNode.literalParser(),
IdentifierNode.parse,
StringLiteralNode.accessParser(),
StringLiteralNode.literalParser()
), "expression")

View File

@@ -1,32 +1,32 @@
# from smnp.ast.node.expression import ExpressionNode
# from smnp.ast.node.none import NoneNode
# from smnp.ast.node.statement import StatementNode
# from smnp.ast.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),
# Parser.doAssert(ExpressionNode.parse, "expression"),
# createNode=createNode
# )(input)
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.none import NoneNode
from smnp.ast.node.statement import StatementNode
from smnp.ast.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),
Parser.doAssert(ExpressionNode.parse, "expression"),
createNode=createNode
)(input)

View File

@@ -1,34 +1,17 @@
from smnp.ast.node.expression import MaxPrecedenceExpressionParser
from smnp.ast.node.model import Node
from smnp.ast.parser import Parser
class Statement(Node):
pass
class StatementNode(Node):
@classmethod
def _parse(cls, input):
from smnp.ast.node.block import BlockNode
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.ret import ReturnNode
def StatementParser(input):
from smnp.ast.node.block import BlockParser
from smnp.ast.node.condition import IfElseStatementParser
parser = Parser.oneOf(
IfElseStatementParser,
BlockParser,
MaxPrecedenceExpressionParser
)
return Parser(parser, "statement", parser)(input)
# class StatementNode(Node):
#
# @classmethod
# def _parse(cls, input):
# from smnp.ast.node.block import BlockNode
# from smnp.ast.node.expression import ExpressionNode
# from smnp.ast.node.ret import ReturnNode
#
# return Parser.oneOf(
# ExpressionNode.parse,
# BlockNode.parse,
# ReturnNode.parse,
# )(input)
return Parser.oneOf(
ExpressionNode.parse,
BlockNode.parse,
ReturnNode.parse,
)(input)

31
smnp/ast/node/string.py Normal file
View File

@@ -0,0 +1,31 @@
from smnp.ast.node.access import AccessNode
from smnp.ast.node.literal import LiteralNode
from smnp.ast.node.relation import RelationOperatorNode
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class StringLiteralNode(AccessNode, RelationOperatorNode, LiteralNode):
def __init__(self, pos):
super().__init__(pos)
del self.children[1]
@classmethod
def _parse(cls, input):
return Parser.oneOf(
cls.accessParser(),
cls.relationParser(),
cls.literalParser()
)(input)
@classmethod
def _accessLhs(cls):
return cls.literalParser()
@classmethod
def _relationLhs(cls):
return cls.literalParser()
@classmethod
def _getTokenType(cls):
return TokenType.STRING

View File

@@ -1,12 +0,0 @@
from smnp.ast.node.factor import FactorParser
from smnp.ast.node.operator import BinaryOperator
from smnp.ast.node.valuable import Valuable
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class Term(Valuable):
pass
TermParser = Parser.leftAssociativeOperatorParser(FactorParser, [TokenType.ASTERISK, TokenType.SLASH], FactorParser,
lambda left, op, right: Term.withValue(BinaryOperator.withValues(left, op, right)))

View File

@@ -1,63 +1,63 @@
# from smnp.ast.node.iterable import abstractIterableParser
# from smnp.ast.node.model import Node
# from smnp.ast.node.operator import LeftAssociativeOperatorNode
# from smnp.ast.parser import Parser
# from smnp.token.type import TokenType
# from smnp.type.model import Type
#
#
# class TypeSpecifier(Node):
#
# @classmethod
# def _parse(cls, input):
# return abstractIterableParser(TypeSpecifier, TokenType.OPEN_ANGLE, TokenType.CLOSE_ANGLE,
# Parser.doAssert(cls._specifierItem(), "type"))(input)
#
# @classmethod
# def _specifierItem(cls):
# return Parser.oneOf(
# TypeNode.parse,
# cls.parse
# )
#
# class TypeSpecifiers(Node):
# pass
#
#
# class TypeNode(LeftAssociativeOperatorNode):
# def __init__(self, pos):
# super().__init__(pos)
#
# @property
# def type(self):
# return self[0]
#
# @type.setter
# def type(self, value):
# self[0] = value
#
# @property
# def specifiers(self):
# return self[1]
#
# @specifiers.setter
# def specifiers(self, value):
# self[1] = value
#
# @classmethod
# def _parse(cls, input):
# def createNode(type, specifiers):
# node = TypeNode(type.pos)
# node.type = Type[type.value.upper()]
# node.specifiers = specifiers
# return node
#
# return Parser.allOf(
# cls._rawTypeParser(),
# Parser.many(TypeSpecifier.parse, lambda specifiers, pos: TypeSpecifiers.withChildren(specifiers, pos)),
# createNode=createNode
# )(input)
#
# @classmethod
# def _rawTypeParser(cls):
# return Parser.terminalParser(TokenType.TYPE, lambda val, pos: TypeNode.withValue(val, pos))
from smnp.ast.node.access import AccessNode
from smnp.ast.node.iterable import abstractIterableParser
from smnp.ast.node.model import Node
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
from smnp.type.model import Type
class TypeSpecifier(Node):
@classmethod
def _parse(cls, input):
return abstractIterableParser(TypeSpecifier, TokenType.OPEN_ANGLE, TokenType.CLOSE_ANGLE,
Parser.doAssert(cls._specifierItem(), "type"))(input)
@classmethod
def _specifierItem(cls):
return Parser.oneOf(
TypeNode.parse,
cls.parse
)
class TypeSpecifiers(Node):
pass
class TypeNode(AccessNode):
def __init__(self, pos):
super().__init__(pos)
@property
def type(self):
return self[0]
@type.setter
def type(self, value):
self[0] = value
@property
def specifiers(self):
return self[1]
@specifiers.setter
def specifiers(self, value):
self[1] = value
@classmethod
def _parse(cls, input):
def createNode(type, specifiers):
node = TypeNode(type.pos)
node.type = Type[type.value.upper()]
node.specifiers = specifiers
return node
return Parser.allOf(
cls._rawTypeParser(),
Parser.many(TypeSpecifier.parse, lambda specifiers, pos: TypeSpecifiers.withChildren(specifiers, pos)),
createNode=createNode
)(input)
@classmethod
def _rawTypeParser(cls):
return Parser.terminalParser(TokenType.TYPE, lambda val, pos: TypeNode.withValue(val, pos))

View File

@@ -1,22 +0,0 @@
from smnp.ast.node.model import Node
from smnp.ast.node.none import NoneNode
class Valuable(Node):
def __init__(self, pos):
super().__init__(pos)
self.children = [NoneNode()]
@property
def value(self):
return self[0]
@value.setter
def value(self, value):
self[0] = value
@classmethod
def withValue(cls, value):
node = cls(value.pos)
node.value = value
return node

View File

@@ -1,290 +1,176 @@
from smnp.ast.node.ignore import IgnoredNode
from smnp.ast.node.model import ParseResult, Node
from smnp.ast.node.none import NoneNode
from smnp.ast.node.operator import OperatorNode
from smnp.error.syntax import SyntaxException
def parse(input):
from smnp.ast.node.program import ProgramParser
return ProgramParser(input).node
from smnp.ast.node.program import Program
return Program.parse(input).node
class Parser(object):
def __init__(self, name):
self.name = name
class Parser:
# a -> A
@staticmethod
def terminalParser(expectedType, createNode=None, doAssert=False):
def provideNode(value, pos):
if createNode is None:
return IgnoredNode(pos)
return createNode(value, pos)
def parse(input):
if input.hasCurrent() and input.current().type == expectedType:
token = input.current()
input.ahead()
return ParseResult.OK(provideNode(token.value, token.pos))
elif doAssert:
found = f", found '{input.current().rawValue}'" if input.hasCurrent() else ""
raise SyntaxException(f"Expected '{expectedType.key}'{found}", input.currentPos())
def parse(self, input):
result = self._parse(input)
if result is None:
return ParseResult.FAIL()
if not isinstance(result, ParseResult):
raise RuntimeError(
f"_parse() method of '{self.__class__.__name__}' class haven't returned ParseResult object")
return result
def _parse(self, input):
raise RuntimeError(f"_name method of '{self.__class__.__name__}' class is not implemented")
def grammar(self):
rules = []
self._grammarRules(rules)
return "\n".join(self._uniq(rules))
def _uniq(self, seq):
seen = set()
seen_add = seen.add
return [x for x in seq if not (x in seen or seen_add(x))]
def _grammarRules(self, output):
output.append(f"class '{self.__class__.__name__}' does not implement _grammarRules() method")
def __call__(self, input):
return self.parse(input)
def __str__(self):
return self.name
def __repr__(self):
return self.__str__()
class Parsers:
return parse
# oneOf -> a | b | c | ...
@staticmethod
def terminal(expectedType, createNode=lambda val, pos: IgnoredNode(pos), doAssert=False):
return TerminalParser(expectedType, createNode, doAssert)
def oneOf(*parsers, exception=None):
def combinedParser(input):
snap = input.snapshot()
for parser in parsers:
value = parser(input)
if value.result:
return value
input.reset(snap)
if exception is not None:
if callable(exception):
raise exception(input)
else:
raise exception
input.reset(snap)
return ParseResult.FAIL()
return combinedParser
# allOf -> a b c ...
@staticmethod
def oneOf(*parsers, name, exception=None):
return OneOfParser(*parsers, name=name, exception=exception)
@staticmethod
def allOf(*parsers, createNode, exception=None, name):
return AllOfParser(*parsers, createNode=createNode, exception=exception, name=name)
@staticmethod
def leftAssociativeOperatorParser(leftParser, operatorTokenTypes, rightParser, createNode, name):
return LeftAssociativeOperatorParser(leftParser, operatorTokenTypes, rightParser, createNode, name)
@staticmethod
def many(itemParser, createNode, name):
return ManyParser(itemParser, createNode, name)
@staticmethod
def optional(parser, name):
return OptionalParser(parser, name)
@staticmethod
def loop(startParser, itemParser, endParser, createNode, name):
return LoopParser(startParser, itemParser, endParser, createNode, name)
class DecoratorParser(Parser):
def __init__(self, wrapper, parser):
super().__init__(parser.name)
self.wrapper = wrapper
self.parser = parser
self._grammarRules = parser._grammarRules
def _parse(self, input):
result = self.parser.parse(input)
return self.wrapper(result)
class TerminalParser(Parser):
def __init__(self, expectedType, createNode=lambda val, pos: IgnoredNode(pos), doAssert=False):
super().__init__(expectedType.name.lower())
self.expectedType = expectedType
self.createNode = createNode
self.doAssert = doAssert
def _grammarRules(self, output):
output.append(f"{self.name} -> '{self.expectedType.value}'")
def _parse(self, input):
if input.isCurrent(self.expectedType):
token = input.current()
input.ahead()
return ParseResult.OK(self.createNode(token.value, token.pos))
elif self.doAssert:
found = f", found '{input.current().rawValue}'" if input.hasCurrent() else ""
raise SyntaxException(f"Expected '{self.expectedType.key}'{found}", input.currentPos())
return ParseResult.FAIL()
class OneOfParser(Parser):
def __init__(self, *parsers, name, exception=None):
super().__init__(name)
self.parsers = parsers
self.exception = exception
def _parse(self, input):
snap = input.snapshot()
for parser in self.parsers:
value = parser.parse(input)
if value.result:
return value
input.reset(snap) # TODO sprawdzic, czy koneiczne !!!!!
if self.exception is not None:
if callable(self.exception):
raise self.exception(input)
else:
raise self.exception
return ParseResult.FAIL()
def _grammarRules(self, output):
output.extend([ f"{self.name} -> {parser.name}" for parser in self.parsers ])
[ parser._grammarRules(output) for parser in self.parsers ]
class AllOfParser(Parser):
def __init__(self, *parsers, createNode, exception=None, name):
super().__init__(name)
def allOf(*parsers, createNode, exception=None):
if len(parsers) == 0:
raise RuntimeError("Pass one parser at least")
self.parsers = parsers
self.createNode = createNode
self.exception = exception
def extendedParser(input):
snap = input.snapshot()
def _parse(self, input):
snap = input.snapshot()
parsedItems = []
results = []
for parser in self.parsers:
result = parser.parse(input)
for parser in parsers:
result = parser(input)
if not result.result:
if exception is not None:
if callable(exception):
raise exception(input)
else:
raise exception
input.reset(snap)
return ParseResult.FAIL()
results.append(result.node)
node = createNode(*results)
if not isinstance(node, Node):
raise RuntimeError("Function 'createNode' haven't returned a Node object. Probably forget to pass 'return'")
return ParseResult.OK(node)
return extendedParser
# leftAssociative -> left | left OP right
@staticmethod
def leftAssociativeOperatorParser(leftParser, operatorTokenType, rightParser, createNode):
def parse(input):
left = leftParser(input)
oneAtLeast = False
if left.result:
operator = Parser.terminalParser(operatorTokenType, lambda val, pos: OperatorNode.withChildren([val], pos))(input)
while operator.result:
oneAtLeast = True
right = rightParser(input)
left = ParseResult.OK(createNode(left.node, operator.node, right.node))
operator = Parser.terminalParser(operatorTokenType, lambda val, pos: OperatorNode.withChildren([val], pos))(input)
if oneAtLeast:
return left
return ParseResult.FAIL()
return parse
# loop -> start item* end
@staticmethod
def loop(startParser, itemParser, endParser, createNode):
def parse(input):
items = []
start = startParser(input)
if start.result:
while True:
end = endParser(input)
if end.result:
return ParseResult.OK(createNode(start.node, items, end.node))
item = itemParser(input)
if not item.result:
return ParseResult.FAIL()
items.append(item.node)
return ParseResult.FAIL()
return parse
@staticmethod
def doAssert(parser, expected):
def parse(input):
result = parser(input)
if not result.result:
if self.exception is not None:
if callable(self.exception):
raise self.exception(input)
else:
raise self.exception
found = f", found '{input.current().rawValue}'" if input.hasCurrent() else ''
input.reset(snap)
return ParseResult.FAIL()
raise SyntaxException(f"Expected {expected}{found}", input.currentPos())
parsedItems.append(result.node)
node = self.createNode(*parsedItems)
if not isinstance(node, Node):
raise RuntimeError(f"Method 'createNode' of class '{self.__class__.__name__}' haven't returned a Node object. Probably forget to pass 'return'")
return ParseResult.OK(node)
def _grammarRules(self, output):
output.append(self.name + ' -> ' + ' '.join([ parser.name for parser in self.parsers ]))
[ parser._grammarRules(output) for parser in self.parsers ]
class LeftAssociativeOperatorParser(Parser):
def __init__(self, leftParser, operatorTokenTypes, rightParser, createNode, name):
from smnp.ast.node.operator import Operator
super().__init__(name)
self.leftParser = leftParser
self.rightParser = rightParser
self.createNode = createNode
self.operators = operatorTokenTypes
operatorParsers = [ TerminalParser(expectedType, createNode=lambda val, pos: Operator.withValue(val, pos)) for expectedType in operatorTokenTypes ]
self.operatorParser = OneOfParser(*operatorParsers, name="not important")
def _parse(self, input):
snap = input.snapshot()
left = self.leftParser.parse(input)
if left.result:
operator = self.operatorParser.parse(input)
while operator.result:
right = self.rightParser.parse(input)
left = ParseResult.OK(self.createNode(left.node, operator.node, right.node))
operator = self.operatorParser.parse(input)
return left
return ParseResult.FAIL()
def _grammarRules(self, output):
output.append('\n'.join([f"{self.name} -> {self.leftParser.name} {operator.name.lower()} {self.rightParser.name} | {self.leftParser.name}" for operator in self.operators]))
self.leftParser._grammarRules(output)
self.rightParser._grammarRules(output)
class ManyParser(Parser):
def __init__(self, itemParser, createNode, name):
super().__init__(name)
self.itemParser = itemParser
self.createNode = createNode
def _parse(self, input):
snap = input.snapshot()
parsedItems = []
pos = input.currentPos()
while True:
result = self.itemParser.parse(input)
if result.result:
parsedItems.append(result.node)
snap = input.snapshot()
else:
input.reset(snap)
return ParseResult.OK(self.createNode(parsedItems, pos) if len(parsedItems) > 0 else NoneNode())
def _grammarRules(self, output):
output.append(f"{self.name} -> {self.itemParser.name}*")
self.itemParser._grammarRules(output)
class OptionalParser(Parser):
def __init__(self, parser, name):
super().__init__(name)
self.parser = parser
def _parse(self, input):
result = self.parser.parse(input)
if result.result:
return result
return ParseResult.OK(NoneNode())
return parse
def _grammarRules(self, output):
output.append(f"{self.name} -> {self.parser.name}?")
@staticmethod
def optional(parser):
def parse(input):
result = parser(input)
if result.result:
return result
return ParseResult.OK(NoneNode())
class LoopParser(Parser):
def __init__(self, startParser, itemParser, endParser, createNode, name):
super().__init__(name)
self.startParser = startParser
self.itemParser = itemParser
self.endParser = endParser
self.createNode = createNode
return parse
def _parse(self, input):
items = []
start = self.startParser.parse(input)
if start.result:
@staticmethod
def many(parser, createNode):
def parse(input):
results = []
snap = input.snapshot()
pos = input.currentPos()
while True:
end = self.endParser.parse(input)
if end.result:
return ParseResult.OK(self.createNode(start.node, items, end.node))
item = self.itemParser.parse(input)
if not item.result:
return ParseResult.FAIL()
items.append(item.node)
return ParseResult.FAIL()
def _grammarRules(self, output):
output.append(f"{self.name} -> {self.startParser.name} {self.itemParser.name}* {self.endParser.name}")
self.startParser._grammarRules(output)
self.itemParser._grammarRules(output)
self.endParser._grammarRules(output)
result = parser(input)
if result.result:
results.append(result.node)
snap = input.snapshot()
else:
input.reset(snap)
return ParseResult.OK(createNode(results, pos) if len(results) > 0 else NoneNode())
return parse

View File

@@ -1,66 +0,0 @@
from smnp.ast.node.model import Node
from smnp.ast.parser import Parser
from smnp.token.tokenizer import tokenize
from smnp.token.type import TokenType
class Atom(Node):
def __init__(self, value, pos):
super().__init__(pos)
self.children = [value]
@property
def value(self):
return self[0]
class Operation(Node):
def __init__(self, left, op, right, pos):
super().__init__(pos)
self.children = [left, op, right]
@property
def left(self):
return self[0]
@property
def operator(self):
return self[1]
@property
def right(self):
return self[2]
def atom():
return Parser.oneOfTerminals(TokenType.INTEGER, TokenType.NOTE, TokenType.STRING, createNode=lambda val, pos: Atom(val, pos))
def chain():
return Parser.leftAssociativeOperatorParser(atom(), [TokenType.DOT], atom(), lambda left, op, right: Operation(left, op, right, op.pos), name="chain")
def factor():
return Parser.leftAssociativeOperatorParser(chain(), [TokenType.DOUBLE_ASTERISK], chain(), lambda left, op, right: Operation(left, op, right, op.pos), name="factor")
def term():
return Parser.leftAssociativeOperatorParser(factor(), [TokenType.ASTERISK, TokenType.SLASH], factor(), lambda left, op, right: Operation(left, op, right, op.pos), name="term")
def expr():
return Parser.leftAssociativeOperatorParser(term(), [TokenType.PLUS, TokenType.MINUS], term(), lambda left, op, right: Operation(left, op, right, op.pos), name="expr")
#
def evaluate(node):
if type(node) == Atom:
return node.value
lhs = evaluate(node.left)
rhs = evaluate(node.right)
return {
"+": int(lhs) + int(rhs),
"*": int(lhs) * int(rhs),
"-": int(lhs) - int(rhs),
"/": int(lhs) / int(rhs),
"**": int(lhs) ** int(rhs)
}[node.operator.value]
def draft():
tokens = tokenize(['"fesf fe" + "fsefsef" + "fsefs"'])
e = expr()
node = e(tokens).node
node.print()

View File

@@ -1,32 +1,13 @@
from smnp.ast.node.atom import AtomParser
from smnp.ast.node.chain import ChainParser
from smnp.ast.node.list import ListParser
from smnp.ast.node.model import Node
import sys
from smnp.error.base import SmnpException
from smnp.token.tokenizer import tokenize
from smnp.program.interpreter import Interpreter
def main():
try:
# stdLibraryEnv = loadStandardLibrary()
# Interpreter.interpretFile(sys.argv[1], printTokens=True, printAst=True, execute=False, baseEnvironment=None)
# draft()
class TestNode(Node):
def __init__(self, children):
super().__init__((-1, -1))
self.children = children
tokens = tokenize(['[1, 2]'])
parser = ListParser()
#print(parser.grammar())
res = parser.parse(tokens)
print()
if res.result:
res.node.print()
else:
print("nie sparsowano")
#stdLibraryEnv = loadStandardLibrary()
Interpreter.interpretFile(sys.argv[1], printTokens=False, printAst=True, baseEnvironment=None)
except SmnpException as e:
print(e.message())

View File

@@ -1,25 +1,26 @@
from smnp.ast.parser import parse
#from smnp.environment.factory import createEnvironment
from smnp.environment.factory import createEnvironment
from smnp.error.runtime import RuntimeException
from smnp.program.FileReader import readLines
from smnp.runtime.evaluator import evaluate
from smnp.token.tokenizer import tokenize
class Interpreter:
@staticmethod
def interpretString(string, printTokens=False, printAst=False, execute=True, baseEnvironment=None):
return Interpreter._interpret(string.splitlines(), printTokens, printAst, execute, baseEnvironment)
def interpretString(string, printTokens=False, printAst=False, baseEnvironment=None):
return Interpreter._interpret(string.splitlines(), printTokens, printAst, baseEnvironment)
@staticmethod
def interpretFile(file, printTokens=False, printAst=False, execute=True, baseEnvironment=None):
return Interpreter._interpret(readLines(file), printTokens, printAst, execute, baseEnvironment)
def interpretFile(file, printTokens=False, printAst=False, baseEnvironment=None):
return Interpreter._interpret(readLines(file), printTokens, printAst, baseEnvironment)
@staticmethod
def _interpret(lines, printTokens=False, printAst=False, execute=True, baseEnvironment=None):
#environment = createEnvironment()
#if baseEnvironment is not None:
# environment.extend(baseEnvironment)
def _interpret(lines, printTokens=False, printAst=False, baseEnvironment=None):
environment = createEnvironment()
if baseEnvironment is not None:
environment.extend(baseEnvironment)
try:
tokens = tokenize(lines)
@@ -30,10 +31,9 @@ class Interpreter:
if printAst:
ast.print()
#if execute:
# evaluate(ast, environment)
evaluate(ast, environment)
#return environment
return environment
except RuntimeException as e:
#e.environment = environment
e.environment = environment
raise e

View File

@@ -1,9 +1,4 @@
from smnp.ast.node.block import BlockNode
from smnp.ast.node.extend import ExtendNode
from smnp.ast.node.function import FunctionDefinitionNode
from smnp.ast.node.imports import ImportNode
from smnp.ast.node.program import Program
from smnp.ast.node.ret import ReturnNode
from smnp.error.runtime import RuntimeException
from smnp.type.model import Type
@@ -70,18 +65,13 @@ def evaluate(node, environment):
from smnp.runtime.evaluators.program import ProgramEvaluator
from smnp.runtime.evaluators.expression import expressionEvaluator
from smnp.runtime.evaluators.function import FunctionDefinitionEvaluator
from smnp.runtime.evaluators.extend import ExtendEvaluator
from smnp.runtime.evaluators.block import BlockEvaluator
from smnp.runtime.evaluators.imports import ImportEvaluator
from smnp.runtime.evaluators.function import ReturnEvaluator
result = Evaluator.oneOf(
Evaluator.forNodes(ProgramEvaluator.evaluate, Program),
Evaluator.forNodes(ImportEvaluator.evaluate, ImportNode),
Evaluator.forNodes(FunctionDefinitionEvaluator.evaluate, FunctionDefinitionNode),
Evaluator.forNodes(ExtendEvaluator.evaluate, ExtendNode),
Evaluator.forNodes(BlockEvaluator.evaluate, BlockNode),
Evaluator.forNodes(ReturnEvaluator.evaluate, ReturnNode),
#Evaluator.forNodes(ImportEvaluator.evaluate, ImportNode),
#Evaluator.forNodes(FunctionDefinitionEvaluator.evaluate, FunctionDefinitionNode),
#Evaluator.forNodes(ExtendEvaluator.evaluate, ExtendNode),
#Evaluator.forNodes(BlockEvaluator.evaluate, BlockNode),
#Evaluator.forNodes(ReturnEvaluator.evaluate, ReturnNode),
expressionEvaluator()
)(node, environment)

View File

@@ -1,4 +1,4 @@
from smnp.ast.node.identifier import Identifier
from smnp.ast.node.identifier import IdentifierNode
from smnp.ast.node.invocation import FunctionCallNode
from smnp.error.runtime import RuntimeException
from smnp.runtime.evaluator import Evaluator
@@ -14,7 +14,7 @@ class AccessEvaluator(Evaluator):
left = expressionEvaluator(doAssert=True)(node.left, environment).value #TODO check if it isn't necessary to verify 'result' attr of EvaluatioNResult
right = node.right
if type(right) == Identifier:
if type(right) == IdentifierNode:
try:
return left.properties[right.value]
except KeyError:

View File

@@ -1,4 +1,4 @@
from smnp.ast.node.identifier import Identifier
from smnp.ast.node.identifier import IdentifierNode
from smnp.runtime.evaluator import evaluate, Evaluator, EvaluationResult
from smnp.runtime.evaluators.expression import expressionEvaluator
from smnp.type.model import Type
@@ -40,7 +40,7 @@ class AsteriskEvaluator(Evaluator):
@classmethod
def _automaticNamedVariable(cls, iteratorNode, environment, prefix=''):
if type(iteratorNode) == Identifier:
if type(iteratorNode) == IdentifierNode:
return cls._automaticVariableName(environment, prefix, iteratorNode.value, False)
else:
return cls._automaticVariableName(environment, prefix, '', True)

View File

@@ -1,13 +1,13 @@
from smnp.ast.node.access import AccessNode
from smnp.ast.node.assignment import AssignmentNode
from smnp.ast.node.asterisk import AsteriskNode
from smnp.ast.node.bool import BoolLiteralNode
from smnp.ast.node.identifier import Identifier
from smnp.ast.node.identifier import IdentifierNode
from smnp.ast.node.integer import IntegerLiteralNode
from smnp.ast.node.invocation import FunctionCallNode
from smnp.ast.node.list import List
from smnp.ast.node.list import ListNode
from smnp.ast.node.map import MapNode
from smnp.ast.node.note import NoteLiteralNode
from smnp.ast.node.operator import LeftAssociativeOperatorNode
from smnp.ast.node.string import StringLiteralNode
from smnp.ast.node.type import TypeNode
from smnp.error.runtime import RuntimeException
@@ -37,9 +37,9 @@ def expressionEvaluator(doAssert=False):
Evaluator.forNodes(NoteEvaluator.evaluate, NoteLiteralNode),
Evaluator.forNodes(BoolEvaluator.evaluate, BoolLiteralNode),
Evaluator.forNodes(TypeEvaluator.evaluate, TypeNode),
Evaluator.forNodes(IdentifierEvaluator.evaluate, Identifier),
Evaluator.forNodes(ListEvaluator.evaluate, List),
Evaluator.forNodes(AccessEvaluator.evaluate, LeftAssociativeOperatorNode),
Evaluator.forNodes(IdentifierEvaluator.evaluate, IdentifierNode),
Evaluator.forNodes(ListEvaluator.evaluate, ListNode),
Evaluator.forNodes(AccessEvaluator.evaluate, AccessNode),
Evaluator.forNodes(AssignmentEvaluator.evaluate, AssignmentNode),
Evaluator.forNodes(AsteriskEvaluator.evaluate, AsteriskNode),
Evaluator.forNodes(MapEvaluator.evaluate, MapNode)

View File

@@ -5,18 +5,13 @@ from smnp.token.tokenizers.comment import commentTokenizer
from smnp.token.tokenizers.identifier import identifierTokenizer
from smnp.token.tokenizers.keyword import typeTokenizer
from smnp.token.tokenizers.note import noteTokenizer
from smnp.token.tokenizers.relation import relationOperatorTokenizer
from smnp.token.tokenizers.string import stringTokenizer
from smnp.token.tokenizers.whitespace import whitespacesTokenizer
from smnp.token.tools import defaultTokenizer, separated, regexPatternTokenizer
from smnp.token.type import TokenType
tokenizers = (
defaultTokenizer(TokenType.ARROW),
# Double-character operators
relationOperatorTokenizer,
defaultTokenizer(TokenType.DOUBLE_ASTERISK),
defaultTokenizer(TokenType.EQUAL),
# Characters
defaultTokenizer(TokenType.OPEN_CURLY),
@@ -29,11 +24,9 @@ tokenizers = (
defaultTokenizer(TokenType.CLOSE_ANGLE),
defaultTokenizer(TokenType.ASTERISK),
defaultTokenizer(TokenType.ASSIGN),
defaultTokenizer(TokenType.ARROW),
defaultTokenizer(TokenType.COMMA),
defaultTokenizer(TokenType.SLASH),
defaultTokenizer(TokenType.MINUS),
defaultTokenizer(TokenType.PLUS),
defaultTokenizer(TokenType.DASH),
defaultTokenizer(TokenType.DOTS),
defaultTokenizer(TokenType.AMP),
defaultTokenizer(TokenType.DOT),
@@ -51,12 +44,7 @@ tokenizers = (
separated(defaultTokenizer(TokenType.EXTEND)),
separated(defaultTokenizer(TokenType.IMPORT)),
separated(defaultTokenizer(TokenType.FROM)),
separated(defaultTokenizer(TokenType.ELSE)),
separated(defaultTokenizer(TokenType.AND)),
separated(defaultTokenizer(TokenType.NOT)),
separated(defaultTokenizer(TokenType.AS)),
separated(defaultTokenizer(TokenType.IF)),
separated(defaultTokenizer(TokenType.OR)),
# Identifier (couldn't be before keywords!)
identifierTokenizer,

View File

@@ -1,6 +0,0 @@
from smnp.token.tools import keywordsTokenizer
from smnp.token.type import TokenType
def relationOperatorTokenizer(input, current, line):
return keywordsTokenizer(TokenType.RELATION, "==", "!=", ">=", "<=", ">", "<")(input, current, line)

View File

@@ -2,8 +2,7 @@ from enum import Enum
class TokenType(Enum):
RELATION = 'relation'
DOUBLE_ASTERISK = '**'
EQUAL = '=='
OPEN_CURLY = '{'
CLOSE_CURLY = '}'
OPEN_PAREN = '('
@@ -16,16 +15,10 @@ class TokenType(Enum):
ASSIGN = '='
ARROW = '->'
COMMA = ','
SLASH = '/'
MINUS = '-'
PLUS = '+'
DASH = '^'
DOTS = '...'
AMP = '&'
DOT = '.'
AND = 'and'
OR = 'or'
NOT = 'not'
INTEGER = 'integer'
STRING = 'string'
NOTE = 'note'
@@ -36,8 +29,6 @@ class TokenType(Enum):
EXTEND = 'extend'
IMPORT = 'import'
FROM = 'from'
ELSE = 'else'
IF = 'if'
AS = 'as'
IDENTIFIER = 'identifier'
COMMENT = 'comment'

View File

View File

@@ -1,14 +0,0 @@
from smnp.ast.parser import Parser
def SingletonParser(function):
def wrapper(*args, **kwargs):
if not hasattr(function, 'instance'):
function.instance = function(*args, **kwargs)
if not isinstance(function.instance, Parser):
raise RuntimeError(f"Function {function.__name__} haven't returned Parser object")
return function.instance
return wrapper