Compare commits
5 Commits
new-parser
...
add-bool
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a1bc422fba | ||
|
|
98d710ac97 | ||
|
|
d6fb101337 | ||
|
|
e008be7952 | ||
|
|
0a7d29d4a1 |
56
smnp/ast/node/access.py
Normal file
56
smnp/ast/node/access.py
Normal 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())
|
||||||
|
)
|
||||||
28
smnp/ast/node/assignment.py
Normal file
28
smnp/ast/node/assignment.py
Normal 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
28
smnp/ast/node/asterisk.py
Normal 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")
|
||||||
@@ -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"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,19 +1,20 @@
|
|||||||
from smnp.ast.node.model import Node
|
from smnp.ast.node.statement import StatementNode
|
||||||
from smnp.ast.node.statement import StatementParser
|
|
||||||
from smnp.ast.parser import Parser
|
from smnp.ast.parser import Parser
|
||||||
from smnp.token.type import TokenType
|
from smnp.token.type import TokenType
|
||||||
|
|
||||||
|
|
||||||
class Block(Node):
|
class BlockNode(StatementNode):
|
||||||
pass
|
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _parse(cls, input):
|
||||||
|
def createNode(start, items, end):
|
||||||
|
node = BlockNode(start.pos)
|
||||||
|
node.children = items
|
||||||
|
return node
|
||||||
|
|
||||||
def BlockParser(input):
|
return Parser.loop(
|
||||||
parser = Parser.loop(
|
Parser.terminalParser(TokenType.OPEN_CURLY),
|
||||||
Parser.terminalParser(TokenType.OPEN_CURLY),
|
Parser.doAssert(StatementNode.parse, f"statement or '{TokenType.CLOSE_CURLY.key}'"),
|
||||||
Parser.doAssert(StatementParser, f"statement or '{TokenType.CLOSE_CURLY.key}'"),
|
Parser.terminalParser(TokenType.CLOSE_CURLY),
|
||||||
Parser.terminalParser(TokenType.CLOSE_CURLY),
|
createNode=createNode,
|
||||||
createNode=lambda open, statements, close: Block.withChildren(statements, open.pos)
|
)(input)
|
||||||
)
|
|
||||||
|
|
||||||
return Parser(parser, "block", [parser])(input)
|
|
||||||
32
smnp/ast/node/bool.py
Normal file
32
smnp/ast/node/bool.py
Normal 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()
|
||||||
@@ -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"
|
|
||||||
)
|
|
||||||
|
|
||||||
@@ -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)
|
|
||||||
@@ -1,63 +1,66 @@
|
|||||||
from smnp.ast.node.operator import BinaryOperator
|
from smnp.ast.node.asterisk import AsteriskNode
|
||||||
from smnp.ast.node.term import TermParser
|
from smnp.ast.node.model import Node
|
||||||
from smnp.ast.node.valuable import Valuable
|
from smnp.ast.node.none import NoneNode
|
||||||
|
from smnp.ast.node.statement import StatementNode
|
||||||
from smnp.ast.parser import Parser
|
from smnp.ast.parser import Parser
|
||||||
from smnp.token.type import TokenType
|
from smnp.token.type import TokenType
|
||||||
|
|
||||||
|
|
||||||
class Expression(Valuable):
|
class ExpressionNode(Node):
|
||||||
pass
|
def __init__(self, pos):
|
||||||
|
super().__init__(pos, [NoneNode()])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def value(self):
|
||||||
|
return self[0]
|
||||||
|
|
||||||
|
|
||||||
def ExpressionParser(input):
|
@value.setter
|
||||||
return Parser.leftAssociativeOperatorParser(
|
def value(self, v):
|
||||||
TermParser,
|
self[0] = v
|
||||||
[TokenType.PLUS, TokenType.MINUS],
|
|
||||||
TermParser,
|
|
||||||
lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right))
|
|
||||||
)(input)
|
|
||||||
|
|
||||||
|
|
||||||
def Expression2Parser(input):
|
@classmethod
|
||||||
return Parser.leftAssociativeOperatorParser(
|
def withValue(cls, val, pos):
|
||||||
ExpressionParser,
|
node = cls(pos)
|
||||||
[TokenType.RELATION],
|
node.value = val
|
||||||
ExpressionParser,
|
return node
|
||||||
lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right))
|
|
||||||
)(input)
|
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _parse(cls, input):
|
||||||
|
return Parser.oneOf(
|
||||||
|
cls._asteriskParser(),
|
||||||
|
cls._expressionParser(),
|
||||||
|
)(input)
|
||||||
|
|
||||||
def Expression3Parser(input):
|
@classmethod
|
||||||
return Parser.leftAssociativeOperatorParser(
|
def _asteriskParser(cls):
|
||||||
Expression2Parser,
|
def createNode(iterator, asterisk, statement):
|
||||||
[TokenType.AND],
|
node = AsteriskNode(asterisk.pos)
|
||||||
Expression2Parser,
|
node.iterator = iterator
|
||||||
lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right))
|
node.statement = statement
|
||||||
)(input)
|
return node
|
||||||
|
|
||||||
|
return Parser.allOf(
|
||||||
|
cls._expressionParser(),
|
||||||
|
Parser.terminalParser(TokenType.ASTERISK),
|
||||||
|
Parser.doAssert(StatementNode.parse, 'statement'),
|
||||||
|
createNode=createNode
|
||||||
|
)
|
||||||
|
|
||||||
def Expression4Parser(input):
|
@classmethod
|
||||||
from smnp.ast.node.condition import IfElse
|
def _expressionParser(cls):
|
||||||
exprParser = Parser.leftAssociativeOperatorParser(
|
from smnp.ast.node.bool import BoolLiteralNode
|
||||||
Expression3Parser,
|
|
||||||
[TokenType.OR],
|
|
||||||
Expression3Parser,
|
|
||||||
lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right))
|
|
||||||
)
|
|
||||||
|
|
||||||
ifElseExpression = Parser.allOf(
|
from smnp.ast.node.identifier import IdentifierNode
|
||||||
exprParser,
|
from smnp.ast.node.string import StringLiteralNode
|
||||||
Parser.terminalParser(TokenType.IF),
|
return Parser.oneOf(
|
||||||
Expression4Parser,
|
#IntegerLiteralNode.parse,
|
||||||
Parser.terminalParser(TokenType.ELSE),
|
StringLiteralNode.parse,
|
||||||
Expression4Parser,
|
#NoteLiteralNode.parse,
|
||||||
createNode=lambda ifNode, _, condition, __, elseNode: IfElse.createNode(ifNode, condition, elseNode)
|
BoolLiteralNode.parse,
|
||||||
)
|
IdentifierNode.parse,
|
||||||
|
#MapNode.parse,
|
||||||
return Parser.oneOf(
|
#ListNode.parse,
|
||||||
ifElseExpression,
|
#TypeNode.parse,
|
||||||
exprParser,
|
)
|
||||||
)(input)
|
|
||||||
|
|
||||||
|
|
||||||
MaxPrecedenceExpressionParser = Expression4Parser
|
|
||||||
@@ -1,70 +1,70 @@
|
|||||||
# from smnp.ast.node.block import BlockNode
|
from smnp.ast.node.block import BlockNode
|
||||||
# from smnp.ast.node.function import FunctionDefinitionNode
|
from smnp.ast.node.function import FunctionDefinitionNode
|
||||||
# from smnp.ast.node.identifier import IdentifierNode
|
from smnp.ast.node.identifier import IdentifierNode
|
||||||
# from smnp.ast.node.none import NoneNode
|
from smnp.ast.node.none import NoneNode
|
||||||
# from smnp.ast.node.statement import StatementNode
|
from smnp.ast.node.statement import StatementNode
|
||||||
# from smnp.ast.node.type import TypeNode
|
from smnp.ast.node.type import TypeNode
|
||||||
# from smnp.ast.parser import Parser
|
from smnp.ast.parser import Parser
|
||||||
# from smnp.token.type import TokenType
|
from smnp.token.type import TokenType
|
||||||
#
|
|
||||||
#
|
|
||||||
# class ExtendNode(StatementNode):
|
class ExtendNode(StatementNode):
|
||||||
# def __init__(self, pos):
|
def __init__(self, pos):
|
||||||
# super().__init__(pos)
|
super().__init__(pos)
|
||||||
# self.children = [NoneNode(), NoneNode(), NoneNode()]
|
self.children = [NoneNode(), NoneNode(), NoneNode()]
|
||||||
#
|
|
||||||
# @property
|
@property
|
||||||
# def type(self):
|
def type(self):
|
||||||
# return self[0]
|
return self[0]
|
||||||
#
|
|
||||||
# @type.setter
|
@type.setter
|
||||||
# def type(self, value):
|
def type(self, value):
|
||||||
# self[0] = value
|
self[0] = value
|
||||||
#
|
|
||||||
# @property
|
@property
|
||||||
# def variable(self):
|
def variable(self):
|
||||||
# return self[1]
|
return self[1]
|
||||||
#
|
|
||||||
# @variable.setter
|
@variable.setter
|
||||||
# def variable(self, value):
|
def variable(self, value):
|
||||||
# self[1] = value
|
self[1] = value
|
||||||
#
|
|
||||||
# @property
|
@property
|
||||||
# def methods(self):
|
def methods(self):
|
||||||
# return self[2]
|
return self[2]
|
||||||
#
|
|
||||||
# @methods.setter
|
@methods.setter
|
||||||
# def methods(self, value):
|
def methods(self, value):
|
||||||
# self[2] = value
|
self[2] = value
|
||||||
#
|
|
||||||
# @classmethod
|
@classmethod
|
||||||
# def _parse(cls, input):
|
def _parse(cls, input):
|
||||||
# def createNode(extend, type, asKeyword, variable, methods):
|
def createNode(extend, type, asKeyword, variable, methods):
|
||||||
# node = ExtendNode(extend.pos)
|
node = ExtendNode(extend.pos)
|
||||||
# node.type = type
|
node.type = type
|
||||||
# node.variable = variable
|
node.variable = variable
|
||||||
# node.methods = methods
|
node.methods = methods
|
||||||
# return node
|
return node
|
||||||
#
|
|
||||||
# return Parser.allOf(
|
return Parser.allOf(
|
||||||
# Parser.terminalParser(TokenType.EXTEND),
|
Parser.terminalParser(TokenType.EXTEND),
|
||||||
# Parser.doAssert(TypeNode.parse, "type being extended"),
|
Parser.doAssert(TypeNode.parse, "type being extended"),
|
||||||
# Parser.terminalParser(TokenType.AS, doAssert=True),
|
Parser.terminalParser(TokenType.AS, doAssert=True),
|
||||||
# Parser.doAssert(IdentifierNode.identifierParser(), "variable name"),
|
Parser.doAssert(IdentifierNode.identifierParser(), "variable name"),
|
||||||
# Parser.doAssert(cls._methodsDeclarationsParser(), "methods declarations"),
|
Parser.doAssert(cls._methodsDeclarationsParser(), "methods declarations"),
|
||||||
# createNode=createNode
|
createNode=createNode
|
||||||
# )(input)
|
)(input)
|
||||||
#
|
|
||||||
# @classmethod
|
@classmethod
|
||||||
# def _methodsDeclarationsParser(cls):
|
def _methodsDeclarationsParser(cls):
|
||||||
# def createNode(openBracket, items, closeBracket):
|
def createNode(openBracket, items, closeBracket):
|
||||||
# node = BlockNode(openBracket.pos)
|
node = BlockNode(openBracket.pos)
|
||||||
# node.children = items
|
node.children = items
|
||||||
# return node
|
return node
|
||||||
#
|
|
||||||
# return Parser.loop(
|
return Parser.loop(
|
||||||
# Parser.terminalParser(TokenType.OPEN_CURLY),
|
Parser.terminalParser(TokenType.OPEN_CURLY),
|
||||||
# Parser.doAssert(FunctionDefinitionNode.parse, f"method declaration or '{TokenType.CLOSE_CURLY.key}'"),
|
Parser.doAssert(FunctionDefinitionNode.parse, f"method declaration or '{TokenType.CLOSE_CURLY.key}'"),
|
||||||
# Parser.terminalParser(TokenType.CLOSE_CURLY),
|
Parser.terminalParser(TokenType.CLOSE_CURLY),
|
||||||
# createNode=createNode
|
createNode=createNode
|
||||||
# )
|
)
|
||||||
@@ -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)
|
|
||||||
@@ -1,128 +1,128 @@
|
|||||||
# from smnp.ast.node.block import BlockNode
|
from smnp.ast.node.block import BlockNode
|
||||||
# from smnp.ast.node.expression import ExpressionNode
|
from smnp.ast.node.expression import ExpressionNode
|
||||||
# from smnp.ast.node.identifier import IdentifierNode
|
from smnp.ast.node.identifier import IdentifierNode
|
||||||
# from smnp.ast.node.iterable import abstractIterableParser
|
from smnp.ast.node.iterable import abstractIterableParser
|
||||||
# from smnp.ast.node.model import Node
|
from smnp.ast.node.model import Node
|
||||||
# from smnp.ast.node.none import NoneNode
|
from smnp.ast.node.none import NoneNode
|
||||||
# from smnp.ast.node.statement import StatementNode
|
from smnp.ast.node.statement import StatementNode
|
||||||
# from smnp.ast.node.type import TypeNode, TypeSpecifier
|
from smnp.ast.node.type import TypeNode, TypeSpecifier
|
||||||
# from smnp.ast.parser import Parser
|
from smnp.ast.parser import Parser
|
||||||
# from smnp.token.type import TokenType
|
from smnp.token.type import TokenType
|
||||||
#
|
|
||||||
#
|
|
||||||
# class ArgumentsDeclarationNode(Node):
|
class ArgumentsDeclarationNode(Node):
|
||||||
#
|
|
||||||
# @classmethod
|
@classmethod
|
||||||
# def _parse(cls, input):
|
def _parse(cls, input):
|
||||||
# raise RuntimeError("This class is not supposed to be automatically called")
|
raise RuntimeError("This class is not supposed to be automatically called")
|
||||||
#
|
|
||||||
#
|
|
||||||
# class VarargNode(Node):
|
class VarargNode(Node):
|
||||||
# pass
|
pass
|
||||||
#
|
|
||||||
#
|
|
||||||
# class ArgumentDefinitionNode(ExpressionNode):
|
class ArgumentDefinitionNode(ExpressionNode):
|
||||||
# def __init__(self, pos):
|
def __init__(self, pos):
|
||||||
# super().__init__(pos)
|
super().__init__(pos)
|
||||||
# self.children.extend([NoneNode(), False])
|
self.children.extend([NoneNode(), False])
|
||||||
#
|
|
||||||
# @property
|
@property
|
||||||
# def type(self):
|
def type(self):
|
||||||
# return self[0]
|
return self[0]
|
||||||
#
|
|
||||||
# @type.setter
|
@type.setter
|
||||||
# def type(self, value):
|
def type(self, value):
|
||||||
# self[0] = value
|
self[0] = value
|
||||||
#
|
|
||||||
# @property
|
@property
|
||||||
# def variable(self):
|
def variable(self):
|
||||||
# return self[1]
|
return self[1]
|
||||||
#
|
|
||||||
# @variable.setter
|
@variable.setter
|
||||||
# def variable(self, value):
|
def variable(self, value):
|
||||||
# self[1] = value
|
self[1] = value
|
||||||
#
|
|
||||||
# @property
|
@property
|
||||||
# def vararg(self):
|
def vararg(self):
|
||||||
# return self[2]
|
return self[2]
|
||||||
#
|
|
||||||
# @vararg.setter
|
@vararg.setter
|
||||||
# def vararg(self, value):
|
def vararg(self, value):
|
||||||
# self[2] = value
|
self[2] = value
|
||||||
#
|
|
||||||
#
|
|
||||||
# @classmethod
|
@classmethod
|
||||||
# def parser(cls):
|
def parser(cls):
|
||||||
# def createNode(type, variable, dots):
|
def createNode(type, variable, dots):
|
||||||
# node = ArgumentDefinitionNode(type.pos)
|
node = ArgumentDefinitionNode(type.pos)
|
||||||
# node.type = type
|
node.type = type
|
||||||
# node.variable = variable
|
node.variable = variable
|
||||||
# node.vararg = isinstance(dots, VarargNode)
|
node.vararg = isinstance(dots, VarargNode)
|
||||||
# return node
|
return node
|
||||||
#
|
|
||||||
# return Parser.allOf(
|
return Parser.allOf(
|
||||||
# Parser.optional(Parser.oneOf(
|
Parser.optional(Parser.oneOf(
|
||||||
# TypeNode.parse,
|
TypeNode.parse,
|
||||||
# TypeSpecifier.parse
|
TypeSpecifier.parse
|
||||||
# )),
|
)),
|
||||||
# Parser.doAssert(IdentifierNode.identifierParser(), "variable name"),
|
Parser.doAssert(IdentifierNode.identifierParser(), "variable name"),
|
||||||
# Parser.optional(Parser.terminalParser(TokenType.DOTS, lambda val, pos: VarargNode(pos))),
|
Parser.optional(Parser.terminalParser(TokenType.DOTS, lambda val, pos: VarargNode(pos))),
|
||||||
# createNode=createNode
|
createNode=createNode
|
||||||
# )
|
)
|
||||||
#
|
|
||||||
# @classmethod
|
@classmethod
|
||||||
# def _parse(cls, input):
|
def _parse(cls, input):
|
||||||
# #TODO
|
#TODO
|
||||||
# raise RuntimeError("Not implemented yet. There is still required work to correctly build AST related to IdentifierNode")
|
raise RuntimeError("Not implemented yet. There is still required work to correctly build AST related to IdentifierNode")
|
||||||
#
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# class FunctionDefinitionNode(StatementNode):
|
class FunctionDefinitionNode(StatementNode):
|
||||||
# def __init__(self, pos):
|
def __init__(self, pos):
|
||||||
# super().__init__(pos)
|
super().__init__(pos)
|
||||||
# self.children = [NoneNode(), NoneNode(), NoneNode()]
|
self.children = [NoneNode(), NoneNode(), NoneNode()]
|
||||||
#
|
|
||||||
# @property
|
@property
|
||||||
# def name(self):
|
def name(self):
|
||||||
# return self[0]
|
return self[0]
|
||||||
#
|
|
||||||
# @name.setter
|
@name.setter
|
||||||
# def name(self, value):
|
def name(self, value):
|
||||||
# self[0] = value
|
self[0] = value
|
||||||
#
|
|
||||||
# @property
|
@property
|
||||||
# def arguments(self):
|
def arguments(self):
|
||||||
# return self[1]
|
return self[1]
|
||||||
#
|
|
||||||
# @arguments.setter
|
@arguments.setter
|
||||||
# def arguments(self, value):
|
def arguments(self, value):
|
||||||
# self[1] = value
|
self[1] = value
|
||||||
#
|
|
||||||
# @property
|
@property
|
||||||
# def body(self):
|
def body(self):
|
||||||
# return self[2]
|
return self[2]
|
||||||
#
|
|
||||||
# @body.setter
|
@body.setter
|
||||||
# def body(self, value):
|
def body(self, value):
|
||||||
# self[2] = value
|
self[2] = value
|
||||||
#
|
|
||||||
# @classmethod
|
@classmethod
|
||||||
# def _parse(cls, input):
|
def _parse(cls, input):
|
||||||
# def createNode(function, name, arguments, body):
|
def createNode(function, name, arguments, body):
|
||||||
# node = FunctionDefinitionNode(function.pos)
|
node = FunctionDefinitionNode(function.pos)
|
||||||
# node.name = name
|
node.name = name
|
||||||
# node.arguments = arguments
|
node.arguments = arguments
|
||||||
# node.body = body
|
node.body = body
|
||||||
# return node
|
return node
|
||||||
#
|
|
||||||
# return Parser.allOf(
|
return Parser.allOf(
|
||||||
# Parser.terminalParser(TokenType.FUNCTION),
|
Parser.terminalParser(TokenType.FUNCTION),
|
||||||
# Parser.doAssert(IdentifierNode.identifierParser(), "function name"),
|
Parser.doAssert(IdentifierNode.identifierParser(), "function name"),
|
||||||
# Parser.doAssert(cls._argumentsDeclarationParser(), "arguments list"),
|
Parser.doAssert(cls._argumentsDeclarationParser(), "arguments list"),
|
||||||
# Parser.doAssert(BlockNode.parse, "function body"),
|
Parser.doAssert(BlockNode.parse, "function body"),
|
||||||
# createNode=createNode
|
createNode=createNode
|
||||||
# )(input)
|
)(input)
|
||||||
#
|
|
||||||
# @staticmethod
|
@staticmethod
|
||||||
# def _argumentsDeclarationParser():
|
def _argumentsDeclarationParser():
|
||||||
# return abstractIterableParser(ArgumentsDeclarationNode, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN, ArgumentDefinitionNode.parser())
|
return abstractIterableParser(ArgumentsDeclarationNode, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN, ArgumentDefinitionNode.parser())
|
||||||
@@ -1,75 +1,73 @@
|
|||||||
from smnp.ast.node.atom import Atom
|
from smnp.ast.node.access import AccessNode
|
||||||
from smnp.ast.node.model import Node
|
from smnp.ast.node.assignment import AssignmentNode
|
||||||
from smnp.ast.node.none import NoneNode
|
from smnp.ast.node.expression import ExpressionNode
|
||||||
from smnp.ast.node.operator import BinaryOperator, Operator
|
from smnp.ast.node.invocation import FunctionCallNode, ArgumentsListNode
|
||||||
from smnp.ast.parser import Parsers
|
from smnp.ast.node.relation import RelationOperatorNode
|
||||||
|
from smnp.ast.parser import Parser
|
||||||
from smnp.token.type import TokenType
|
from smnp.token.type import TokenType
|
||||||
from smnp.util.singleton import SingletonParser
|
|
||||||
|
|
||||||
|
|
||||||
class Identifier(Atom):
|
class IdentifierNode(AccessNode, RelationOperatorNode):
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class FunctionCall(Node):
|
|
||||||
def __init__(self, pos):
|
def __init__(self, pos):
|
||||||
super().__init__(pos)
|
super().__init__(pos)
|
||||||
self.children = [NoneNode(), NoneNode()]
|
del self.children[1]
|
||||||
|
|
||||||
@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
|
@classmethod
|
||||||
def withChildren(cls, name, arguments):
|
def _parse(cls, input):
|
||||||
node = cls(name.pos)
|
return Parser.oneOf(
|
||||||
node.name = name
|
cls.relationParser(),
|
||||||
node.arguments = arguments
|
cls.accessParser(),
|
||||||
return node
|
cls.literalParser()
|
||||||
|
)(input)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _accessLhs(cls):
|
||||||
|
return cls.literalParser()
|
||||||
|
|
||||||
class ArgumentsList(Node):
|
@classmethod
|
||||||
pass
|
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):
|
@staticmethod
|
||||||
pass
|
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
|
@staticmethod
|
||||||
def IdentifierParser():
|
def functionCallParser():
|
||||||
identifierLiteralParser = Parsers.terminal(TokenType.IDENTIFIER, createNode=Identifier.withValue)
|
def createNode(name, arguments):
|
||||||
|
node = FunctionCallNode(name.pos)
|
||||||
|
node.name = name
|
||||||
|
node.arguments = arguments
|
||||||
|
return node
|
||||||
|
|
||||||
functionCallParser = Parsers.allOf(
|
return Parser.allOf(
|
||||||
identifierLiteralParser,
|
IdentifierNode.identifierParser(),
|
||||||
#abstractIterableParser(ArgumentsList, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN, MaxPrecedenceExpressionParser),
|
ArgumentsListNode.parse,
|
||||||
createNode=lambda name, arguments: FunctionCall.withChildren(name, arguments),
|
createNode=createNode
|
||||||
name="functionCall"
|
)
|
||||||
)
|
|
||||||
|
|
||||||
assignmentParser = Parsers.allOf(
|
@staticmethod
|
||||||
identifierLiteralParser,
|
def identifierParser():
|
||||||
Parsers.terminal(TokenType.ASSIGN, createNode=Operator.withValue),
|
return Parser.terminalParser(TokenType.IDENTIFIER, lambda val, pos: IdentifierNode.withValue(val, pos))
|
||||||
#MaxPrecedenceExpressionParser,
|
|
||||||
createNode=lambda identifier, assign, expr: Assignment.withValues(identifier, assign, expr),
|
|
||||||
name="assignment"
|
|
||||||
)
|
|
||||||
|
|
||||||
return Parsers.oneOf(
|
|
||||||
assignmentParser,
|
|
||||||
functionCallParser,
|
|
||||||
identifierLiteralParser,
|
|
||||||
name="idExpr"
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -1,21 +1,16 @@
|
|||||||
# from smnp.ast.node.identifier import Identifier
|
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
|
|
||||||
#
|
|
||||||
from smnp.ast.node.atom import StringParser
|
|
||||||
from smnp.ast.node.model import Node
|
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.ast.parser import Parser
|
||||||
from smnp.token.type import TokenType
|
from smnp.token.type import TokenType
|
||||||
|
|
||||||
|
|
||||||
class Import(Node):
|
class ImportNode(Node):
|
||||||
def __init__(self, pos):
|
def __init__(self, pos):
|
||||||
super().__init__(pos)
|
super().__init__(pos)
|
||||||
self.children = [None]
|
self.children = [NoneNode(), NoneNode(), NoneNode()]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def source(self):
|
def source(self):
|
||||||
@@ -25,17 +20,57 @@ class Import(Node):
|
|||||||
def source(self, value):
|
def source(self, value):
|
||||||
self[0] = 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
|
@classmethod
|
||||||
def withValue(cls, value):
|
def _parse(cls, input):
|
||||||
node = cls(value.pos)
|
return Parser.oneOf(
|
||||||
node.source = value
|
cls._literalImportParser(),
|
||||||
return node
|
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(
|
||||||
return Parser.allOf(
|
Parser.terminalParser(TokenType.IMPORT),
|
||||||
Parser.terminalParser(TokenType.IMPORT),
|
TypeNode.parse,
|
||||||
StringParser,
|
Parser.doAssert(Parser.terminalParser(TokenType.FROM), "'from <source> as <variable name>'"),
|
||||||
createNode=lambda imp, source: Import.withValue(source),
|
Parser.doAssert(StringLiteralNode.literalParser(), "source as a string"),
|
||||||
name="import"
|
Parser.doAssert(Parser.terminalParser(TokenType.AS), "'as <variable name>'"),
|
||||||
)(input)
|
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
37
smnp/ast/node/integer.py
Normal 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))
|
||||||
40
smnp/ast/node/invocation.py
Normal file
40
smnp/ast/node/invocation.py
Normal 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")
|
||||||
|
|
||||||
@@ -1,24 +1,17 @@
|
|||||||
|
from smnp.ast.node.expression import ExpressionNode
|
||||||
from smnp.ast.node.ignore import IgnoredNode
|
from smnp.ast.node.ignore import IgnoredNode
|
||||||
from smnp.ast.node.model import Node, ParseResult
|
from smnp.ast.node.model import Node, ParseResult
|
||||||
from smnp.ast.node.none import NoneNode
|
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
|
from smnp.token.type import TokenType
|
||||||
|
|
||||||
|
|
||||||
def abstractIterableParser(iterableNodeType, openTokenType, closeTokenType, itemParser, name):
|
def abstractIterableParser(iterableNodeType, openTokenType, closeTokenType, itemParser):
|
||||||
|
class AbstractIterableTailNode(ExpressionNode):
|
||||||
class AbstractIterable(Node):
|
|
||||||
def __init__(self, pos):
|
def __init__(self, pos):
|
||||||
super().__init__(pos)
|
super().__init__(pos)
|
||||||
self.children = [NoneNode(), NoneNode()]
|
|
||||||
|
|
||||||
@property
|
self.children.append(NoneNode())
|
||||||
def value(self):
|
|
||||||
return self[0]
|
|
||||||
|
|
||||||
@value.setter
|
|
||||||
def value(self, value):
|
|
||||||
self[0] = value
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def next(self):
|
def next(self):
|
||||||
@@ -28,77 +21,89 @@ def abstractIterableParser(iterableNodeType, openTokenType, closeTokenType, item
|
|||||||
def next(self, value):
|
def next(self, value):
|
||||||
self[1] = value
|
self[1] = value
|
||||||
|
|
||||||
class AbstractIterableTail(AbstractIterable):
|
@classmethod
|
||||||
pass
|
def _parse(cls, input):
|
||||||
|
return Parser.oneOf(
|
||||||
|
AbstractIterableTailNode._parser1(),
|
||||||
|
AbstractIterableTailNode._parser2(),
|
||||||
|
)(input)
|
||||||
|
|
||||||
def abstractIterableParser():
|
@staticmethod
|
||||||
return Parsers.oneOf(
|
def _parser1():
|
||||||
emptyIterable(),
|
return Parser.terminalParser(closeTokenType)
|
||||||
openIterable(),
|
|
||||||
name=name
|
|
||||||
)
|
|
||||||
|
|
||||||
def emptyIterable():
|
@staticmethod
|
||||||
def createNode(open, close):
|
def _parser2():
|
||||||
node = AbstractIterable(open.pos)
|
def createNode(comma, expr, iterableTail):
|
||||||
node.value = open
|
node = AbstractIterableTailNode(expr.pos)
|
||||||
node.next = close
|
node.value = expr
|
||||||
return node
|
node.next = iterableTail
|
||||||
|
return node
|
||||||
|
|
||||||
return Parsers.allOf(
|
return Parser.allOf(
|
||||||
Parsers.terminal(openTokenType),
|
Parser.terminalParser(TokenType.COMMA, doAssert=True),
|
||||||
Parsers.terminal(closeTokenType),
|
itemParser,
|
||||||
createNode=createNode,
|
AbstractIterableTailNode.parse,
|
||||||
name=name+"Empty"
|
createNode=createNode
|
||||||
)
|
)
|
||||||
|
|
||||||
def openIterable():
|
class AbstractIterableNode(ExpressionNode):
|
||||||
def createNode(open, item, tail):
|
def __init__(self, pos):
|
||||||
node = AbstractIterable(open.pos)
|
super().__init__(pos)
|
||||||
node.value = item
|
|
||||||
node.next = tail
|
|
||||||
return node
|
|
||||||
|
|
||||||
return Parsers.allOf(
|
self.children.append(NoneNode())
|
||||||
Parsers.terminal(openTokenType),
|
|
||||||
itemParser,
|
|
||||||
abstractIterableTailParser(),
|
|
||||||
createNode=createNode,
|
|
||||||
name=name+"Open"
|
|
||||||
)
|
|
||||||
|
|
||||||
def abstractIterableTailParser():
|
@property
|
||||||
return Parsers.oneOf(
|
def next(self):
|
||||||
closeIterable(),
|
return self[1]
|
||||||
nextItem(),
|
|
||||||
name=name+"Tail"
|
|
||||||
)
|
|
||||||
|
|
||||||
def nextItem():
|
@next.setter
|
||||||
def createNode(comma, item, tail):
|
def next(self, value):
|
||||||
node = AbstractIterableTail(item.pos)
|
self[1] = value
|
||||||
node.value = item
|
|
||||||
node.next = tail
|
|
||||||
return node
|
|
||||||
|
|
||||||
return Parsers.allOf(
|
@classmethod
|
||||||
Parsers.terminal(TokenType.COMMA, doAssert=True),
|
def _parse(cls, input):
|
||||||
itemParser,
|
return Parser.oneOf(
|
||||||
abstractIterableTailParser(),
|
AbstractIterableNode._parser1(),
|
||||||
name=name+"NextItem",
|
AbstractIterableNode._parser2()
|
||||||
createNode=createNode
|
)(input)
|
||||||
)
|
|
||||||
|
|
||||||
def closeIterable():
|
@staticmethod
|
||||||
return Parsers.terminal(closeTokenType)
|
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()
|
@staticmethod
|
||||||
#return toFlatDesiredNode(iterableNodeType, abstractIterableParser())
|
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 toFlatDesiredNode(iterableNodeType, parser):
|
||||||
def wrapper(result):
|
def parse(input):
|
||||||
|
result = parser(input)
|
||||||
|
|
||||||
if result.result:
|
if result.result:
|
||||||
value = flattenList(result.node)
|
value = flattenList(result.node)
|
||||||
node = iterableNodeType(result.node.pos)
|
node = iterableNodeType(result.node.pos)
|
||||||
@@ -109,7 +114,7 @@ def toFlatDesiredNode(iterableNodeType, parser):
|
|||||||
|
|
||||||
return ParseResult.FAIL()
|
return ParseResult.FAIL()
|
||||||
|
|
||||||
return DecoratorParser(wrapper, parser)
|
return parse
|
||||||
|
|
||||||
|
|
||||||
def flattenList(node, output=None):
|
def flattenList(node, output=None):
|
||||||
|
|||||||
@@ -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.iterable import abstractIterableParser
|
||||||
from smnp.ast.node.model import Node
|
from smnp.ast.parser import Parser
|
||||||
from smnp.token.type import TokenType
|
from smnp.token.type import TokenType
|
||||||
|
|
||||||
|
|
||||||
class List(Node):
|
class ListNode(ExpressionNode):
|
||||||
pass
|
|
||||||
|
|
||||||
|
# TODO: To Remove
|
||||||
|
@classmethod
|
||||||
|
def _parse(cls, input):
|
||||||
|
return cls._literalParser()(input)
|
||||||
|
|
||||||
def ListParser():
|
@classmethod
|
||||||
return abstractIterableParser(List, TokenType.OPEN_SQUARE, TokenType.CLOSE_SQUARE, AtomParser(), name="list")
|
def _literalParser(cls):
|
||||||
#MaxPrecedenceExpressionParser)(input)
|
return abstractIterableParser(ListNode, TokenType.OPEN_SQUARE, TokenType.CLOSE_SQUARE,
|
||||||
|
Parser.doAssert(ExpressionNode.parse, "expression"))
|
||||||
|
|||||||
18
smnp/ast/node/literal.py
Normal file
18
smnp/ast/node/literal.py
Normal 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)
|
||||||
@@ -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.iterable import abstractIterableParser
|
||||||
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.node.note import NoteLiteralNode
|
||||||
from smnp.ast.parser import Parsers
|
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.token.type import TokenType
|
||||||
|
|
||||||
|
class MapEntry(ExpressionNode):
|
||||||
class MapEntry(BinaryOperator):
|
def __init__(self, pos):
|
||||||
|
super().__init__(pos)
|
||||||
|
self.children = [NoneNode(), NoneNode()]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def key(self):
|
def key(self):
|
||||||
@@ -17,31 +25,39 @@ class MapEntry(BinaryOperator):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def value(self):
|
def value(self):
|
||||||
return self[2]
|
return self[1]
|
||||||
|
|
||||||
@value.setter
|
@value.setter
|
||||||
def value(self, value):
|
def value(self, value):
|
||||||
self[2] = value
|
self[1] = value
|
||||||
|
|
||||||
|
class MapNode(AccessNode):
|
||||||
|
|
||||||
class Map(Node):
|
@classmethod
|
||||||
pass
|
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):
|
return Parser.allOf(
|
||||||
from smnp.ast.node.atom import LiteralParser
|
cls._keyParser(),
|
||||||
#from smnp.ast.node.expression import MaxPrecedenceExpressionParser
|
Parser.terminalParser(TokenType.ARROW),
|
||||||
keyParser = LiteralParser
|
ExpressionNode.parse,
|
||||||
#valueParser = MaxPrecedenceExpressionParser
|
createNode=createNode
|
||||||
|
)
|
||||||
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)
|
|
||||||
|
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _keyParser(cls):
|
||||||
|
return Parser.oneOf(
|
||||||
|
IntegerLiteralNode._literalParser(),
|
||||||
|
StringLiteralNode._literalParser(),
|
||||||
|
NoteLiteralNode._literalParser(),
|
||||||
|
BoolLiteralNode._literalParser(),
|
||||||
|
TypeNode.parse
|
||||||
|
)
|
||||||
@@ -47,7 +47,7 @@ class Node:
|
|||||||
self._print(first=True)
|
self._print(first=True)
|
||||||
|
|
||||||
def _print(self, prefix="", last=True, first=False):
|
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 '│ '
|
prefix += ' ' if last else '│ '
|
||||||
for i, child in enumerate(self.children):
|
for i, child in enumerate(self.children):
|
||||||
last = i == len(self.children) - 1
|
last = i == len(self.children) - 1
|
||||||
|
|||||||
18
smnp/ast/node/note.py
Normal file
18
smnp/ast/node/note.py
Normal 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
|
||||||
@@ -1,136 +1,7 @@
|
|||||||
from smnp.ast.node.model import Node
|
from smnp.ast.node.model import Node
|
||||||
from smnp.ast.node.none import NoneNode
|
|
||||||
|
|
||||||
|
|
||||||
class UnaryOperator(Node):
|
class OperatorNode(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):
|
|
||||||
def __init__(self, pos):
|
def __init__(self, pos):
|
||||||
super().__init__(pos)
|
super().__init__(pos)
|
||||||
self.children = [None]
|
self.children = [None]
|
||||||
@@ -142,9 +13,3 @@ class Operator(Node):
|
|||||||
@value.setter
|
@value.setter
|
||||||
def value(self, value):
|
def value(self, value):
|
||||||
self[0] = value
|
self[0] = value
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def withValue(cls, value, pos):
|
|
||||||
node = cls(pos)
|
|
||||||
node.value = value
|
|
||||||
return node
|
|
||||||
@@ -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.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.ast.parser import Parser
|
||||||
|
from smnp.error.syntax import SyntaxException
|
||||||
|
|
||||||
|
|
||||||
class Program(Node):
|
class Program(Node):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__((-1, -1))
|
super().__init__((-1, -1))
|
||||||
|
|
||||||
def parse(input):
|
@classmethod
|
||||||
root = Program()
|
def _parse(cls, input):
|
||||||
while input.hasCurrent():
|
def parseToken(input):
|
||||||
result = Parser.oneOf(
|
return Parser.oneOf(
|
||||||
# Start Symbol
|
FunctionDefinitionNode.parse,
|
||||||
ImportParser,
|
ExtendNode.parse,
|
||||||
StatementParser,
|
ExpressionNode.parse,
|
||||||
exception=RuntimeError("Nie znam tego wyrazenia")
|
ImportNode.parse,
|
||||||
)(input)
|
StatementNode.parse,
|
||||||
|
exception = SyntaxException(f"Invalid statement: {input.currentToEndOfLine()}", input.current().pos)
|
||||||
|
)(input)
|
||||||
|
|
||||||
if result.result:
|
root = Program()
|
||||||
root.append(result.node)
|
while input.hasCurrent():
|
||||||
|
result = parseToken(input)
|
||||||
return ParseResult.OK(root)
|
if result.result:
|
||||||
|
root.append(result.node)
|
||||||
ProgramParser = Parser(parse, name="program")
|
return ParseResult.OK(root)
|
||||||
# @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)
|
|
||||||
68
smnp/ast/node/relation.py
Normal file
68
smnp/ast/node/relation.py
Normal 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")
|
||||||
@@ -1,32 +1,32 @@
|
|||||||
# from smnp.ast.node.expression import ExpressionNode
|
from smnp.ast.node.expression import ExpressionNode
|
||||||
# from smnp.ast.node.none import NoneNode
|
from smnp.ast.node.none import NoneNode
|
||||||
# from smnp.ast.node.statement import StatementNode
|
from smnp.ast.node.statement import StatementNode
|
||||||
# from smnp.ast.parser import Parser
|
from smnp.ast.parser import Parser
|
||||||
# from smnp.token.type import TokenType
|
from smnp.token.type import TokenType
|
||||||
#
|
|
||||||
#
|
|
||||||
# class ReturnNode(StatementNode):
|
class ReturnNode(StatementNode):
|
||||||
# def __init__(self, pos):
|
def __init__(self, pos):
|
||||||
# super().__init__(pos)
|
super().__init__(pos)
|
||||||
# self.children.append(NoneNode())
|
self.children.append(NoneNode())
|
||||||
#
|
|
||||||
# @property
|
@property
|
||||||
# def value(self):
|
def value(self):
|
||||||
# return self[0]
|
return self[0]
|
||||||
#
|
|
||||||
# @value.setter
|
@value.setter
|
||||||
# def value(self, value):
|
def value(self, value):
|
||||||
# self[0] = value
|
self[0] = value
|
||||||
#
|
|
||||||
# @classmethod
|
@classmethod
|
||||||
# def _parse(cls, input):
|
def _parse(cls, input):
|
||||||
# def createNode(ret, value):
|
def createNode(ret, value):
|
||||||
# node = ReturnNode(ret.pos)
|
node = ReturnNode(ret.pos)
|
||||||
# node.value = value
|
node.value = value
|
||||||
# return node
|
return node
|
||||||
#
|
|
||||||
# return Parser.allOf(
|
return Parser.allOf(
|
||||||
# Parser.terminalParser(TokenType.RETURN),
|
Parser.terminalParser(TokenType.RETURN),
|
||||||
# Parser.doAssert(ExpressionNode.parse, "expression"),
|
Parser.doAssert(ExpressionNode.parse, "expression"),
|
||||||
# createNode=createNode
|
createNode=createNode
|
||||||
# )(input)
|
)(input)
|
||||||
@@ -1,34 +1,17 @@
|
|||||||
from smnp.ast.node.expression import MaxPrecedenceExpressionParser
|
|
||||||
from smnp.ast.node.model import Node
|
from smnp.ast.node.model import Node
|
||||||
from smnp.ast.parser import Parser
|
from smnp.ast.parser import Parser
|
||||||
|
|
||||||
|
|
||||||
class Statement(Node):
|
class StatementNode(Node):
|
||||||
pass
|
|
||||||
|
|
||||||
|
@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):
|
return Parser.oneOf(
|
||||||
from smnp.ast.node.block import BlockParser
|
ExpressionNode.parse,
|
||||||
from smnp.ast.node.condition import IfElseStatementParser
|
BlockNode.parse,
|
||||||
|
ReturnNode.parse,
|
||||||
parser = Parser.oneOf(
|
)(input)
|
||||||
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)
|
|
||||||
31
smnp/ast/node/string.py
Normal file
31
smnp/ast/node/string.py
Normal 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
|
||||||
@@ -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)))
|
|
||||||
@@ -1,63 +1,63 @@
|
|||||||
# from smnp.ast.node.iterable import abstractIterableParser
|
from smnp.ast.node.access import AccessNode
|
||||||
# from smnp.ast.node.model import Node
|
from smnp.ast.node.iterable import abstractIterableParser
|
||||||
# from smnp.ast.node.operator import LeftAssociativeOperatorNode
|
from smnp.ast.node.model import Node
|
||||||
# from smnp.ast.parser import Parser
|
from smnp.ast.parser import Parser
|
||||||
# from smnp.token.type import TokenType
|
from smnp.token.type import TokenType
|
||||||
# from smnp.type.model import Type
|
from smnp.type.model import Type
|
||||||
#
|
|
||||||
#
|
|
||||||
# class TypeSpecifier(Node):
|
class TypeSpecifier(Node):
|
||||||
#
|
|
||||||
# @classmethod
|
@classmethod
|
||||||
# def _parse(cls, input):
|
def _parse(cls, input):
|
||||||
# return abstractIterableParser(TypeSpecifier, TokenType.OPEN_ANGLE, TokenType.CLOSE_ANGLE,
|
return abstractIterableParser(TypeSpecifier, TokenType.OPEN_ANGLE, TokenType.CLOSE_ANGLE,
|
||||||
# Parser.doAssert(cls._specifierItem(), "type"))(input)
|
Parser.doAssert(cls._specifierItem(), "type"))(input)
|
||||||
#
|
|
||||||
# @classmethod
|
@classmethod
|
||||||
# def _specifierItem(cls):
|
def _specifierItem(cls):
|
||||||
# return Parser.oneOf(
|
return Parser.oneOf(
|
||||||
# TypeNode.parse,
|
TypeNode.parse,
|
||||||
# cls.parse
|
cls.parse
|
||||||
# )
|
)
|
||||||
#
|
|
||||||
# class TypeSpecifiers(Node):
|
class TypeSpecifiers(Node):
|
||||||
# pass
|
pass
|
||||||
#
|
|
||||||
#
|
|
||||||
# class TypeNode(LeftAssociativeOperatorNode):
|
class TypeNode(AccessNode):
|
||||||
# def __init__(self, pos):
|
def __init__(self, pos):
|
||||||
# super().__init__(pos)
|
super().__init__(pos)
|
||||||
#
|
|
||||||
# @property
|
@property
|
||||||
# def type(self):
|
def type(self):
|
||||||
# return self[0]
|
return self[0]
|
||||||
#
|
|
||||||
# @type.setter
|
@type.setter
|
||||||
# def type(self, value):
|
def type(self, value):
|
||||||
# self[0] = value
|
self[0] = value
|
||||||
#
|
|
||||||
# @property
|
@property
|
||||||
# def specifiers(self):
|
def specifiers(self):
|
||||||
# return self[1]
|
return self[1]
|
||||||
#
|
|
||||||
# @specifiers.setter
|
@specifiers.setter
|
||||||
# def specifiers(self, value):
|
def specifiers(self, value):
|
||||||
# self[1] = value
|
self[1] = value
|
||||||
#
|
|
||||||
# @classmethod
|
@classmethod
|
||||||
# def _parse(cls, input):
|
def _parse(cls, input):
|
||||||
# def createNode(type, specifiers):
|
def createNode(type, specifiers):
|
||||||
# node = TypeNode(type.pos)
|
node = TypeNode(type.pos)
|
||||||
# node.type = Type[type.value.upper()]
|
node.type = Type[type.value.upper()]
|
||||||
# node.specifiers = specifiers
|
node.specifiers = specifiers
|
||||||
# return node
|
return node
|
||||||
#
|
|
||||||
# return Parser.allOf(
|
return Parser.allOf(
|
||||||
# cls._rawTypeParser(),
|
cls._rawTypeParser(),
|
||||||
# Parser.many(TypeSpecifier.parse, lambda specifiers, pos: TypeSpecifiers.withChildren(specifiers, pos)),
|
Parser.many(TypeSpecifier.parse, lambda specifiers, pos: TypeSpecifiers.withChildren(specifiers, pos)),
|
||||||
# createNode=createNode
|
createNode=createNode
|
||||||
# )(input)
|
)(input)
|
||||||
#
|
|
||||||
# @classmethod
|
@classmethod
|
||||||
# def _rawTypeParser(cls):
|
def _rawTypeParser(cls):
|
||||||
# return Parser.terminalParser(TokenType.TYPE, lambda val, pos: TypeNode.withValue(val, pos))
|
return Parser.terminalParser(TokenType.TYPE, lambda val, pos: TypeNode.withValue(val, pos))
|
||||||
@@ -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
|
|
||||||
@@ -1,290 +1,176 @@
|
|||||||
from smnp.ast.node.ignore import IgnoredNode
|
from smnp.ast.node.ignore import IgnoredNode
|
||||||
from smnp.ast.node.model import ParseResult, Node
|
from smnp.ast.node.model import ParseResult, Node
|
||||||
from smnp.ast.node.none import NoneNode
|
from smnp.ast.node.none import NoneNode
|
||||||
|
from smnp.ast.node.operator import OperatorNode
|
||||||
from smnp.error.syntax import SyntaxException
|
from smnp.error.syntax import SyntaxException
|
||||||
|
|
||||||
|
|
||||||
def parse(input):
|
def parse(input):
|
||||||
from smnp.ast.node.program import ProgramParser
|
from smnp.ast.node.program import Program
|
||||||
return ProgramParser(input).node
|
return Program.parse(input).node
|
||||||
|
|
||||||
|
|
||||||
class Parser(object):
|
class Parser:
|
||||||
def __init__(self, name):
|
|
||||||
self.name = name
|
# 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()
|
return ParseResult.FAIL()
|
||||||
|
|
||||||
if not isinstance(result, ParseResult):
|
return parse
|
||||||
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:
|
|
||||||
|
|
||||||
|
# oneOf -> a | b | c | ...
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def terminal(expectedType, createNode=lambda val, pos: IgnoredNode(pos), doAssert=False):
|
def oneOf(*parsers, exception=None):
|
||||||
return TerminalParser(expectedType, createNode, doAssert)
|
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
|
@staticmethod
|
||||||
def oneOf(*parsers, name, exception=None):
|
def allOf(*parsers, createNode, 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)
|
|
||||||
|
|
||||||
if len(parsers) == 0:
|
if len(parsers) == 0:
|
||||||
raise RuntimeError("Pass one parser at least")
|
raise RuntimeError("Pass one parser at least")
|
||||||
|
|
||||||
self.parsers = parsers
|
def extendedParser(input):
|
||||||
self.createNode = createNode
|
snap = input.snapshot()
|
||||||
self.exception = exception
|
|
||||||
|
|
||||||
def _parse(self, input):
|
results = []
|
||||||
snap = input.snapshot()
|
|
||||||
parsedItems = []
|
|
||||||
|
|
||||||
for parser in self.parsers:
|
for parser in parsers:
|
||||||
result = parser.parse(input)
|
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 not result.result:
|
||||||
if self.exception is not None:
|
found = f", found '{input.current().rawValue}'" if input.hasCurrent() else ''
|
||||||
if callable(self.exception):
|
|
||||||
raise self.exception(input)
|
|
||||||
else:
|
|
||||||
raise self.exception
|
|
||||||
|
|
||||||
input.reset(snap)
|
raise SyntaxException(f"Expected {expected}{found}", input.currentPos())
|
||||||
return ParseResult.FAIL()
|
|
||||||
|
|
||||||
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 result
|
||||||
|
|
||||||
return ParseResult.OK(NoneNode())
|
return parse
|
||||||
|
|
||||||
def _grammarRules(self, output):
|
@staticmethod
|
||||||
output.append(f"{self.name} -> {self.parser.name}?")
|
def optional(parser):
|
||||||
|
def parse(input):
|
||||||
|
result = parser(input)
|
||||||
|
if result.result:
|
||||||
|
return result
|
||||||
|
|
||||||
|
return ParseResult.OK(NoneNode())
|
||||||
|
|
||||||
class LoopParser(Parser):
|
return parse
|
||||||
def __init__(self, startParser, itemParser, endParser, createNode, name):
|
|
||||||
super().__init__(name)
|
|
||||||
self.startParser = startParser
|
|
||||||
self.itemParser = itemParser
|
|
||||||
self.endParser = endParser
|
|
||||||
self.createNode = createNode
|
|
||||||
|
|
||||||
def _parse(self, input):
|
@staticmethod
|
||||||
items = []
|
def many(parser, createNode):
|
||||||
start = self.startParser.parse(input)
|
def parse(input):
|
||||||
if start.result:
|
results = []
|
||||||
|
snap = input.snapshot()
|
||||||
|
pos = input.currentPos()
|
||||||
while True:
|
while True:
|
||||||
end = self.endParser.parse(input)
|
result = parser(input)
|
||||||
if end.result:
|
if result.result:
|
||||||
return ParseResult.OK(self.createNode(start.node, items, end.node))
|
results.append(result.node)
|
||||||
item = self.itemParser.parse(input)
|
snap = input.snapshot()
|
||||||
if not item.result:
|
else:
|
||||||
return ParseResult.FAIL()
|
input.reset(snap)
|
||||||
items.append(item.node)
|
return ParseResult.OK(createNode(results, pos) if len(results) > 0 else NoneNode())
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
|
return parse
|
||||||
|
|||||||
66
smnp/calc.py
66
smnp/calc.py
@@ -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()
|
|
||||||
29
smnp/main.py
29
smnp/main.py
@@ -1,32 +1,13 @@
|
|||||||
from smnp.ast.node.atom import AtomParser
|
import sys
|
||||||
from smnp.ast.node.chain import ChainParser
|
|
||||||
from smnp.ast.node.list import ListParser
|
|
||||||
from smnp.ast.node.model import Node
|
|
||||||
from smnp.error.base import SmnpException
|
from smnp.error.base import SmnpException
|
||||||
from smnp.token.tokenizer import tokenize
|
from smnp.program.interpreter import Interpreter
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
try:
|
try:
|
||||||
# stdLibraryEnv = loadStandardLibrary()
|
#stdLibraryEnv = loadStandardLibrary()
|
||||||
# Interpreter.interpretFile(sys.argv[1], printTokens=True, printAst=True, execute=False, baseEnvironment=None)
|
Interpreter.interpretFile(sys.argv[1], printTokens=False, printAst=True, 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")
|
|
||||||
|
|
||||||
except SmnpException as e:
|
except SmnpException as e:
|
||||||
print(e.message())
|
print(e.message())
|
||||||
|
|||||||
@@ -1,25 +1,26 @@
|
|||||||
from smnp.ast.parser import parse
|
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.error.runtime import RuntimeException
|
||||||
from smnp.program.FileReader import readLines
|
from smnp.program.FileReader import readLines
|
||||||
|
from smnp.runtime.evaluator import evaluate
|
||||||
from smnp.token.tokenizer import tokenize
|
from smnp.token.tokenizer import tokenize
|
||||||
|
|
||||||
|
|
||||||
class Interpreter:
|
class Interpreter:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def interpretString(string, printTokens=False, printAst=False, execute=True, baseEnvironment=None):
|
def interpretString(string, printTokens=False, printAst=False, baseEnvironment=None):
|
||||||
return Interpreter._interpret(string.splitlines(), printTokens, printAst, execute, baseEnvironment)
|
return Interpreter._interpret(string.splitlines(), printTokens, printAst, baseEnvironment)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def interpretFile(file, printTokens=False, printAst=False, execute=True, baseEnvironment=None):
|
def interpretFile(file, printTokens=False, printAst=False, baseEnvironment=None):
|
||||||
return Interpreter._interpret(readLines(file), printTokens, printAst, execute, baseEnvironment)
|
return Interpreter._interpret(readLines(file), printTokens, printAst, baseEnvironment)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _interpret(lines, printTokens=False, printAst=False, execute=True, baseEnvironment=None):
|
def _interpret(lines, printTokens=False, printAst=False, baseEnvironment=None):
|
||||||
#environment = createEnvironment()
|
environment = createEnvironment()
|
||||||
#if baseEnvironment is not None:
|
if baseEnvironment is not None:
|
||||||
# environment.extend(baseEnvironment)
|
environment.extend(baseEnvironment)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
tokens = tokenize(lines)
|
tokens = tokenize(lines)
|
||||||
@@ -30,10 +31,9 @@ class Interpreter:
|
|||||||
if printAst:
|
if printAst:
|
||||||
ast.print()
|
ast.print()
|
||||||
|
|
||||||
#if execute:
|
evaluate(ast, environment)
|
||||||
# evaluate(ast, environment)
|
|
||||||
|
|
||||||
#return environment
|
return environment
|
||||||
except RuntimeException as e:
|
except RuntimeException as e:
|
||||||
#e.environment = environment
|
e.environment = environment
|
||||||
raise e
|
raise e
|
||||||
@@ -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.program import Program
|
||||||
from smnp.ast.node.ret import ReturnNode
|
|
||||||
from smnp.error.runtime import RuntimeException
|
from smnp.error.runtime import RuntimeException
|
||||||
from smnp.type.model import Type
|
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.program import ProgramEvaluator
|
||||||
from smnp.runtime.evaluators.expression import expressionEvaluator
|
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(
|
result = Evaluator.oneOf(
|
||||||
Evaluator.forNodes(ProgramEvaluator.evaluate, Program),
|
Evaluator.forNodes(ProgramEvaluator.evaluate, Program),
|
||||||
Evaluator.forNodes(ImportEvaluator.evaluate, ImportNode),
|
#Evaluator.forNodes(ImportEvaluator.evaluate, ImportNode),
|
||||||
Evaluator.forNodes(FunctionDefinitionEvaluator.evaluate, FunctionDefinitionNode),
|
#Evaluator.forNodes(FunctionDefinitionEvaluator.evaluate, FunctionDefinitionNode),
|
||||||
Evaluator.forNodes(ExtendEvaluator.evaluate, ExtendNode),
|
#Evaluator.forNodes(ExtendEvaluator.evaluate, ExtendNode),
|
||||||
Evaluator.forNodes(BlockEvaluator.evaluate, BlockNode),
|
#Evaluator.forNodes(BlockEvaluator.evaluate, BlockNode),
|
||||||
Evaluator.forNodes(ReturnEvaluator.evaluate, ReturnNode),
|
#Evaluator.forNodes(ReturnEvaluator.evaluate, ReturnNode),
|
||||||
expressionEvaluator()
|
expressionEvaluator()
|
||||||
)(node, environment)
|
)(node, environment)
|
||||||
|
|
||||||
|
|||||||
@@ -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.ast.node.invocation import FunctionCallNode
|
||||||
from smnp.error.runtime import RuntimeException
|
from smnp.error.runtime import RuntimeException
|
||||||
from smnp.runtime.evaluator import Evaluator
|
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
|
left = expressionEvaluator(doAssert=True)(node.left, environment).value #TODO check if it isn't necessary to verify 'result' attr of EvaluatioNResult
|
||||||
right = node.right
|
right = node.right
|
||||||
|
|
||||||
if type(right) == Identifier:
|
if type(right) == IdentifierNode:
|
||||||
try:
|
try:
|
||||||
return left.properties[right.value]
|
return left.properties[right.value]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
|||||||
@@ -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.evaluator import evaluate, Evaluator, EvaluationResult
|
||||||
from smnp.runtime.evaluators.expression import expressionEvaluator
|
from smnp.runtime.evaluators.expression import expressionEvaluator
|
||||||
from smnp.type.model import Type
|
from smnp.type.model import Type
|
||||||
@@ -40,7 +40,7 @@ class AsteriskEvaluator(Evaluator):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _automaticNamedVariable(cls, iteratorNode, environment, prefix=''):
|
def _automaticNamedVariable(cls, iteratorNode, environment, prefix=''):
|
||||||
if type(iteratorNode) == Identifier:
|
if type(iteratorNode) == IdentifierNode:
|
||||||
return cls._automaticVariableName(environment, prefix, iteratorNode.value, False)
|
return cls._automaticVariableName(environment, prefix, iteratorNode.value, False)
|
||||||
else:
|
else:
|
||||||
return cls._automaticVariableName(environment, prefix, '', True)
|
return cls._automaticVariableName(environment, prefix, '', True)
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
|
from smnp.ast.node.access import AccessNode
|
||||||
from smnp.ast.node.assignment import AssignmentNode
|
from smnp.ast.node.assignment import AssignmentNode
|
||||||
from smnp.ast.node.asterisk import AsteriskNode
|
from smnp.ast.node.asterisk import AsteriskNode
|
||||||
from smnp.ast.node.bool import BoolLiteralNode
|
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.integer import IntegerLiteralNode
|
||||||
from smnp.ast.node.invocation import FunctionCallNode
|
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.map import MapNode
|
||||||
from smnp.ast.node.note import NoteLiteralNode
|
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.string import StringLiteralNode
|
||||||
from smnp.ast.node.type import TypeNode
|
from smnp.ast.node.type import TypeNode
|
||||||
from smnp.error.runtime import RuntimeException
|
from smnp.error.runtime import RuntimeException
|
||||||
@@ -37,9 +37,9 @@ def expressionEvaluator(doAssert=False):
|
|||||||
Evaluator.forNodes(NoteEvaluator.evaluate, NoteLiteralNode),
|
Evaluator.forNodes(NoteEvaluator.evaluate, NoteLiteralNode),
|
||||||
Evaluator.forNodes(BoolEvaluator.evaluate, BoolLiteralNode),
|
Evaluator.forNodes(BoolEvaluator.evaluate, BoolLiteralNode),
|
||||||
Evaluator.forNodes(TypeEvaluator.evaluate, TypeNode),
|
Evaluator.forNodes(TypeEvaluator.evaluate, TypeNode),
|
||||||
Evaluator.forNodes(IdentifierEvaluator.evaluate, Identifier),
|
Evaluator.forNodes(IdentifierEvaluator.evaluate, IdentifierNode),
|
||||||
Evaluator.forNodes(ListEvaluator.evaluate, List),
|
Evaluator.forNodes(ListEvaluator.evaluate, ListNode),
|
||||||
Evaluator.forNodes(AccessEvaluator.evaluate, LeftAssociativeOperatorNode),
|
Evaluator.forNodes(AccessEvaluator.evaluate, AccessNode),
|
||||||
Evaluator.forNodes(AssignmentEvaluator.evaluate, AssignmentNode),
|
Evaluator.forNodes(AssignmentEvaluator.evaluate, AssignmentNode),
|
||||||
Evaluator.forNodes(AsteriskEvaluator.evaluate, AsteriskNode),
|
Evaluator.forNodes(AsteriskEvaluator.evaluate, AsteriskNode),
|
||||||
Evaluator.forNodes(MapEvaluator.evaluate, MapNode)
|
Evaluator.forNodes(MapEvaluator.evaluate, MapNode)
|
||||||
|
|||||||
@@ -5,18 +5,13 @@ from smnp.token.tokenizers.comment import commentTokenizer
|
|||||||
from smnp.token.tokenizers.identifier import identifierTokenizer
|
from smnp.token.tokenizers.identifier import identifierTokenizer
|
||||||
from smnp.token.tokenizers.keyword import typeTokenizer
|
from smnp.token.tokenizers.keyword import typeTokenizer
|
||||||
from smnp.token.tokenizers.note import noteTokenizer
|
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.string import stringTokenizer
|
||||||
from smnp.token.tokenizers.whitespace import whitespacesTokenizer
|
from smnp.token.tokenizers.whitespace import whitespacesTokenizer
|
||||||
from smnp.token.tools import defaultTokenizer, separated, regexPatternTokenizer
|
from smnp.token.tools import defaultTokenizer, separated, regexPatternTokenizer
|
||||||
from smnp.token.type import TokenType
|
from smnp.token.type import TokenType
|
||||||
|
|
||||||
tokenizers = (
|
tokenizers = (
|
||||||
defaultTokenizer(TokenType.ARROW),
|
defaultTokenizer(TokenType.EQUAL),
|
||||||
|
|
||||||
# Double-character operators
|
|
||||||
relationOperatorTokenizer,
|
|
||||||
defaultTokenizer(TokenType.DOUBLE_ASTERISK),
|
|
||||||
|
|
||||||
# Characters
|
# Characters
|
||||||
defaultTokenizer(TokenType.OPEN_CURLY),
|
defaultTokenizer(TokenType.OPEN_CURLY),
|
||||||
@@ -29,11 +24,9 @@ tokenizers = (
|
|||||||
defaultTokenizer(TokenType.CLOSE_ANGLE),
|
defaultTokenizer(TokenType.CLOSE_ANGLE),
|
||||||
defaultTokenizer(TokenType.ASTERISK),
|
defaultTokenizer(TokenType.ASTERISK),
|
||||||
defaultTokenizer(TokenType.ASSIGN),
|
defaultTokenizer(TokenType.ASSIGN),
|
||||||
|
defaultTokenizer(TokenType.ARROW),
|
||||||
defaultTokenizer(TokenType.COMMA),
|
defaultTokenizer(TokenType.COMMA),
|
||||||
defaultTokenizer(TokenType.SLASH),
|
|
||||||
defaultTokenizer(TokenType.MINUS),
|
defaultTokenizer(TokenType.MINUS),
|
||||||
defaultTokenizer(TokenType.PLUS),
|
|
||||||
defaultTokenizer(TokenType.DASH),
|
|
||||||
defaultTokenizer(TokenType.DOTS),
|
defaultTokenizer(TokenType.DOTS),
|
||||||
defaultTokenizer(TokenType.AMP),
|
defaultTokenizer(TokenType.AMP),
|
||||||
defaultTokenizer(TokenType.DOT),
|
defaultTokenizer(TokenType.DOT),
|
||||||
@@ -51,12 +44,7 @@ tokenizers = (
|
|||||||
separated(defaultTokenizer(TokenType.EXTEND)),
|
separated(defaultTokenizer(TokenType.EXTEND)),
|
||||||
separated(defaultTokenizer(TokenType.IMPORT)),
|
separated(defaultTokenizer(TokenType.IMPORT)),
|
||||||
separated(defaultTokenizer(TokenType.FROM)),
|
separated(defaultTokenizer(TokenType.FROM)),
|
||||||
separated(defaultTokenizer(TokenType.ELSE)),
|
|
||||||
separated(defaultTokenizer(TokenType.AND)),
|
|
||||||
separated(defaultTokenizer(TokenType.NOT)),
|
|
||||||
separated(defaultTokenizer(TokenType.AS)),
|
separated(defaultTokenizer(TokenType.AS)),
|
||||||
separated(defaultTokenizer(TokenType.IF)),
|
|
||||||
separated(defaultTokenizer(TokenType.OR)),
|
|
||||||
|
|
||||||
# Identifier (couldn't be before keywords!)
|
# Identifier (couldn't be before keywords!)
|
||||||
identifierTokenizer,
|
identifierTokenizer,
|
||||||
|
|||||||
@@ -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)
|
|
||||||
@@ -2,8 +2,7 @@ from enum import Enum
|
|||||||
|
|
||||||
|
|
||||||
class TokenType(Enum):
|
class TokenType(Enum):
|
||||||
RELATION = 'relation'
|
EQUAL = '=='
|
||||||
DOUBLE_ASTERISK = '**'
|
|
||||||
OPEN_CURLY = '{'
|
OPEN_CURLY = '{'
|
||||||
CLOSE_CURLY = '}'
|
CLOSE_CURLY = '}'
|
||||||
OPEN_PAREN = '('
|
OPEN_PAREN = '('
|
||||||
@@ -16,16 +15,10 @@ class TokenType(Enum):
|
|||||||
ASSIGN = '='
|
ASSIGN = '='
|
||||||
ARROW = '->'
|
ARROW = '->'
|
||||||
COMMA = ','
|
COMMA = ','
|
||||||
SLASH = '/'
|
|
||||||
MINUS = '-'
|
MINUS = '-'
|
||||||
PLUS = '+'
|
|
||||||
DASH = '^'
|
|
||||||
DOTS = '...'
|
DOTS = '...'
|
||||||
AMP = '&'
|
AMP = '&'
|
||||||
DOT = '.'
|
DOT = '.'
|
||||||
AND = 'and'
|
|
||||||
OR = 'or'
|
|
||||||
NOT = 'not'
|
|
||||||
INTEGER = 'integer'
|
INTEGER = 'integer'
|
||||||
STRING = 'string'
|
STRING = 'string'
|
||||||
NOTE = 'note'
|
NOTE = 'note'
|
||||||
@@ -36,8 +29,6 @@ class TokenType(Enum):
|
|||||||
EXTEND = 'extend'
|
EXTEND = 'extend'
|
||||||
IMPORT = 'import'
|
IMPORT = 'import'
|
||||||
FROM = 'from'
|
FROM = 'from'
|
||||||
ELSE = 'else'
|
|
||||||
IF = 'if'
|
|
||||||
AS = 'as'
|
AS = 'as'
|
||||||
IDENTIFIER = 'identifier'
|
IDENTIFIER = 'identifier'
|
||||||
COMMENT = 'comment'
|
COMMENT = 'comment'
|
||||||
|
|||||||
@@ -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
|
|
||||||
Reference in New Issue
Block a user