Compare commits
4 Commits
left-assoc
...
new-parser
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
49e4c4487e | ||
|
|
e7674a4834 | ||
|
|
ed2c8dc6dd | ||
|
|
f91e2a75de |
@@ -1,6 +1,7 @@
|
|||||||
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 Parsers
|
||||||
from smnp.token.type import TokenType
|
from smnp.token.type import TokenType
|
||||||
|
from smnp.util.singleton import SingletonParser
|
||||||
|
|
||||||
|
|
||||||
class Atom(Node):
|
class Atom(Node):
|
||||||
@@ -43,48 +44,60 @@ class TypeLiteral(Atom):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def IntegerParser(input):
|
@SingletonParser
|
||||||
return Parser.terminal(TokenType.INTEGER, createNode=IntegerLiteral.withValue)(input)
|
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"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def StringParser(input):
|
@SingletonParser
|
||||||
return Parser.terminal(TokenType.STRING, createNode=StringLiteral.withValue)(input)
|
def StringParser():
|
||||||
|
return Parsers.terminal(TokenType.STRING, createNode=StringLiteral.withValue)
|
||||||
|
|
||||||
|
|
||||||
def NoteParser(input):
|
@SingletonParser
|
||||||
return Parser.terminal(TokenType.NOTE, createNode=NoteLiteral.withValue)(input)
|
def NoteParser():
|
||||||
|
return Parsers.terminal(TokenType.NOTE, createNode=NoteLiteral.withValue)
|
||||||
|
|
||||||
|
|
||||||
def BoolParser(input):
|
@SingletonParser
|
||||||
return Parser.terminal(TokenType.BOOL, createNode=BoolLiteral.withValue)(input)
|
def BoolParser():
|
||||||
|
return Parsers.terminal(TokenType.BOOL, createNode=BoolLiteral.withValue)
|
||||||
|
|
||||||
|
|
||||||
def TypeLiteralParser(input):
|
@SingletonParser
|
||||||
return Parser.terminal(TokenType.TYPE, createNode=TypeLiteral.withValue)(input)
|
def TypeParser():
|
||||||
|
return Parsers.terminal(TokenType.TYPE, createNode=TypeLiteral.withValue)
|
||||||
|
|
||||||
|
|
||||||
def LiteralParser(input):
|
@SingletonParser
|
||||||
return Parser.oneOf(
|
def LiteralParser():
|
||||||
IntegerParser,
|
return Parsers.oneOf(
|
||||||
StringParser,
|
IntegerParser(),
|
||||||
NoteParser,
|
StringParser(),
|
||||||
BoolParser,
|
NoteParser(),
|
||||||
TypeLiteralParser,
|
BoolParser(),
|
||||||
|
TypeParser(),
|
||||||
name="literal"
|
name="literal"
|
||||||
)(input)
|
)
|
||||||
|
|
||||||
|
|
||||||
def AtomParser(input):
|
@SingletonParser
|
||||||
|
def AtomParser():
|
||||||
from smnp.ast.node.identifier import IdentifierParser
|
from smnp.ast.node.identifier import IdentifierParser
|
||||||
from smnp.ast.node.list import ListParser
|
|
||||||
from smnp.ast.node.map import MapParser
|
|
||||||
|
|
||||||
return Parser.oneOf(
|
return Parsers.oneOf(
|
||||||
LiteralParser,
|
LiteralParser(),
|
||||||
IdentifierParser,
|
IdentifierParser(),
|
||||||
ListParser,
|
|
||||||
MapParser,
|
|
||||||
name="atom"
|
name="atom"
|
||||||
)(input)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,11 @@ class Block(Node):
|
|||||||
|
|
||||||
|
|
||||||
def BlockParser(input):
|
def BlockParser(input):
|
||||||
return Parser.loop(
|
parser = Parser.loop(
|
||||||
Parser.terminal(TokenType.OPEN_CURLY),
|
Parser.terminalParser(TokenType.OPEN_CURLY),
|
||||||
Parser.doAssert(StatementParser, f"statement or '{TokenType.CLOSE_CURLY.key}'"),
|
Parser.doAssert(StatementParser, f"statement or '{TokenType.CLOSE_CURLY.key}'"),
|
||||||
Parser.terminal(TokenType.CLOSE_CURLY),
|
Parser.terminalParser(TokenType.CLOSE_CURLY),
|
||||||
createNode=lambda open, statements, close: Block.withChildren(statements, open.pos)
|
createNode=lambda open, statements, close: Block.withChildren(statements, open.pos)
|
||||||
)(input)
|
)
|
||||||
|
|
||||||
|
return Parser(parser, "block", [parser])(input)
|
||||||
|
|||||||
32
smnp/ast/node/chain.py
Normal file
32
smnp/ast/node/chain.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
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,4 +1,4 @@
|
|||||||
from smnp.ast.node.expression import ExpressionParser
|
from smnp.ast.node.expression import MaxPrecedenceExpressionParser
|
||||||
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 StatementParser
|
from smnp.ast.node.statement import StatementParser
|
||||||
@@ -46,23 +46,23 @@ class IfElse(Node):
|
|||||||
|
|
||||||
def IfElseStatementParser(input):
|
def IfElseStatementParser(input):
|
||||||
ifStatementParser = Parser.allOf(
|
ifStatementParser = Parser.allOf(
|
||||||
Parser.terminal(TokenType.IF),
|
Parser.terminalParser(TokenType.IF),
|
||||||
Parser.terminal(TokenType.OPEN_PAREN),
|
Parser.terminalParser(TokenType.OPEN_PAREN),
|
||||||
ExpressionParser,
|
MaxPrecedenceExpressionParser,
|
||||||
Parser.terminal(TokenType.CLOSE_PAREN),
|
Parser.terminalParser(TokenType.CLOSE_PAREN),
|
||||||
StatementParser,
|
StatementParser,
|
||||||
createNode=lambda _, __, condition, ___, ifStatement: IfElse.createNode(ifStatement, condition),
|
createNode=lambda _, __, condition, ___, ifStatement: IfElse.createNode(ifStatement, condition),
|
||||||
name="if statement"
|
name="if statement"
|
||||||
)
|
)
|
||||||
|
|
||||||
ifElseStatementParser = Parser.allOf(
|
ifElseStatementParser = Parser.allOf(
|
||||||
Parser.terminal(TokenType.IF),
|
Parser.terminalParser(TokenType.IF),
|
||||||
Parser.terminal(TokenType.OPEN_PAREN, doAssert=True),
|
Parser.terminalParser(TokenType.OPEN_PAREN),
|
||||||
Parser.doAssert(ExpressionParser, "expression"),
|
MaxPrecedenceExpressionParser,
|
||||||
Parser.terminal(TokenType.CLOSE_PAREN, doAssert=True),
|
Parser.terminalParser(TokenType.CLOSE_PAREN),
|
||||||
Parser.doAssert(StatementParser, "statement"),
|
StatementParser,
|
||||||
Parser.terminal(TokenType.ELSE),
|
Parser.terminalParser(TokenType.ELSE),
|
||||||
Parser.doAssert(StatementParser, "statement"),
|
StatementParser,
|
||||||
createNode=lambda _, __, condition, ___, ifStatement, ____, elseStatement: IfElse.createNode(ifStatement, condition, elseStatement),
|
createNode=lambda _, __, condition, ___, ifStatement, ____, elseStatement: IfElse.createNode(ifStatement, condition, elseStatement),
|
||||||
name="if-else statement"
|
name="if-else statement"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,51 +1,63 @@
|
|||||||
from smnp.ast.node.operator import BinaryOperator
|
from smnp.ast.node.operator import BinaryOperator
|
||||||
from smnp.ast.node.term import TermParser
|
from smnp.ast.node.term import TermParser
|
||||||
|
from smnp.ast.node.valuable import Valuable
|
||||||
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 Sum(BinaryOperator):
|
class Expression(Valuable):
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class Relation(BinaryOperator):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class And(BinaryOperator):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class Or(BinaryOperator):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def ExpressionParser(input):
|
def ExpressionParser(input):
|
||||||
expr1 = Parser.leftAssociativeOperatorParser(
|
return Parser.leftAssociativeOperatorParser(
|
||||||
TermParser,
|
TermParser,
|
||||||
[TokenType.PLUS, TokenType.MINUS],
|
[TokenType.PLUS, TokenType.MINUS],
|
||||||
TermParser,
|
TermParser,
|
||||||
lambda left, op, right: Sum.withValues(left, op, right)
|
lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right))
|
||||||
)
|
|
||||||
|
|
||||||
expr2 = Parser.leftAssociativeOperatorParser(
|
|
||||||
expr1,
|
|
||||||
[TokenType.RELATION, TokenType.OPEN_ANGLE, TokenType.CLOSE_ANGLE],
|
|
||||||
expr1,
|
|
||||||
lambda left, op, right: Relation.withValues(left, op, right)
|
|
||||||
)
|
|
||||||
|
|
||||||
expr3 = Parser.leftAssociativeOperatorParser(
|
|
||||||
expr2,
|
|
||||||
[TokenType.AND],
|
|
||||||
expr2,
|
|
||||||
lambda left, op, right: And.withValues(left, op, right)
|
|
||||||
)
|
|
||||||
|
|
||||||
return Parser.leftAssociativeOperatorParser(
|
|
||||||
expr3,
|
|
||||||
[TokenType.OR],
|
|
||||||
expr3,
|
|
||||||
lambda left, op, right: Or.withValues(left, op, right)
|
|
||||||
)(input)
|
)(input)
|
||||||
|
|
||||||
|
|
||||||
|
def Expression2Parser(input):
|
||||||
|
return Parser.leftAssociativeOperatorParser(
|
||||||
|
ExpressionParser,
|
||||||
|
[TokenType.RELATION],
|
||||||
|
ExpressionParser,
|
||||||
|
lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right))
|
||||||
|
)(input)
|
||||||
|
|
||||||
|
|
||||||
|
def Expression3Parser(input):
|
||||||
|
return Parser.leftAssociativeOperatorParser(
|
||||||
|
Expression2Parser,
|
||||||
|
[TokenType.AND],
|
||||||
|
Expression2Parser,
|
||||||
|
lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right))
|
||||||
|
)(input)
|
||||||
|
|
||||||
|
|
||||||
|
def Expression4Parser(input):
|
||||||
|
from smnp.ast.node.condition import IfElse
|
||||||
|
exprParser = Parser.leftAssociativeOperatorParser(
|
||||||
|
Expression3Parser,
|
||||||
|
[TokenType.OR],
|
||||||
|
Expression3Parser,
|
||||||
|
lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right))
|
||||||
|
)
|
||||||
|
|
||||||
|
ifElseExpression = Parser.allOf(
|
||||||
|
exprParser,
|
||||||
|
Parser.terminalParser(TokenType.IF),
|
||||||
|
Expression4Parser,
|
||||||
|
Parser.terminalParser(TokenType.ELSE),
|
||||||
|
Expression4Parser,
|
||||||
|
createNode=lambda ifNode, _, condition, __, elseNode: IfElse.createNode(ifNode, condition, elseNode)
|
||||||
|
)
|
||||||
|
|
||||||
|
return Parser.oneOf(
|
||||||
|
ifElseExpression,
|
||||||
|
exprParser,
|
||||||
|
)(input)
|
||||||
|
|
||||||
|
|
||||||
|
MaxPrecedenceExpressionParser = Expression4Parser
|
||||||
@@ -1,88 +1,70 @@
|
|||||||
from smnp.ast.node.block import Block
|
# from smnp.ast.node.block import BlockNode
|
||||||
from smnp.ast.node.function import FunctionDefinitionParser
|
# from smnp.ast.node.function import FunctionDefinitionNode
|
||||||
from smnp.ast.node.identifier import IdentifierLiteralParser
|
# 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.none import NoneNode
|
# from smnp.ast.node.statement import StatementNode
|
||||||
from smnp.ast.node.type import TypeParser
|
# 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 Extend(Node):
|
# 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 withValues(cls, pos, type, variable, methods):
|
# def _parse(cls, input):
|
||||||
node = cls(pos)
|
# def createNode(extend, type, asKeyword, variable, methods):
|
||||||
node.type = type
|
# node = ExtendNode(extend.pos)
|
||||||
node.variable = variable
|
# node.type = type
|
||||||
node.methods = methods
|
# node.variable = variable
|
||||||
return node
|
# node.methods = methods
|
||||||
|
# return node
|
||||||
|
#
|
||||||
def ExtendParser(input):
|
# return Parser.allOf(
|
||||||
|
# Parser.terminalParser(TokenType.EXTEND),
|
||||||
simpleExtend = Parser.allOf(
|
# Parser.doAssert(TypeNode.parse, "type being extended"),
|
||||||
Parser.terminal(TokenType.EXTEND),
|
# Parser.terminalParser(TokenType.AS, doAssert=True),
|
||||||
TypeParser,
|
# Parser.doAssert(IdentifierNode.identifierParser(), "variable name"),
|
||||||
Parser.terminal(TokenType.AS),
|
# Parser.doAssert(cls._methodsDeclarationsParser(), "methods declarations"),
|
||||||
IdentifierLiteralParser,
|
# createNode=createNode
|
||||||
Parser.terminal(TokenType.WITH),
|
# )(input)
|
||||||
Parser.doAssert(Parser.wrap(FunctionDefinitionParser, lambda method: Block.withChildren([ method ], method.pos)), "method definition"),
|
#
|
||||||
createNode=lambda extend, type, _, variable, __, methods: Extend.withValues(extend.pos, type, variable, methods),
|
# @classmethod
|
||||||
name="simple extend"
|
# def _methodsDeclarationsParser(cls):
|
||||||
)
|
# def createNode(openBracket, items, closeBracket):
|
||||||
|
# node = BlockNode(openBracket.pos)
|
||||||
multiExtend = Parser.allOf(
|
# node.children = items
|
||||||
Parser.terminal(TokenType.EXTEND),
|
# return node
|
||||||
Parser.doAssert(TypeParser, "type being extended"),
|
#
|
||||||
Parser.terminal(TokenType.AS, doAssert=True),
|
# return Parser.loop(
|
||||||
Parser.doAssert(IdentifierLiteralParser, "variable name"),
|
# Parser.terminalParser(TokenType.OPEN_CURLY),
|
||||||
Parser.doAssert(MethodsDeclarationParser, f"block with methods definitions or '{TokenType.WITH.key}' keyword"),
|
# Parser.doAssert(FunctionDefinitionNode.parse, f"method declaration or '{TokenType.CLOSE_CURLY.key}'"),
|
||||||
createNode=lambda extend, type, _, variable, methods: Extend.withValues(extend.pos, type, variable, methods),
|
# Parser.terminalParser(TokenType.CLOSE_CURLY),
|
||||||
name="multiple extend"
|
# createNode=createNode
|
||||||
)
|
# )
|
||||||
|
|
||||||
|
|
||||||
return Parser.oneOf(
|
|
||||||
simpleExtend,
|
|
||||||
multiExtend,
|
|
||||||
name="extend"
|
|
||||||
)(input)
|
|
||||||
|
|
||||||
|
|
||||||
def MethodsDeclarationParser(input):
|
|
||||||
return Parser.loop(
|
|
||||||
Parser.terminal(TokenType.OPEN_CURLY),
|
|
||||||
Parser.doAssert(FunctionDefinitionParser, f"method definition or '{TokenType.CLOSE_CURLY.key}'"),
|
|
||||||
Parser.terminal(TokenType.CLOSE_CURLY),
|
|
||||||
createNode=lambda open, methods, close: Block.withChildren(methods, open.pos),
|
|
||||||
name="methods block"
|
|
||||||
)(input)
|
|
||||||
|
|
||||||
@@ -1,102 +1,64 @@
|
|||||||
from smnp.ast.node.iterable import abstractIterableParser
|
from smnp.ast.node.chain import ChainParser
|
||||||
from smnp.ast.node.model import Node
|
|
||||||
from smnp.ast.node.none import NoneNode
|
|
||||||
from smnp.ast.node.operator import BinaryOperator, Operator, UnaryOperator
|
from smnp.ast.node.operator import BinaryOperator, Operator, UnaryOperator
|
||||||
from smnp.ast.node.unit import UnitParser
|
from smnp.ast.node.valuable import Valuable
|
||||||
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 Factor(Valuable):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class NotOperator(UnaryOperator):
|
class NotOperator(UnaryOperator):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Power(BinaryOperator):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class Loop(BinaryOperator):
|
class Loop(BinaryOperator):
|
||||||
def __init__(self, pos):
|
|
||||||
super().__init__(pos)
|
|
||||||
self.children.append(NoneNode())
|
|
||||||
|
|
||||||
@property
|
|
||||||
def parameters(self):
|
|
||||||
return self[3]
|
|
||||||
|
|
||||||
@parameters.setter
|
|
||||||
def parameters(self, value):
|
|
||||||
self[3] = value
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def loop(cls, left, parameters, operator, right):
|
|
||||||
node = cls(left.pos)
|
|
||||||
node.left = left
|
|
||||||
node.parameters = parameters
|
|
||||||
node.operator = operator
|
|
||||||
node.right = right
|
|
||||||
return node
|
|
||||||
|
|
||||||
|
|
||||||
class LoopParameters(Node):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def FactorParser(input):
|
def FactorParser(input):
|
||||||
from smnp.ast.node.expression import ExpressionParser
|
from smnp.ast.node.expression import MaxPrecedenceExpressionParser
|
||||||
from smnp.ast.node.statement import StatementParser
|
from smnp.ast.node.statement import StatementParser
|
||||||
from smnp.ast.node.identifier import IdentifierLiteralParser
|
|
||||||
|
|
||||||
parentheses = Parser.allOf(
|
powerFactor = Parser.leftAssociativeOperatorParser(
|
||||||
Parser.terminal(TokenType.OPEN_PAREN),
|
ChainParser,
|
||||||
Parser.doAssert(ExpressionParser, "expression"),
|
[TokenType.DOUBLE_ASTERISK],
|
||||||
Parser.terminal(TokenType.CLOSE_PAREN),
|
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,
|
createNode=lambda open, expr, close: expr,
|
||||||
name="grouping parentheses"
|
name="grouping parentheses"
|
||||||
)
|
)
|
||||||
|
|
||||||
factorOperands = Parser.oneOf(
|
factorParser = Parser.oneOf(
|
||||||
parentheses,
|
powerFactor,
|
||||||
UnitParser,
|
exprFactor,
|
||||||
name="factor operands"
|
name="basic factor"
|
||||||
)
|
|
||||||
|
|
||||||
powerFactor = Parser.leftAssociativeOperatorParser(
|
|
||||||
factorOperands,
|
|
||||||
[TokenType.DOUBLE_ASTERISK],
|
|
||||||
factorOperands,
|
|
||||||
lambda left, op, right: Power.withValues(left, op, right),
|
|
||||||
name="power operator"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
notOperator = Parser.allOf(
|
notOperator = Parser.allOf(
|
||||||
Parser.terminal(TokenType.NOT, Operator.withValue),
|
Parser.terminalParser(TokenType.NOT, Operator.withValue),
|
||||||
powerFactor,
|
factorParser,
|
||||||
createNode=NotOperator.withValues,
|
createNode=NotOperator.withValues,
|
||||||
name="not"
|
name="not"
|
||||||
)
|
)
|
||||||
|
|
||||||
loopParameters = Parser.allOf(
|
|
||||||
Parser.terminal(TokenType.AS),
|
|
||||||
Parser.oneOf(
|
|
||||||
Parser.wrap(IdentifierLiteralParser, lambda id: LoopParameters.withChildren([id], id.pos)),
|
|
||||||
abstractIterableParser(LoopParameters, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN, IdentifierLiteralParser)
|
|
||||||
),
|
|
||||||
createNode=lambda asKeyword, parameters: parameters,
|
|
||||||
name="loop parameters"
|
|
||||||
)
|
|
||||||
|
|
||||||
loopFactor = Parser.allOf(
|
loopFactor = Parser.allOf(
|
||||||
powerFactor,
|
factorParser,
|
||||||
Parser.optional(loopParameters),
|
Parser.terminalParser(TokenType.DASH, createNode=Operator.withValue),
|
||||||
Parser.terminal(TokenType.DASH, createNode=Operator.withValue),
|
|
||||||
StatementParser,
|
StatementParser,
|
||||||
createNode=Loop.loop,
|
createNode=Loop.withValues,
|
||||||
name="dash-loop"
|
name="dash-loop"
|
||||||
)
|
)
|
||||||
|
|
||||||
return Parser.oneOf(
|
return Parser.oneOf(
|
||||||
loopFactor,
|
loopFactor,
|
||||||
notOperator,
|
notOperator,
|
||||||
powerFactor,
|
factorParser
|
||||||
name="factor"
|
|
||||||
)(input)
|
)(input)
|
||||||
|
|||||||
@@ -1,129 +1,128 @@
|
|||||||
from smnp.ast.node.block import BlockParser
|
# from smnp.ast.node.block import BlockNode
|
||||||
from smnp.ast.node.identifier import IdentifierLiteralParser
|
# from smnp.ast.node.expression import ExpressionNode
|
||||||
from smnp.ast.node.iterable import abstractIterableParser
|
# from smnp.ast.node.identifier import IdentifierNode
|
||||||
from smnp.ast.node.model import Node
|
# from smnp.ast.node.iterable import abstractIterableParser
|
||||||
from smnp.ast.node.none import NoneNode
|
# from smnp.ast.node.model import Node
|
||||||
from smnp.ast.node.type import TypeParser, Type
|
# from smnp.ast.node.none import NoneNode
|
||||||
from smnp.ast.parser import Parser
|
# from smnp.ast.node.statement import StatementNode
|
||||||
from smnp.token.type import TokenType
|
# from smnp.ast.node.type import TypeNode, TypeSpecifier
|
||||||
|
# from smnp.ast.parser import Parser
|
||||||
|
# from smnp.token.type import TokenType
|
||||||
class ArgumentsDeclaration(Node):
|
#
|
||||||
pass
|
#
|
||||||
|
# class ArgumentsDeclarationNode(Node):
|
||||||
|
#
|
||||||
class Argument(Node):
|
# @classmethod
|
||||||
|
# def _parse(cls, input):
|
||||||
def __init__(self, pos):
|
# raise RuntimeError("This class is not supposed to be automatically called")
|
||||||
super().__init__(pos)
|
#
|
||||||
self.children = [NoneNode(), NoneNode(), False]
|
#
|
||||||
|
# class VarargNode(Node):
|
||||||
@property
|
# pass
|
||||||
def type(self):
|
#
|
||||||
return self[0]
|
#
|
||||||
|
# class ArgumentDefinitionNode(ExpressionNode):
|
||||||
|
# def __init__(self, pos):
|
||||||
@type.setter
|
# super().__init__(pos)
|
||||||
def type(self, value):
|
# self.children.extend([NoneNode(), False])
|
||||||
self[0] = value
|
#
|
||||||
|
# @property
|
||||||
|
# def type(self):
|
||||||
@property
|
# return self[0]
|
||||||
def variable(self):
|
#
|
||||||
return self[1]
|
# @type.setter
|
||||||
|
# def type(self, value):
|
||||||
|
# self[0] = value
|
||||||
@variable.setter
|
#
|
||||||
def variable(self, value):
|
# @property
|
||||||
self[1] = value
|
# def variable(self):
|
||||||
|
# return self[1]
|
||||||
|
#
|
||||||
@property
|
# @variable.setter
|
||||||
def vararg(self):
|
# def variable(self, value):
|
||||||
return self[2]
|
# self[1] = value
|
||||||
|
#
|
||||||
|
# @property
|
||||||
@vararg.setter
|
# def vararg(self):
|
||||||
def vararg(self, value):
|
# return self[2]
|
||||||
self[2] = value
|
#
|
||||||
|
# @vararg.setter
|
||||||
|
# def vararg(self, value):
|
||||||
class VarargNode(Node):
|
# self[2] = value
|
||||||
pass
|
#
|
||||||
|
#
|
||||||
|
# @classmethod
|
||||||
class FunctionDefinition(Node):
|
# def parser(cls):
|
||||||
def __init__(self, pos):
|
# def createNode(type, variable, dots):
|
||||||
super().__init__(pos)
|
# node = ArgumentDefinitionNode(type.pos)
|
||||||
self.children = [NoneNode(), NoneNode(), NoneNode()]
|
# node.type = type
|
||||||
|
# node.variable = variable
|
||||||
@property
|
# node.vararg = isinstance(dots, VarargNode)
|
||||||
def name(self):
|
# return node
|
||||||
return self[0]
|
#
|
||||||
|
# return Parser.allOf(
|
||||||
@name.setter
|
# Parser.optional(Parser.oneOf(
|
||||||
def name(self, value):
|
# TypeNode.parse,
|
||||||
self[0] = value
|
# TypeSpecifier.parse
|
||||||
|
# )),
|
||||||
@property
|
# Parser.doAssert(IdentifierNode.identifierParser(), "variable name"),
|
||||||
def arguments(self):
|
# Parser.optional(Parser.terminalParser(TokenType.DOTS, lambda val, pos: VarargNode(pos))),
|
||||||
return self[1]
|
# createNode=createNode
|
||||||
|
# )
|
||||||
@arguments.setter
|
#
|
||||||
def arguments(self, value):
|
# @classmethod
|
||||||
self[1] = value
|
# def _parse(cls, input):
|
||||||
|
# #TODO
|
||||||
@property
|
# raise RuntimeError("Not implemented yet. There is still required work to correctly build AST related to IdentifierNode")
|
||||||
def body(self):
|
#
|
||||||
return self[2]
|
#
|
||||||
|
#
|
||||||
@body.setter
|
# class FunctionDefinitionNode(StatementNode):
|
||||||
def body(self, value):
|
# def __init__(self, pos):
|
||||||
self[2] = value
|
# super().__init__(pos)
|
||||||
|
# self.children = [NoneNode(), NoneNode(), NoneNode()]
|
||||||
@classmethod
|
#
|
||||||
def withValues(cls, name, arguments, body):
|
# @property
|
||||||
node = cls(name.pos)
|
# def name(self):
|
||||||
node.name = name
|
# return self[0]
|
||||||
node.arguments = arguments
|
#
|
||||||
node.body = body
|
# @name.setter
|
||||||
return node
|
# def name(self, value):
|
||||||
|
# self[0] = value
|
||||||
|
#
|
||||||
def ArgumentParser(input):
|
# @property
|
||||||
def createNode(type, variable, vararg):
|
# def arguments(self):
|
||||||
pos = type.pos if isinstance(type, Type) else variable.pos
|
# return self[1]
|
||||||
node = Argument(pos)
|
#
|
||||||
node.type = type
|
# @arguments.setter
|
||||||
node.variable = variable
|
# def arguments(self, value):
|
||||||
node.vararg = vararg is True
|
# self[1] = value
|
||||||
return node
|
#
|
||||||
|
# @property
|
||||||
return Parser.allOf(
|
# def body(self):
|
||||||
Parser.optional(TypeParser),
|
# return self[2]
|
||||||
Parser.doAssert(IdentifierLiteralParser, "argument name"),
|
#
|
||||||
Parser.optional(Parser.terminal(TokenType.DOTS, lambda val, pos: True)),
|
# @body.setter
|
||||||
createNode=createNode,
|
# def body(self, value):
|
||||||
name="function argument"
|
# self[2] = value
|
||||||
)(input)
|
#
|
||||||
|
# @classmethod
|
||||||
|
# def _parse(cls, input):
|
||||||
def ArgumentsDeclarationParser(input):
|
# def createNode(function, name, arguments, body):
|
||||||
return abstractIterableParser(
|
# node = FunctionDefinitionNode(function.pos)
|
||||||
ArgumentsDeclaration,
|
# node.name = name
|
||||||
TokenType.OPEN_PAREN,
|
# node.arguments = arguments
|
||||||
TokenType.CLOSE_PAREN,
|
# node.body = body
|
||||||
Parser.doAssert(ArgumentParser, "function/method argument")
|
# return node
|
||||||
)(input)
|
#
|
||||||
|
# return Parser.allOf(
|
||||||
|
# Parser.terminalParser(TokenType.FUNCTION),
|
||||||
def FunctionDefinitionParser(input):
|
# Parser.doAssert(IdentifierNode.identifierParser(), "function name"),
|
||||||
return Parser.allOf(
|
# Parser.doAssert(cls._argumentsDeclarationParser(), "arguments list"),
|
||||||
Parser.terminal(TokenType.FUNCTION),
|
# Parser.doAssert(BlockNode.parse, "function body"),
|
||||||
Parser.doAssert(IdentifierLiteralParser, "function/method name"),
|
# createNode=createNode
|
||||||
Parser.doAssert(ArgumentsDeclarationParser, "function/method arguments"),
|
# )(input)
|
||||||
Parser.doAssert(BlockParser, "function/method body"),
|
#
|
||||||
createNode=lambda _, name, args, body: FunctionDefinition.withValues(name, args, body),
|
# @staticmethod
|
||||||
name="function definition"
|
# def _argumentsDeclarationParser():
|
||||||
)(input)
|
# return abstractIterableParser(ArgumentsDeclarationNode, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN, ArgumentDefinitionNode.parser())
|
||||||
|
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
from smnp.ast.node.atom import Atom
|
from smnp.ast.node.atom import Atom
|
||||||
from smnp.ast.node.expression import ExpressionParser
|
|
||||||
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.operator import BinaryOperator, Operator
|
from smnp.ast.node.operator import BinaryOperator, Operator
|
||||||
from smnp.ast.parser import Parser
|
from smnp.ast.parser import Parsers
|
||||||
from smnp.token.type import TokenType
|
from smnp.token.type import TokenType
|
||||||
|
from smnp.util.singleton import SingletonParser
|
||||||
|
|
||||||
|
|
||||||
class Identifier(Atom):
|
class Identifier(Atom):
|
||||||
@@ -49,26 +48,28 @@ class Assignment(BinaryOperator):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def IdentifierLiteralParser(input):
|
@SingletonParser
|
||||||
return Parser.terminal(TokenType.IDENTIFIER, createNode=Identifier.withValue)(input)
|
def IdentifierParser():
|
||||||
|
identifierLiteralParser = Parsers.terminal(TokenType.IDENTIFIER, createNode=Identifier.withValue)
|
||||||
|
|
||||||
|
functionCallParser = Parsers.allOf(
|
||||||
def IdentifierParser(input):
|
identifierLiteralParser,
|
||||||
functionCallParser = Parser.allOf(
|
#abstractIterableParser(ArgumentsList, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN, MaxPrecedenceExpressionParser),
|
||||||
IdentifierLiteralParser,
|
createNode=lambda name, arguments: FunctionCall.withChildren(name, arguments),
|
||||||
abstractIterableParser(ArgumentsList, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN, Parser.doAssert(ExpressionParser, "expression")),
|
name="functionCall"
|
||||||
createNode=lambda name, arguments: FunctionCall.withChildren(name, arguments)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
assignmentParser = Parser.allOf(
|
assignmentParser = Parsers.allOf(
|
||||||
IdentifierLiteralParser,
|
identifierLiteralParser,
|
||||||
Parser.terminal(TokenType.ASSIGN, createNode=Operator.withValue),
|
Parsers.terminal(TokenType.ASSIGN, createNode=Operator.withValue),
|
||||||
Parser.doAssert(ExpressionParser, "expression"),
|
#MaxPrecedenceExpressionParser,
|
||||||
createNode=lambda identifier, assign, expr: Assignment.withValues(identifier, assign, expr)
|
createNode=lambda identifier, assign, expr: Assignment.withValues(identifier, assign, expr),
|
||||||
|
name="assignment"
|
||||||
)
|
)
|
||||||
|
|
||||||
return Parser.oneOf(
|
return Parsers.oneOf(
|
||||||
assignmentParser,
|
assignmentParser,
|
||||||
functionCallParser,
|
functionCallParser,
|
||||||
IdentifierLiteralParser
|
identifierLiteralParser,
|
||||||
)(input)
|
name="idExpr"
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
|
# from smnp.ast.node.identifier import Identifier
|
||||||
|
# from smnp.ast.node.model import Node
|
||||||
|
# from smnp.ast.node.none import NoneNode
|
||||||
|
# from smnp.ast.node.string import StringLiteralNode
|
||||||
|
# from smnp.ast.node.type import TypeNode
|
||||||
|
# from smnp.ast.parser import Parser
|
||||||
|
# from smnp.token.type import TokenType
|
||||||
|
#
|
||||||
from smnp.ast.node.atom import StringParser
|
from smnp.ast.node.atom import StringParser
|
||||||
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
|
||||||
@@ -26,8 +34,8 @@ class Import(Node):
|
|||||||
|
|
||||||
def ImportParser(input):
|
def ImportParser(input):
|
||||||
return Parser.allOf(
|
return Parser.allOf(
|
||||||
Parser.terminal(TokenType.IMPORT),
|
Parser.terminalParser(TokenType.IMPORT),
|
||||||
Parser.doAssert(StringParser, "import source as string"),
|
StringParser,
|
||||||
createNode=lambda imp, source: Import.withValue(source),
|
createNode=lambda imp, source: Import.withValue(source),
|
||||||
name="import"
|
name="import"
|
||||||
)(input)
|
)(input)
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
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 Parser
|
from smnp.ast.parser import Parsers, DecoratorParser
|
||||||
from smnp.token.type import TokenType
|
from smnp.token.type import TokenType
|
||||||
|
|
||||||
|
|
||||||
def abstractIterableParser(iterableNodeType, openTokenType, closeTokenType, itemParser):
|
def abstractIterableParser(iterableNodeType, openTokenType, closeTokenType, itemParser, name):
|
||||||
|
|
||||||
class AbstractIterable(Node):
|
class AbstractIterable(Node):
|
||||||
def __init__(self, pos):
|
def __init__(self, pos):
|
||||||
@@ -31,70 +31,74 @@ def abstractIterableParser(iterableNodeType, openTokenType, closeTokenType, item
|
|||||||
class AbstractIterableTail(AbstractIterable):
|
class AbstractIterableTail(AbstractIterable):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def abstractIterableParser(input):
|
def abstractIterableParser():
|
||||||
return Parser.oneOf(
|
return Parsers.oneOf(
|
||||||
emptyIterable,
|
emptyIterable(),
|
||||||
openIterable
|
openIterable(),
|
||||||
)(input)
|
name=name
|
||||||
|
)
|
||||||
|
|
||||||
def emptyIterable(input):
|
def emptyIterable():
|
||||||
def createNode(open, close):
|
def createNode(open, close):
|
||||||
node = AbstractIterable(open.pos)
|
node = AbstractIterable(open.pos)
|
||||||
node.value = open
|
node.value = open
|
||||||
node.next = close
|
node.next = close
|
||||||
return node
|
return node
|
||||||
|
|
||||||
return Parser.allOf(
|
return Parsers.allOf(
|
||||||
Parser.terminal(openTokenType),
|
Parsers.terminal(openTokenType),
|
||||||
Parser.terminal(closeTokenType),
|
Parsers.terminal(closeTokenType),
|
||||||
createNode=createNode
|
createNode=createNode,
|
||||||
)(input)
|
name=name+"Empty"
|
||||||
|
)
|
||||||
|
|
||||||
def openIterable(input):
|
def openIterable():
|
||||||
def createNode(open, item, tail):
|
def createNode(open, item, tail):
|
||||||
node = AbstractIterable(open.pos)
|
node = AbstractIterable(open.pos)
|
||||||
node.value = item
|
node.value = item
|
||||||
node.next = tail
|
node.next = tail
|
||||||
return node
|
return node
|
||||||
|
|
||||||
return Parser.allOf(
|
return Parsers.allOf(
|
||||||
Parser.terminal(openTokenType),
|
Parsers.terminal(openTokenType),
|
||||||
itemParser,
|
itemParser,
|
||||||
abstractIterableTailParser,
|
abstractIterableTailParser(),
|
||||||
createNode=createNode
|
createNode=createNode,
|
||||||
)(input)
|
name=name+"Open"
|
||||||
|
)
|
||||||
|
|
||||||
def abstractIterableTailParser(input):
|
def abstractIterableTailParser():
|
||||||
return Parser.oneOf(
|
return Parsers.oneOf(
|
||||||
closeIterable,
|
closeIterable(),
|
||||||
nextItem,
|
nextItem(),
|
||||||
)(input)
|
name=name+"Tail"
|
||||||
|
)
|
||||||
|
|
||||||
def nextItem(input):
|
def nextItem():
|
||||||
def createNode(comma, item, tail):
|
def createNode(comma, item, tail):
|
||||||
node = AbstractIterableTail(item.pos)
|
node = AbstractIterableTail(item.pos)
|
||||||
node.value = item
|
node.value = item
|
||||||
node.next = tail
|
node.next = tail
|
||||||
return node
|
return node
|
||||||
|
|
||||||
return Parser.allOf(
|
return Parsers.allOf(
|
||||||
Parser.doAssert(Parser.terminal(TokenType.COMMA), f"'{TokenType.COMMA.key}' or '{closeTokenType.key}'"),
|
Parsers.terminal(TokenType.COMMA, doAssert=True),
|
||||||
itemParser,
|
itemParser,
|
||||||
abstractIterableTailParser,
|
abstractIterableTailParser(),
|
||||||
|
name=name+"NextItem",
|
||||||
createNode=createNode
|
createNode=createNode
|
||||||
)(input)
|
)
|
||||||
|
|
||||||
def closeIterable(input):
|
def closeIterable():
|
||||||
return Parser.terminal(closeTokenType)(input)
|
return Parsers.terminal(closeTokenType)
|
||||||
|
|
||||||
|
|
||||||
return toFlatDesiredNode(iterableNodeType, abstractIterableParser)
|
return abstractIterableParser()
|
||||||
|
#return toFlatDesiredNode(iterableNodeType, abstractIterableParser())
|
||||||
|
|
||||||
|
|
||||||
def toFlatDesiredNode(iterableNodeType, parser):
|
def toFlatDesiredNode(iterableNodeType, parser):
|
||||||
def parse(input):
|
def wrapper(result):
|
||||||
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)
|
||||||
@@ -105,7 +109,7 @@ def toFlatDesiredNode(iterableNodeType, parser):
|
|||||||
|
|
||||||
return ParseResult.FAIL()
|
return ParseResult.FAIL()
|
||||||
|
|
||||||
return Parser(parse, "flat", [parser])
|
return DecoratorParser(wrapper, parser)
|
||||||
|
|
||||||
|
|
||||||
def flattenList(node, output=None):
|
def flattenList(node, output=None):
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
from smnp.ast.node.atom import AtomParser
|
||||||
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.parser import Parser
|
|
||||||
from smnp.token.type import TokenType
|
from smnp.token.type import TokenType
|
||||||
|
|
||||||
|
|
||||||
@@ -8,12 +8,6 @@ class List(Node):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def ListParser(input):
|
def ListParser():
|
||||||
from smnp.ast.node.expression import ExpressionParser
|
return abstractIterableParser(List, TokenType.OPEN_SQUARE, TokenType.CLOSE_SQUARE, AtomParser(), name="list")
|
||||||
|
#MaxPrecedenceExpressionParser)(input)
|
||||||
return abstractIterableParser(
|
|
||||||
List,
|
|
||||||
TokenType.OPEN_SQUARE,
|
|
||||||
TokenType.CLOSE_SQUARE,
|
|
||||||
Parser.doAssert(ExpressionParser, "expression")
|
|
||||||
)(input)
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
from smnp.ast.node.atom import LiteralParser
|
|
||||||
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.operator import BinaryOperator, Operator
|
from smnp.ast.node.operator import BinaryOperator, Operator
|
||||||
from smnp.ast.parser import Parser
|
from smnp.ast.parser import Parsers
|
||||||
from smnp.token.type import TokenType
|
from smnp.token.type import TokenType
|
||||||
|
|
||||||
|
|
||||||
@@ -30,21 +29,19 @@ class Map(Node):
|
|||||||
|
|
||||||
|
|
||||||
def MapParser(input):
|
def MapParser(input):
|
||||||
from smnp.ast.node.expression import ExpressionParser
|
from smnp.ast.node.atom import LiteralParser
|
||||||
|
#from smnp.ast.node.expression import MaxPrecedenceExpressionParser
|
||||||
keyParser = LiteralParser
|
keyParser = LiteralParser
|
||||||
valueParser = ExpressionParser
|
#valueParser = MaxPrecedenceExpressionParser
|
||||||
|
|
||||||
mapEntryParser = Parser.allOf(
|
mapEntryParser = Parsers.allOf(
|
||||||
keyParser,
|
keyParser,
|
||||||
Parser.terminal(TokenType.ARROW, createNode=Operator.withValue, doAssert=True),
|
Parsers.terminal(TokenType.ARROW, createNode=Operator.withValue),
|
||||||
Parser.doAssert(valueParser, "expression"),
|
#valueParser,
|
||||||
createNode=MapEntry.withValues
|
createNode=MapEntry.withValues,
|
||||||
|
name="mapEntry"
|
||||||
)
|
)
|
||||||
|
|
||||||
return abstractIterableParser(
|
return abstractIterableParser(Map, TokenType.OPEN_CURLY, TokenType.CLOSE_CURLY, mapEntryParser)
|
||||||
Map,
|
|
||||||
TokenType.OPEN_CURLY,
|
|
||||||
TokenType.CLOSE_CURLY,
|
|
||||||
mapEntryParser
|
|
||||||
)(input)
|
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,21 @@ class Node:
|
|||||||
def pop(self, index):
|
def pop(self, index):
|
||||||
return self.children.pop(index)
|
return self.children.pop(index)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _parse(cls, input):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def parse(cls, input):
|
||||||
|
result = cls._parse(input)
|
||||||
|
if result is None:
|
||||||
|
return ParseResult.FAIL()
|
||||||
|
|
||||||
|
if not isinstance(result, ParseResult):
|
||||||
|
raise RuntimeError(f"_parse() method of '{cls.__name__}' class haven't returned ParseResult object")
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
def print(self):
|
def print(self):
|
||||||
self._print(first=True)
|
self._print(first=True)
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,68 @@ class BinaryOperator(Node):
|
|||||||
node.right = right
|
node.right = right
|
||||||
return node
|
return node
|
||||||
|
|
||||||
|
#
|
||||||
|
# class LeftAssociativeOperatorNode(ExpressionNode):
|
||||||
|
# def __init__(self, pos):
|
||||||
|
# super().__init__(pos)
|
||||||
|
# self.children = [NoneNode(), NoneNode(), NoneNode()]
|
||||||
|
#
|
||||||
|
# @property
|
||||||
|
# def left(self):
|
||||||
|
# return self[0]
|
||||||
|
#
|
||||||
|
# @left.setter
|
||||||
|
# def left(self, value):
|
||||||
|
# self[0] = value
|
||||||
|
#
|
||||||
|
# @property
|
||||||
|
# def operator(self):
|
||||||
|
# return self[1]
|
||||||
|
#
|
||||||
|
# @operator.setter
|
||||||
|
# def operator(self, value):
|
||||||
|
# self[1] = value
|
||||||
|
#
|
||||||
|
# @property
|
||||||
|
# def right(self):
|
||||||
|
# return self[2]
|
||||||
|
#
|
||||||
|
# @right.setter
|
||||||
|
# def right(self, value):
|
||||||
|
# self[2] = value
|
||||||
|
#
|
||||||
|
# @classmethod
|
||||||
|
# def _parse(cls, input):
|
||||||
|
# def createNode(left, operator, right):
|
||||||
|
# node = LeftAssociativeOperatorNode(right.pos)
|
||||||
|
# node.left = left
|
||||||
|
# node.operator = operator
|
||||||
|
# node.right = right
|
||||||
|
# return node
|
||||||
|
#
|
||||||
|
# return Parser.leftAssociativeOperatorParser(
|
||||||
|
# cls._lhsParser(),
|
||||||
|
# TokenType.DOT,
|
||||||
|
# cls._rhsParser(),
|
||||||
|
# createNode=createNode
|
||||||
|
# )(input)
|
||||||
|
#
|
||||||
|
# @classmethod
|
||||||
|
# def _lhsParser(cls):
|
||||||
|
# raise RuntimeError(f"LHS parser is not implemented in {cls.__name__}")
|
||||||
|
#
|
||||||
|
# @staticmethod
|
||||||
|
# def _rhsParser():
|
||||||
|
# from smnp.ast.node.identifier import IdentifierNode
|
||||||
|
#
|
||||||
|
# return Parser.oneOf(
|
||||||
|
# # TODO!!!
|
||||||
|
# IdentifierNode._lhsParser(),
|
||||||
|
# IdentifierNode._functionCallParser(),
|
||||||
|
# exception=lambda input: SyntaxException(f"Expected property name or method call, found '{input.current().rawValue}'", input.currentPos())
|
||||||
|
# )
|
||||||
|
#
|
||||||
|
#
|
||||||
class Operator(Node):
|
class Operator(Node):
|
||||||
def __init__(self, pos):
|
def __init__(self, pos):
|
||||||
super().__init__(pos)
|
super().__init__(pos)
|
||||||
|
|||||||
@@ -1,36 +1,44 @@
|
|||||||
from smnp.ast.node.extend import ExtendParser
|
|
||||||
from smnp.ast.node.function import FunctionDefinitionParser
|
|
||||||
from smnp.ast.node.imports import ImportParser
|
from smnp.ast.node.imports import ImportParser
|
||||||
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 StatementParser
|
||||||
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 ProgramParser(input):
|
def parse(input):
|
||||||
def parse(input):
|
root = Program()
|
||||||
root = Program()
|
while input.hasCurrent():
|
||||||
|
result = Parser.oneOf(
|
||||||
# Start Symbol
|
# Start Symbol
|
||||||
startSymbolParser = Parser.oneOf(
|
|
||||||
ImportParser,
|
ImportParser,
|
||||||
FunctionDefinitionParser,
|
|
||||||
ExtendParser,
|
|
||||||
StatementParser,
|
StatementParser,
|
||||||
exception=lambda inp: SyntaxException(f"Invalid statement: {inp.currentToEndOfLine()}", inp.current().pos),
|
exception=RuntimeError("Nie znam tego wyrazenia")
|
||||||
name="start symbol"
|
)(input)
|
||||||
)
|
|
||||||
|
|
||||||
while input.hasCurrent():
|
if result.result:
|
||||||
result = startSymbolParser(input)
|
root.append(result.node)
|
||||||
|
|
||||||
if result.result:
|
return ParseResult.OK(root)
|
||||||
root.append(result.node)
|
|
||||||
|
|
||||||
return ParseResult.OK(root)
|
ProgramParser = Parser(parse, name="program")
|
||||||
|
# @classmethod
|
||||||
return Parser(parse, name="program")(input)
|
# 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)
|
||||||
@@ -1,17 +1,32 @@
|
|||||||
from smnp.ast.node.expression import ExpressionParser
|
# from smnp.ast.node.expression import ExpressionNode
|
||||||
from smnp.ast.node.valuable import Valuable
|
# from smnp.ast.node.none import NoneNode
|
||||||
from smnp.ast.parser import Parser
|
# from smnp.ast.node.statement import StatementNode
|
||||||
from smnp.token.type import TokenType
|
# from smnp.ast.parser import Parser
|
||||||
|
# from smnp.token.type import TokenType
|
||||||
|
#
|
||||||
class Return(Valuable):
|
#
|
||||||
pass
|
# class ReturnNode(StatementNode):
|
||||||
|
# def __init__(self, pos):
|
||||||
|
# super().__init__(pos)
|
||||||
def ReturnParser(input):
|
# self.children.append(NoneNode())
|
||||||
return Parser.allOf(
|
#
|
||||||
Parser.terminal(TokenType.RETURN),
|
# @property
|
||||||
Parser.optional(ExpressionParser),
|
# def value(self):
|
||||||
createNode=lambda ret, val: Return.withValue(val, ret.pos),
|
# return self[0]
|
||||||
name="return"
|
#
|
||||||
)(input)
|
# @value.setter
|
||||||
|
# def value(self, value):
|
||||||
|
# self[0] = value
|
||||||
|
#
|
||||||
|
# @classmethod
|
||||||
|
# def _parse(cls, input):
|
||||||
|
# def createNode(ret, value):
|
||||||
|
# node = ReturnNode(ret.pos)
|
||||||
|
# node.value = value
|
||||||
|
# return node
|
||||||
|
#
|
||||||
|
# return Parser.allOf(
|
||||||
|
# Parser.terminalParser(TokenType.RETURN),
|
||||||
|
# Parser.doAssert(ExpressionNode.parse, "expression"),
|
||||||
|
# createNode=createNode
|
||||||
|
# )(input)
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
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
|
||||||
|
|
||||||
@@ -9,13 +10,25 @@ class Statement(Node):
|
|||||||
def StatementParser(input):
|
def StatementParser(input):
|
||||||
from smnp.ast.node.block import BlockParser
|
from smnp.ast.node.block import BlockParser
|
||||||
from smnp.ast.node.condition import IfElseStatementParser
|
from smnp.ast.node.condition import IfElseStatementParser
|
||||||
from smnp.ast.node.expression import ExpressionParser
|
|
||||||
|
|
||||||
from smnp.ast.node.ret import ReturnParser
|
parser = Parser.oneOf(
|
||||||
return Parser.oneOf(
|
|
||||||
IfElseStatementParser,
|
IfElseStatementParser,
|
||||||
ExpressionParser,
|
|
||||||
BlockParser,
|
BlockParser,
|
||||||
ReturnParser,
|
MaxPrecedenceExpressionParser
|
||||||
name="statement"
|
)
|
||||||
)(input)
|
|
||||||
|
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)
|
||||||
@@ -1,17 +1,12 @@
|
|||||||
from smnp.ast.node.factor import FactorParser
|
from smnp.ast.node.factor import FactorParser
|
||||||
from smnp.ast.node.operator import BinaryOperator
|
from smnp.ast.node.operator import BinaryOperator
|
||||||
|
from smnp.ast.node.valuable import Valuable
|
||||||
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 Product(BinaryOperator):
|
class Term(Valuable):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
TermParser = Parser.leftAssociativeOperatorParser(FactorParser, [TokenType.ASTERISK, TokenType.SLASH], FactorParser,
|
||||||
def TermParser(input):
|
lambda left, op, right: Term.withValue(BinaryOperator.withValues(left, op, right)))
|
||||||
return Parser.leftAssociativeOperatorParser(
|
|
||||||
FactorParser,
|
|
||||||
[TokenType.ASTERISK, TokenType.SLASH],
|
|
||||||
FactorParser,
|
|
||||||
lambda left, op, right: Product.withValues(left, op, right)
|
|
||||||
)(input)
|
|
||||||
@@ -1,67 +1,63 @@
|
|||||||
from smnp.ast.node.atom import TypeLiteralParser
|
# 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.operator import LeftAssociativeOperatorNode
|
||||||
from smnp.ast.node.none import NoneNode
|
# 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
|
||||||
|
#
|
||||||
|
#
|
||||||
class Type(Node):
|
# class TypeSpecifier(Node):
|
||||||
def __init__(self, pos):
|
#
|
||||||
super().__init__(pos)
|
# @classmethod
|
||||||
self.children = [NoneNode(), NoneNode()]
|
# def _parse(cls, input):
|
||||||
|
# return abstractIterableParser(TypeSpecifier, TokenType.OPEN_ANGLE, TokenType.CLOSE_ANGLE,
|
||||||
@property
|
# Parser.doAssert(cls._specifierItem(), "type"))(input)
|
||||||
def type(self):
|
#
|
||||||
return self[0]
|
# @classmethod
|
||||||
|
# def _specifierItem(cls):
|
||||||
@type.setter
|
# return Parser.oneOf(
|
||||||
def type(self, value):
|
# TypeNode.parse,
|
||||||
self[0] = value
|
# cls.parse
|
||||||
|
# )
|
||||||
@property
|
#
|
||||||
def specifiers(self):
|
# class TypeSpecifiers(Node):
|
||||||
return self[1]
|
# pass
|
||||||
|
#
|
||||||
@specifiers.setter
|
#
|
||||||
def specifiers(self, value):
|
# class TypeNode(LeftAssociativeOperatorNode):
|
||||||
self[1] = value
|
# def __init__(self, pos):
|
||||||
|
# super().__init__(pos)
|
||||||
@classmethod
|
#
|
||||||
def withValues(cls, pos, type, specifiers=NoneNode()):
|
# @property
|
||||||
node = cls(pos)
|
# def type(self):
|
||||||
node.type = type
|
# return self[0]
|
||||||
node.specifiers = specifiers
|
#
|
||||||
return node
|
# @type.setter
|
||||||
|
# def type(self, value):
|
||||||
|
# self[0] = value
|
||||||
class TypesList(Node):
|
#
|
||||||
pass
|
# @property
|
||||||
|
# def specifiers(self):
|
||||||
|
# return self[1]
|
||||||
def TypesListParser(input):
|
#
|
||||||
return abstractIterableParser(
|
# @specifiers.setter
|
||||||
TypesList,
|
# def specifiers(self, value):
|
||||||
TokenType.OPEN_ANGLE,
|
# self[1] = value
|
||||||
TokenType.CLOSE_ANGLE,
|
#
|
||||||
TypeParser
|
# @classmethod
|
||||||
)(input)
|
# def _parse(cls, input):
|
||||||
|
# def createNode(type, specifiers):
|
||||||
|
# node = TypeNode(type.pos)
|
||||||
class TypeSpecifiers(Node):
|
# node.type = Type[type.value.upper()]
|
||||||
pass
|
# node.specifiers = specifiers
|
||||||
|
# return node
|
||||||
|
#
|
||||||
def TypeParser(input):
|
# return Parser.allOf(
|
||||||
typeWithSpecifier = Parser.allOf(
|
# cls._rawTypeParser(),
|
||||||
TypeLiteralParser,
|
# Parser.many(TypeSpecifier.parse, lambda specifiers, pos: TypeSpecifiers.withChildren(specifiers, pos)),
|
||||||
Parser.many(TypesListParser, createNode=TypeSpecifiers.withChildren),
|
# createNode=createNode
|
||||||
createNode=lambda type, specifiers: Type.withValues(type.pos, type, specifiers),
|
# )(input)
|
||||||
name="type with specifiers?"
|
#
|
||||||
)
|
# @classmethod
|
||||||
|
# def _rawTypeParser(cls):
|
||||||
return Parser.oneOf(
|
# return Parser.terminalParser(TokenType.TYPE, lambda val, pos: TypeNode.withValue(val, pos))
|
||||||
typeWithSpecifier,
|
|
||||||
TypesListParser,
|
|
||||||
name="mult. types or type with specifier"
|
|
||||||
)(input)
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
from smnp.ast.node.atom import AtomParser
|
|
||||||
from smnp.ast.node.operator import BinaryOperator, UnaryOperator, Operator
|
|
||||||
from smnp.ast.parser import Parser
|
|
||||||
from smnp.token.type import TokenType
|
|
||||||
|
|
||||||
|
|
||||||
class MinusOperator(UnaryOperator):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class Access(BinaryOperator):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def UnitParser(input):
|
|
||||||
minusOperator = Parser.allOf(
|
|
||||||
Parser.terminal(TokenType.MINUS, createNode=Operator.withValue),
|
|
||||||
Parser.doAssert(AtomParser, "atom"),
|
|
||||||
createNode=MinusOperator.withValues,
|
|
||||||
name="minus"
|
|
||||||
)
|
|
||||||
|
|
||||||
atom2 = Parser.oneOf(
|
|
||||||
minusOperator,
|
|
||||||
AtomParser,
|
|
||||||
name="atom2"
|
|
||||||
)
|
|
||||||
|
|
||||||
return Parser.leftAssociativeOperatorParser(
|
|
||||||
atom2,
|
|
||||||
[TokenType.DOT],
|
|
||||||
Parser.doAssert(atom2, "atom"),
|
|
||||||
createNode=lambda left, op, right: Access.withValues(left, op, right),
|
|
||||||
name="unit"
|
|
||||||
)(input)
|
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ class Valuable(Node):
|
|||||||
self[0] = value
|
self[0] = value
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def withValue(cls, value, pos=None):
|
def withValue(cls, value):
|
||||||
node = cls(value.pos if pos is None else pos)
|
node = cls(value.pos)
|
||||||
node.value = value
|
node.value = value
|
||||||
return node
|
return node
|
||||||
@@ -9,15 +9,8 @@ def parse(input):
|
|||||||
return ProgramParser(input).node
|
return ProgramParser(input).node
|
||||||
|
|
||||||
|
|
||||||
class Parser:
|
class Parser(object):
|
||||||
def __init__(self, parse, name=None, parsers=None):
|
def __init__(self, name):
|
||||||
if parsers is None:
|
|
||||||
parsers = []
|
|
||||||
self.parsers = parsers
|
|
||||||
|
|
||||||
self._parse = parse
|
|
||||||
if name is None:
|
|
||||||
name = parse.__name__
|
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
def parse(self, input):
|
def parse(self, input):
|
||||||
@@ -26,10 +19,27 @@ class Parser:
|
|||||||
return ParseResult.FAIL()
|
return ParseResult.FAIL()
|
||||||
|
|
||||||
if not isinstance(result, ParseResult):
|
if not isinstance(result, ParseResult):
|
||||||
raise RuntimeError(f"_parse() method of '{self.__class__.__name__}' class haven't returned ParseResult object")
|
raise RuntimeError(
|
||||||
|
f"_parse() method of '{self.__class__.__name__}' class haven't returned ParseResult object")
|
||||||
|
|
||||||
return result
|
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):
|
def __call__(self, input):
|
||||||
return self.parse(input)
|
return self.parse(input)
|
||||||
|
|
||||||
@@ -39,186 +49,242 @@ class Parser:
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return self.__str__()
|
return self.__str__()
|
||||||
|
|
||||||
# a -> A
|
|
||||||
|
class Parsers:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def terminal(expectedType, createNode=None, doAssert=False):
|
def terminal(expectedType, createNode=lambda val, pos: IgnoredNode(pos), doAssert=False):
|
||||||
def provideNode(value, pos):
|
return TerminalParser(expectedType, createNode, doAssert)
|
||||||
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())
|
|
||||||
|
|
||||||
return ParseResult.FAIL()
|
|
||||||
|
|
||||||
return Parser(parse, name=expectedType.name.lower())
|
|
||||||
|
|
||||||
# oneOf -> a | b | c | ...
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def oneOf(*parsers, assertExpected=None, exception=None, name="or"):
|
def oneOf(*parsers, name, exception=None):
|
||||||
def combinedParser(input):
|
return OneOfParser(*parsers, name=name, exception=exception)
|
||||||
snap = input.snapshot()
|
|
||||||
for parser in parsers:
|
|
||||||
value = parser(input)
|
|
||||||
if value.result:
|
|
||||||
return value
|
|
||||||
input.reset(snap)
|
|
||||||
|
|
||||||
if assertExpected is not None:
|
|
||||||
found = f", found '{input.current().rawValue}'" if input.hasCurrent() else ""
|
|
||||||
raise SyntaxException(f"Expected {assertExpected}{found}", input.currentPos())
|
|
||||||
|
|
||||||
if exception is not None:
|
|
||||||
if callable(exception):
|
|
||||||
raise exception(input)
|
|
||||||
else:
|
|
||||||
raise exception
|
|
||||||
|
|
||||||
input.reset(snap)
|
|
||||||
return ParseResult.FAIL()
|
|
||||||
|
|
||||||
return Parser(combinedParser, name=name, parsers=parsers)
|
|
||||||
|
|
||||||
# allOf -> a b c ...
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def allOf(*parsers, createNode, exception=None, name="all"):
|
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")
|
||||||
|
|
||||||
def extendedParser(input):
|
self.parsers = parsers
|
||||||
snap = input.snapshot()
|
self.createNode = createNode
|
||||||
|
self.exception = exception
|
||||||
|
|
||||||
results = []
|
def _parse(self, input):
|
||||||
|
snap = input.snapshot()
|
||||||
|
parsedItems = []
|
||||||
|
|
||||||
for parser in parsers:
|
for parser in self.parsers:
|
||||||
result = parser(input)
|
result = parser.parse(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 Parser(extendedParser, name=name, parsers=parsers)
|
|
||||||
|
|
||||||
|
|
||||||
# leftAssociative -> left | left OP right
|
|
||||||
@staticmethod
|
|
||||||
def leftAssociativeOperatorParser(leftParser, operatorTokenTypes, rightParser, createNode, name="leftAssoc"):
|
|
||||||
from smnp.ast.node.operator import Operator
|
|
||||||
|
|
||||||
def parse(input):
|
|
||||||
operatorParser = Parser.oneOfTerminals(*operatorTokenTypes, createNode=lambda val, pos: Operator.withChildren([val], pos))
|
|
||||||
left = leftParser(input)
|
|
||||||
if left.result:
|
|
||||||
operator = operatorParser(input)
|
|
||||||
while operator.result:
|
|
||||||
right = rightParser(input)
|
|
||||||
left = ParseResult.OK(createNode(left.node, operator.node, right.node))
|
|
||||||
operator = operatorParser(input)
|
|
||||||
return left
|
|
||||||
|
|
||||||
return ParseResult.FAIL()
|
|
||||||
|
|
||||||
return Parser(parse, name=name, parsers=[leftParser, '|'.join([t.value for t in operatorTokenTypes]), rightParser])
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def oneOfTerminals(*tokenTypes, createNode=None):
|
|
||||||
return Parser.oneOf(*[Parser.terminal(expectedType, createNode=createNode) for expectedType in tokenTypes], name='|'.join([t.value for t in tokenTypes]))
|
|
||||||
|
|
||||||
# loop -> start item* end
|
|
||||||
@staticmethod
|
|
||||||
def loop(startParser, itemParser, endParser, createNode, name="loop"):
|
|
||||||
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 Parser(parse, name, parsers=[startParser, itemParser, endParser])
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def doAssert(parser, expected, name="!!"):
|
|
||||||
def parse(input):
|
|
||||||
result = parser(input)
|
|
||||||
|
|
||||||
if not result.result:
|
if not result.result:
|
||||||
found = f", found '{input.current().rawValue}'" if input.hasCurrent() else ''
|
if self.exception is not None:
|
||||||
|
if callable(self.exception):
|
||||||
|
raise self.exception(input)
|
||||||
|
else:
|
||||||
|
raise self.exception
|
||||||
|
|
||||||
raise SyntaxException(f"Expected {expected}{found}", input.currentPos())
|
input.reset(snap)
|
||||||
|
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 Parser(parse, name, parsers=parser)
|
return ParseResult.OK(NoneNode())
|
||||||
|
|
||||||
@staticmethod
|
def _grammarRules(self, output):
|
||||||
def optional(parser, name="??"):
|
output.append(f"{self.name} -> {self.parser.name}?")
|
||||||
def parse(input):
|
|
||||||
result = parser(input)
|
|
||||||
if result.result:
|
|
||||||
return result
|
|
||||||
|
|
||||||
return ParseResult.OK(NoneNode())
|
|
||||||
|
|
||||||
return Parser(parse, name, parsers=[parser])
|
class LoopParser(Parser):
|
||||||
|
def __init__(self, startParser, itemParser, endParser, createNode, name):
|
||||||
|
super().__init__(name)
|
||||||
|
self.startParser = startParser
|
||||||
|
self.itemParser = itemParser
|
||||||
|
self.endParser = endParser
|
||||||
|
self.createNode = createNode
|
||||||
|
|
||||||
@staticmethod
|
def _parse(self, input):
|
||||||
def epsilon():
|
items = []
|
||||||
return lambda *args: ParseResult.OK(NoneNode())
|
start = self.startParser.parse(input)
|
||||||
|
if start.result:
|
||||||
@staticmethod
|
|
||||||
def many(parser, createNode, name="*"):
|
|
||||||
def parse(input):
|
|
||||||
results = []
|
|
||||||
snap = input.snapshot()
|
|
||||||
pos = input.currentPos()
|
|
||||||
while True:
|
while True:
|
||||||
result = parser(input)
|
end = self.endParser.parse(input)
|
||||||
if result.result:
|
if end.result:
|
||||||
results.append(result.node)
|
return ParseResult.OK(self.createNode(start.node, items, end.node))
|
||||||
snap = input.snapshot()
|
item = self.itemParser.parse(input)
|
||||||
else:
|
if not item.result:
|
||||||
input.reset(snap)
|
return ParseResult.FAIL()
|
||||||
return ParseResult.OK(createNode(results, pos) if len(results) > 0 else NoneNode())
|
items.append(item.node)
|
||||||
|
|
||||||
return Parser(parse, name, parsers=[parser])
|
return ParseResult.FAIL()
|
||||||
|
|
||||||
@staticmethod
|
def _grammarRules(self, output):
|
||||||
def wrap(parser, createNode):
|
output.append(f"{self.name} -> {self.startParser.name} {self.itemParser.name}* {self.endParser.name}")
|
||||||
def parse(input):
|
self.startParser._grammarRules(output)
|
||||||
result = parser(input)
|
self.itemParser._grammarRules(output)
|
||||||
if result.result:
|
self.endParser._grammarRules(output)
|
||||||
return ParseResult.OK(createNode(result.node))
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
return parse
|
|
||||||
@@ -10,9 +10,6 @@ class Sound:
|
|||||||
def play(self):
|
def play(self):
|
||||||
sd.play(self.data, self.fs, blocking=True)
|
sd.play(self.data, self.fs, blocking=True)
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
return self.file == other.file and self.data == other.data
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"sound[{self.file}]"
|
return f"sound[{self.file}]"
|
||||||
|
|
||||||
|
|||||||
@@ -5,5 +5,7 @@ from smnp.program.interpreter import Interpreter
|
|||||||
|
|
||||||
def loadStandardLibrary():
|
def loadStandardLibrary():
|
||||||
mainSource = resource_string('smnp.library.code', 'main.mus').decode("utf-8")
|
mainSource = resource_string('smnp.library.code', 'main.mus').decode("utf-8")
|
||||||
|
boolSource = resource_string('smnp.library.code', 'bool.mus').decode("utf-8")
|
||||||
env = Interpreter.interpretString(mainSource)
|
env = Interpreter.interpretString(mainSource)
|
||||||
return env
|
return Interpreter.interpretString(boolSource, baseEnvironment=env)
|
||||||
|
|
||||||
|
|||||||
33
smnp/main.py
33
smnp/main.py
@@ -1,17 +1,32 @@
|
|||||||
import sys
|
from smnp.ast.node.atom import AtomParser
|
||||||
|
from smnp.ast.node.chain import ChainParser
|
||||||
|
from smnp.ast.node.list import ListParser
|
||||||
|
from smnp.ast.node.model import Node
|
||||||
from smnp.error.base import SmnpException
|
from smnp.error.base import SmnpException
|
||||||
from smnp.library.loader import loadStandardLibrary
|
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=False, printAst=False, execute=True, baseEnvironment=stdLibraryEnv)
|
# Interpreter.interpretFile(sys.argv[1], printTokens=True, printAst=True, execute=False, baseEnvironment=None)
|
||||||
#draft()
|
# draft()
|
||||||
#tokens = tokenize(['function a(b...) { x+y}'])
|
|
||||||
#FunctionDefinitionParser(tokens).node.print()
|
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,4 +1,4 @@
|
|||||||
from smnp.module.iterable.function import combine, map, range, get
|
from smnp.module.iterable.function import combine, flat, map, range, get
|
||||||
|
|
||||||
functions = [ combine.function, map.function, range.function ]
|
functions = [ combine.function, flat.function, map.function, range.function ]
|
||||||
methods = [ get.function ]
|
methods = [ get.function ]
|
||||||
23
smnp/module/iterable/function/flat.py
Normal file
23
smnp/module/iterable/function/flat.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
from smnp.function.model import Function
|
||||||
|
from smnp.function.signature import varargSignature
|
||||||
|
from smnp.type.model import Type
|
||||||
|
from smnp.type.signature.matcher.type import allTypes
|
||||||
|
|
||||||
|
_signature = varargSignature(allTypes())
|
||||||
|
def _function(env, vararg):
|
||||||
|
return Type.list(doFlat(vararg, [])).decompose()
|
||||||
|
|
||||||
|
|
||||||
|
def doFlat(input, output=None):
|
||||||
|
if output is None:
|
||||||
|
output = []
|
||||||
|
|
||||||
|
for item in input:
|
||||||
|
if item.type == Type.LIST:
|
||||||
|
doFlat(item.value, output)
|
||||||
|
else:
|
||||||
|
output.append(item)
|
||||||
|
return output
|
||||||
|
|
||||||
|
|
||||||
|
function = Function(_signature, _function, 'flat')
|
||||||
@@ -6,17 +6,17 @@ from smnp.type.signature.matcher.type import ofType
|
|||||||
|
|
||||||
_signature1 = signature(ofType(Type.INTEGER))
|
_signature1 = signature(ofType(Type.INTEGER))
|
||||||
def _function1(env, upper):
|
def _function1(env, upper):
|
||||||
return Type.list([ Type.integer(i) for i in range(upper.value + 1)])
|
return Type.list(list(range(upper.value + 1)))
|
||||||
|
|
||||||
|
|
||||||
_signature2 = signature(ofType(Type.INTEGER), ofType(Type.INTEGER))
|
_signature2 = signature(ofType(Type.INTEGER), ofType(Type.INTEGER))
|
||||||
def _function2(env, lower, upper):
|
def _function2(env, lower, upper):
|
||||||
return Type.list([ Type.integer(i) for i in range(lower.value, upper.value + 1)])
|
return Type.list(list(range(lower.value, upper.value + 1)))
|
||||||
|
|
||||||
|
|
||||||
_signature3 = signature(ofType(Type.INTEGER), ofType(Type.INTEGER), ofType(Type.INTEGER))
|
_signature3 = signature(ofType(Type.INTEGER), ofType(Type.INTEGER), ofType(Type.INTEGER))
|
||||||
def _function3(env, lower, upper, step):
|
def _function3(env, lower, upper, step):
|
||||||
return Type.list([ Type.integer(i) for i in range(lower.value, upper.value + 1, step.value)])
|
return Type.list(list(range(lower.value, upper.value + 1, step.value)))
|
||||||
|
|
||||||
|
|
||||||
_signature4 = signature(ofType(Type.NOTE), ofType(Type.NOTE))
|
_signature4 = signature(ofType(Type.NOTE), ofType(Type.NOTE))
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
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
|
||||||
|
|
||||||
|
|
||||||
@@ -18,9 +17,9 @@ class Interpreter:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _interpret(lines, printTokens=False, printAst=False, execute=True, baseEnvironment=None):
|
def _interpret(lines, printTokens=False, printAst=False, execute=True, 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)
|
||||||
@@ -31,10 +30,10 @@ class Interpreter:
|
|||||||
if printAst:
|
if printAst:
|
||||||
ast.print()
|
ast.print()
|
||||||
|
|
||||||
if execute:
|
#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,10 +1,9 @@
|
|||||||
from smnp.ast.node.block import Block
|
from smnp.ast.node.block import BlockNode
|
||||||
from smnp.ast.node.condition import IfElse
|
from smnp.ast.node.extend import ExtendNode
|
||||||
from smnp.ast.node.extend import Extend
|
from smnp.ast.node.function import FunctionDefinitionNode
|
||||||
from smnp.ast.node.function import FunctionDefinition
|
from smnp.ast.node.imports import ImportNode
|
||||||
from smnp.ast.node.imports import Import
|
|
||||||
from smnp.ast.node.program import Program
|
from smnp.ast.node.program import Program
|
||||||
from smnp.ast.node.ret import Return
|
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
|
||||||
|
|
||||||
@@ -69,27 +68,20 @@ class EvaluationResult():
|
|||||||
|
|
||||||
def evaluate(node, environment):
|
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.condition import IfElseStatementEvaluator
|
|
||||||
|
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.block import BlockEvaluator
|
||||||
from smnp.runtime.evaluators.imports import ImportEvaluator
|
from smnp.runtime.evaluators.imports import ImportEvaluator
|
||||||
from smnp.runtime.evaluators.function import FunctionDefinitionEvaluator
|
|
||||||
from smnp.runtime.evaluators.function import ReturnEvaluator
|
from smnp.runtime.evaluators.function import ReturnEvaluator
|
||||||
from smnp.runtime.evaluators.extend import ExtendEvaluator
|
|
||||||
result = Evaluator.oneOf(
|
result = Evaluator.oneOf(
|
||||||
Evaluator.forNodes(ProgramEvaluator.evaluate, Program),
|
Evaluator.forNodes(ProgramEvaluator.evaluate, Program),
|
||||||
Evaluator.forNodes(IfElseStatementEvaluator.evaluate, IfElse),
|
Evaluator.forNodes(ImportEvaluator.evaluate, ImportNode),
|
||||||
Evaluator.forNodes(BlockEvaluator.evaluate, Block),
|
Evaluator.forNodes(FunctionDefinitionEvaluator.evaluate, FunctionDefinitionNode),
|
||||||
Evaluator.forNodes(ImportEvaluator.evaluate, Import),
|
Evaluator.forNodes(ExtendEvaluator.evaluate, ExtendNode),
|
||||||
Evaluator.forNodes(FunctionDefinitionEvaluator.evaluate, FunctionDefinition),
|
Evaluator.forNodes(BlockEvaluator.evaluate, BlockNode),
|
||||||
Evaluator.forNodes(ReturnEvaluator.evaluate, Return),
|
Evaluator.forNodes(ReturnEvaluator.evaluate, ReturnNode),
|
||||||
Evaluator.forNodes(ExtendEvaluator.evaluate, Extend),
|
|
||||||
#Evaluator.forNodes(ImportEvaluator.evaluate, ImportNode),
|
|
||||||
#Evaluator.forNodes(FunctionDefinitionEvaluator.evaluate, FunctionDefinitionNode),
|
|
||||||
#Evaluator.forNodes(ExtendEvaluator.evaluate, ExtendNode),
|
|
||||||
#Evaluator.forNodes(BlockEvaluator.evaluate, BlockNode),
|
|
||||||
#Evaluator.forNodes(ReturnEvaluator.evaluate, ReturnNode),
|
|
||||||
expressionEvaluator()
|
expressionEvaluator()
|
||||||
)(node, environment)
|
)(node, environment)
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from smnp.ast.node.identifier import Identifier, FunctionCall
|
from smnp.ast.node.identifier import Identifier
|
||||||
|
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
|
||||||
from smnp.runtime.evaluators.expression import expressionEvaluator
|
from smnp.runtime.evaluators.expression import expressionEvaluator
|
||||||
@@ -19,9 +20,9 @@ class AccessEvaluator(Evaluator):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
raise RuntimeException(f"Unknown property '{right.value}' of type '{left.type.name.lower()}'", right.pos)
|
raise RuntimeException(f"Unknown property '{right.value}' of type '{left.type.name.lower()}'", right.pos)
|
||||||
|
|
||||||
if type(right) == FunctionCall:
|
if type(right) == FunctionCallNode:
|
||||||
try:
|
try:
|
||||||
arguments = abstractIterableEvaluator(expressionEvaluator(doAssert=True))(right.arguments, environment)
|
arguments = abstractIterableEvaluator(expressionEvaluator(True))(right.arguments, environment)
|
||||||
return environment.invokeMethod(left, right.name.value, arguments)
|
return environment.invokeMethod(left, right.name.value, arguments)
|
||||||
except RuntimeException as e:
|
except RuntimeException as e:
|
||||||
raise updatePos(e, right)
|
raise updatePos(e, right)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
from smnp.error.runtime import RuntimeException
|
||||||
from smnp.runtime.evaluator import Evaluator
|
from smnp.runtime.evaluator import Evaluator
|
||||||
from smnp.runtime.evaluators.expression import expressionEvaluator
|
from smnp.runtime.evaluators.expression import expressionEvaluator
|
||||||
|
|
||||||
@@ -6,8 +7,11 @@ class AssignmentEvaluator(Evaluator):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def evaluator(cls, node, environment):
|
def evaluator(cls, node, environment):
|
||||||
target = node.left.value
|
target = node.target.value
|
||||||
value = expressionEvaluator(doAssert=True)(node.right, environment).value #TODO check if it isn't necessary to verify 'result' attr of EvaluatioNResult
|
if target.startswith("_"):
|
||||||
|
raise RuntimeException("Declaration and assignation variables with names starting with '_' is not allowed", node.target.pos)
|
||||||
|
|
||||||
|
value = expressionEvaluator(doAssert=True)(node.value, environment).value #TODO check if it isn't necessary to verify 'result' attr of EvaluatioNResult
|
||||||
scopeOfExistingVariable = environment.findVariableScope(target)
|
scopeOfExistingVariable = environment.findVariableScope(target)
|
||||||
if scopeOfExistingVariable is None:
|
if scopeOfExistingVariable is None:
|
||||||
environment.scopes[-1][target] = value
|
environment.scopes[-1][target] = value
|
||||||
|
|||||||
@@ -1,94 +0,0 @@
|
|||||||
from smnp.ast.node.atom import StringLiteral, IntegerLiteral, NoteLiteral, BoolLiteral, TypeLiteral
|
|
||||||
from smnp.ast.node.identifier import Identifier
|
|
||||||
from smnp.ast.node.list import List
|
|
||||||
from smnp.ast.node.map import Map
|
|
||||||
from smnp.error.runtime import RuntimeException
|
|
||||||
from smnp.runtime.evaluator import Evaluator
|
|
||||||
from smnp.runtime.evaluators.expression import expressionEvaluator
|
|
||||||
from smnp.runtime.evaluators.iterable import abstractIterableEvaluator
|
|
||||||
from smnp.runtime.tools.error import updatePos
|
|
||||||
from smnp.type.model import Type
|
|
||||||
|
|
||||||
|
|
||||||
class IntegerEvaluator(Evaluator):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def evaluator(cls, node, environment):
|
|
||||||
return Type.integer(node.value)
|
|
||||||
|
|
||||||
|
|
||||||
class StringEvaluator(Evaluator):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def evaluator(cls, node, environment):
|
|
||||||
return Type.string(node.value)
|
|
||||||
|
|
||||||
|
|
||||||
class NoteEvaluator(Evaluator):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def evaluator(cls, node, environment):
|
|
||||||
return Type.note(node.value)
|
|
||||||
|
|
||||||
|
|
||||||
class BoolEvaluator(Evaluator):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def evaluator(cls, node, environment):
|
|
||||||
return Type.bool(node.value)
|
|
||||||
|
|
||||||
|
|
||||||
class TypeEvaluator(Evaluator):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def evaluator(cls, node, environment):
|
|
||||||
return Type.type(node.value)
|
|
||||||
|
|
||||||
|
|
||||||
class ListEvaluator(Evaluator):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def evaluator(cls, node, environment):
|
|
||||||
list = abstractIterableEvaluator(expressionEvaluator(doAssert=True))(node, environment)
|
|
||||||
return Type.list(list)
|
|
||||||
|
|
||||||
|
|
||||||
class MapEvaluator(Evaluator):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def evaluator(cls, node, environment):
|
|
||||||
map = {}
|
|
||||||
exprEvaluator = expressionEvaluator(doAssert=True)
|
|
||||||
for entry in node.children:
|
|
||||||
key = exprEvaluator(entry.key, environment).value
|
|
||||||
if key in map:
|
|
||||||
raise RuntimeException(f"Duplicated key '{key.stringify()}' found in map", entry.pos)
|
|
||||||
map[key] = exprEvaluator(entry.value, environment).value
|
|
||||||
|
|
||||||
return Type.map(map)
|
|
||||||
|
|
||||||
|
|
||||||
class IdentifierEvaluator(Evaluator):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def evaluator(cls, node, environment):
|
|
||||||
try:
|
|
||||||
return environment.findVariable(node.value)
|
|
||||||
except RuntimeException as e:
|
|
||||||
raise updatePos(e, node)
|
|
||||||
|
|
||||||
|
|
||||||
class AtomEvaluator(Evaluator):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def evaluator(cls, node, environment):
|
|
||||||
return Evaluator.oneOf(
|
|
||||||
Evaluator.forNodes(StringEvaluator.evaluate, StringLiteral),
|
|
||||||
Evaluator.forNodes(IntegerEvaluator.evaluate, IntegerLiteral),
|
|
||||||
Evaluator.forNodes(NoteEvaluator.evaluate, NoteLiteral),
|
|
||||||
Evaluator.forNodes(BoolEvaluator.evaluate, BoolLiteral),
|
|
||||||
Evaluator.forNodes(TypeEvaluator.evaluate, TypeLiteral),
|
|
||||||
Evaluator.forNodes(IdentifierEvaluator.evaluate, Identifier),
|
|
||||||
Evaluator.forNodes(ListEvaluator.evaluate, List),
|
|
||||||
Evaluator.forNodes(MapEvaluator.evaluate, Map)
|
|
||||||
)(node, environment).value
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
from smnp.error.runtime import RuntimeException
|
|
||||||
from smnp.runtime.evaluator import Evaluator, evaluate
|
|
||||||
from smnp.runtime.evaluators.expression import expressionEvaluator
|
|
||||||
from smnp.type.model import Type
|
|
||||||
|
|
||||||
|
|
||||||
class IfElseEvaluator(Evaluator):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def evaluator(cls, node, environment):
|
|
||||||
condition = expressionEvaluator(doAssert=True)(node.condition, environment).value
|
|
||||||
|
|
||||||
if condition.type != Type.BOOL:
|
|
||||||
raise RuntimeException(f"Only {Type.BOOL.name.lower()} types can be used as conditions in conditional expression", node.condition.pos)
|
|
||||||
|
|
||||||
if condition.value:
|
|
||||||
return expressionEvaluator(doAssert=True)(node.ifNode, environment).value
|
|
||||||
else:
|
|
||||||
return expressionEvaluator(doAssert=True)(node.elseNode, environment).value
|
|
||||||
|
|
||||||
|
|
||||||
class IfElseStatementEvaluator(Evaluator):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def evaluator(cls, node, environment):
|
|
||||||
condition = expressionEvaluator(doAssert=True)(node.condition, environment).value
|
|
||||||
|
|
||||||
if condition.type != Type.BOOL:
|
|
||||||
raise RuntimeException(
|
|
||||||
f"Only {Type.BOOL.name.lower()} types can be used as conditions in conditional expression", node.condition.pos)
|
|
||||||
|
|
||||||
if condition.value:
|
|
||||||
evaluate(node.ifNode, environment)
|
|
||||||
else:
|
|
||||||
evaluate(node.elseNode, environment)
|
|
||||||
@@ -1,9 +1,15 @@
|
|||||||
from smnp.ast.node.condition import IfElse
|
from smnp.ast.node.assignment import AssignmentNode
|
||||||
from smnp.ast.node.expression import Sum, Relation
|
from smnp.ast.node.asterisk import AsteriskNode
|
||||||
from smnp.ast.node.factor import NotOperator, Power, Loop
|
from smnp.ast.node.bool import BoolLiteralNode
|
||||||
from smnp.ast.node.identifier import FunctionCall, Assignment
|
from smnp.ast.node.identifier import Identifier
|
||||||
from smnp.ast.node.term import Product
|
from smnp.ast.node.integer import IntegerLiteralNode
|
||||||
from smnp.ast.node.unit import MinusOperator, Access
|
from smnp.ast.node.invocation import FunctionCallNode
|
||||||
|
from smnp.ast.node.list import List
|
||||||
|
from smnp.ast.node.map import MapNode
|
||||||
|
from smnp.ast.node.note import NoteLiteralNode
|
||||||
|
from smnp.ast.node.operator import LeftAssociativeOperatorNode
|
||||||
|
from smnp.ast.node.string import StringLiteralNode
|
||||||
|
from smnp.ast.node.type import TypeNode
|
||||||
from smnp.error.runtime import RuntimeException
|
from smnp.error.runtime import RuntimeException
|
||||||
from smnp.runtime.evaluator import Evaluator
|
from smnp.runtime.evaluator import Evaluator
|
||||||
from smnp.type.model import Type
|
from smnp.type.model import Type
|
||||||
@@ -11,38 +17,38 @@ from smnp.type.model import Type
|
|||||||
|
|
||||||
def expressionEvaluator(doAssert=False):
|
def expressionEvaluator(doAssert=False):
|
||||||
def evaluateExpression(node, environment):
|
def evaluateExpression(node, environment):
|
||||||
from smnp.runtime.evaluators.function import FunctionCallEvaluator
|
from smnp.runtime.evaluators.string import StringEvaluator
|
||||||
from smnp.runtime.evaluators.minus import MinusEvaluator
|
from smnp.runtime.evaluators.integer import IntegerEvaluator
|
||||||
from smnp.runtime.evaluators.atom import AtomEvaluator
|
from smnp.runtime.evaluators.note import NoteEvaluator
|
||||||
from smnp.runtime.evaluators.access import AccessEvaluator
|
from smnp.runtime.evaluators.identifier import IdentifierEvaluator
|
||||||
from smnp.runtime.evaluators.negation import NotEvaluator
|
from smnp.runtime.evaluators.list import ListEvaluator
|
||||||
from smnp.runtime.evaluators.power import PowerEvaluator
|
from smnp.runtime.evaluators.function import FunctionCallEvaluator
|
||||||
from smnp.runtime.evaluators.loop import LoopEvaluator
|
|
||||||
from smnp.runtime.evaluators.assignment import AssignmentEvaluator
|
|
||||||
from smnp.runtime.evaluators.product import ProductEvaluator
|
|
||||||
|
|
||||||
from smnp.runtime.evaluators.sum import SumEvaluator
|
from smnp.runtime.evaluators.access import AccessEvaluator
|
||||||
from smnp.runtime.evaluators.relation import RelationEvaluator
|
from smnp.runtime.evaluators.assignment import AssignmentEvaluator
|
||||||
from smnp.runtime.evaluators.condition import IfElseEvaluator
|
from smnp.runtime.evaluators.asterisk import AsteriskEvaluator
|
||||||
result = Evaluator.oneOf(
|
from smnp.runtime.evaluators.map import MapEvaluator
|
||||||
Evaluator.forNodes(FunctionCallEvaluator.evaluate, FunctionCall),
|
from smnp.runtime.evaluators.type import TypeEvaluator
|
||||||
Evaluator.forNodes(MinusEvaluator.evaluate, MinusOperator),
|
from smnp.runtime.evaluators.bool import BoolEvaluator
|
||||||
Evaluator.forNodes(AccessEvaluator.evaluate, Access),
|
result = Evaluator.oneOf(
|
||||||
Evaluator.forNodes(NotEvaluator.evaluate, NotOperator),
|
Evaluator.forNodes(FunctionCallEvaluator.evaluate, FunctionCallNode),
|
||||||
Evaluator.forNodes(PowerEvaluator.evaluate, Power),
|
Evaluator.forNodes(StringEvaluator.evaluate, StringLiteralNode),
|
||||||
Evaluator.forNodes(LoopEvaluator.evaluate, Loop),
|
Evaluator.forNodes(IntegerEvaluator.evaluate, IntegerLiteralNode),
|
||||||
Evaluator.forNodes(AssignmentEvaluator.evaluate, Assignment),
|
Evaluator.forNodes(NoteEvaluator.evaluate, NoteLiteralNode),
|
||||||
Evaluator.forNodes(ProductEvaluator.evaluate, Product),
|
Evaluator.forNodes(BoolEvaluator.evaluate, BoolLiteralNode),
|
||||||
Evaluator.forNodes(SumEvaluator.evaluate, Sum),
|
Evaluator.forNodes(TypeEvaluator.evaluate, TypeNode),
|
||||||
Evaluator.forNodes(RelationEvaluator.evaluate, Relation),
|
Evaluator.forNodes(IdentifierEvaluator.evaluate, Identifier),
|
||||||
Evaluator.forNodes(IfElseEvaluator.evaluate, IfElse),
|
Evaluator.forNodes(ListEvaluator.evaluate, List),
|
||||||
AtomEvaluator.evaluate
|
Evaluator.forNodes(AccessEvaluator.evaluate, LeftAssociativeOperatorNode),
|
||||||
)(node, environment)
|
Evaluator.forNodes(AssignmentEvaluator.evaluate, AssignmentNode),
|
||||||
|
Evaluator.forNodes(AsteriskEvaluator.evaluate, AsteriskNode),
|
||||||
|
Evaluator.forNodes(MapEvaluator.evaluate, MapNode)
|
||||||
|
)(node, environment)
|
||||||
|
|
||||||
if doAssert and result.result and result.value.type == Type.VOID:
|
if doAssert and result.result and result.value.type == Type.VOID:
|
||||||
raise RuntimeException(f"Expected expression", node.pos)
|
raise RuntimeException(f"Expected expression", node.pos)
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
return evaluateExpression
|
return evaluateExpression
|
||||||
|
|
||||||
|
|||||||
@@ -17,11 +17,11 @@ class ExtendEvaluator(Evaluator):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def _typeToMethodSignature(cls, node):
|
def _typeToMethodSignature(cls, node):
|
||||||
if type(node.specifiers) == NoneNode:
|
if type(node.specifiers) == NoneNode:
|
||||||
return signature(ofType(node.type.value))
|
return signature(ofType(node.type))
|
||||||
|
|
||||||
elif node.type.value == Type.LIST:
|
elif node.type == Type.LIST:
|
||||||
return signature(listSpecifier(node.specifiers[0]))
|
return signature(listSpecifier(node.specifiers[0]))
|
||||||
elif node.type.value == Type.MAP:
|
elif node.type == Type.MAP:
|
||||||
return signature(mapSpecifier(node.specifiers[0], node.specifiers[1]))
|
return signature(mapSpecifier(node.specifiers[0], node.specifiers[1]))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
from smnp.ast.node.none import NoneNode
|
||||||
from smnp.program.interpreter import Interpreter
|
from smnp.program.interpreter import Interpreter
|
||||||
from smnp.runtime.evaluator import Evaluator
|
from smnp.runtime.evaluator import Evaluator
|
||||||
|
|
||||||
@@ -6,6 +7,13 @@ class ImportEvaluator(Evaluator):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def evaluator(cls, node, environment):
|
def evaluator(cls, node, environment):
|
||||||
|
if type(node.type) == NoneNode:
|
||||||
|
cls._evaluateCodeImport(node, environment)
|
||||||
|
else:
|
||||||
|
raise RuntimeError("Importing types is not implemented yet")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _evaluateCodeImport(cls, node, environment):
|
||||||
source = node.source
|
source = node.source
|
||||||
newEnvironment = Interpreter.interpretFile(source.value, baseEnvironment=environment)
|
newEnvironment = Interpreter.interpretFile(source.value)
|
||||||
environment.extend(newEnvironment)
|
environment.extend(newEnvironment)
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
from smnp.ast.node.none import NoneNode
|
|
||||||
from smnp.error.runtime import RuntimeException
|
|
||||||
from smnp.runtime.evaluator import Evaluator, evaluate
|
|
||||||
from smnp.runtime.evaluators.expression import expressionEvaluator
|
|
||||||
from smnp.type.model import Type
|
|
||||||
|
|
||||||
|
|
||||||
class LoopEvaluator(Evaluator):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def evaluator(cls, node, environment):
|
|
||||||
iterator = expressionEvaluator(doAssert=True)(node.left, environment).value
|
|
||||||
parameters = [ identifier.value for identifier in node.parameters ] if type(node.parameters) != NoneNode() else []
|
|
||||||
|
|
||||||
try:
|
|
||||||
environment.scopes.append({})
|
|
||||||
|
|
||||||
output = {
|
|
||||||
Type.INTEGER: cls.numberEvaluator,
|
|
||||||
Type.BOOL: cls.boolEvaluator,
|
|
||||||
Type.LIST: cls.listEvaluator,
|
|
||||||
Type.MAP: cls.mapEvaluator
|
|
||||||
}[iterator.type](node, environment, iterator, parameters)
|
|
||||||
|
|
||||||
environment.scopes.pop(-1)
|
|
||||||
except KeyError:
|
|
||||||
raise RuntimeException(f"The {iterator.type.name.lower()} type cannot stand as an iterator for loop statement", node.left.pos)
|
|
||||||
|
|
||||||
return Type.list(output)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def numberEvaluator(cls, node, environment, evaluatedIterator, parameters):
|
|
||||||
output = []
|
|
||||||
|
|
||||||
|
|
||||||
if len(parameters) > 1:
|
|
||||||
raise RuntimeException(f"Loop with numeric iterator can handle only one parameter", node.parameters.pos)
|
|
||||||
|
|
||||||
for i in range(evaluatedIterator.value):
|
|
||||||
if len(parameters) > 0:
|
|
||||||
environment.scopes[-1][parameters[0]] = Type.integer(i)
|
|
||||||
|
|
||||||
output.append(evaluate(node.right, environment).value)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def boolEvaluator(cls, node, environment, evaluatedIterator, parameters):
|
|
||||||
output = []
|
|
||||||
|
|
||||||
if len(parameters) > 0:
|
|
||||||
raise RuntimeException(f"Loop with logic iterator can't' handle any parameters", node.parameters.pos)
|
|
||||||
|
|
||||||
condition = evaluatedIterator
|
|
||||||
while condition.value:
|
|
||||||
output.append(evaluate(node.right, environment).value)
|
|
||||||
condition = expressionEvaluator(doAssert=True)(node.left, environment).value
|
|
||||||
|
|
||||||
return output
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def listEvaluator(cls, node, environment, evaluatedIterator, parameters):
|
|
||||||
output = []
|
|
||||||
|
|
||||||
if len(parameters) > 2:
|
|
||||||
raise RuntimeException(f"Loop with list iterator can handle only two parameters", node.parameters.pos)
|
|
||||||
|
|
||||||
for i, value in enumerate(evaluatedIterator.value):
|
|
||||||
if len(parameters) == 1:
|
|
||||||
environment.scopes[-1][parameters[0]] = value
|
|
||||||
if len(parameters) == 2:
|
|
||||||
environment.scopes[-1][parameters[0]] = Type.integer(i)
|
|
||||||
environment.scopes[-1][parameters[1]] = value
|
|
||||||
|
|
||||||
output.append(evaluate(node.right, environment).value)
|
|
||||||
|
|
||||||
return output
|
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def mapEvaluator(cls, node, environment, evaluatedIterator, parameters):
|
|
||||||
output = []
|
|
||||||
|
|
||||||
if len(parameters) > 3:
|
|
||||||
raise RuntimeException(f"Loop with map iterator can handle only three parameters", node.parameters.pos)
|
|
||||||
|
|
||||||
i = 0
|
|
||||||
for key, value in evaluatedIterator.value.items():
|
|
||||||
if len(parameters) == 1:
|
|
||||||
environment.scopes[-1][parameters[0]] = value
|
|
||||||
if len(parameters) == 2:
|
|
||||||
environment.scopes[-1][parameters[0]] = key
|
|
||||||
environment.scopes[-1][parameters[1]] = value
|
|
||||||
if len(parameters) == 3:
|
|
||||||
environment.scopes[-1][parameters[0]] = Type.integer(i)
|
|
||||||
environment.scopes[-1][parameters[1]] = key
|
|
||||||
environment.scopes[-1][parameters[2]] = value
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
output.append(evaluate(node.right, environment).value)
|
|
||||||
|
|
||||||
return output
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
from smnp.error.runtime import RuntimeException
|
|
||||||
from smnp.runtime.evaluator import Evaluator, evaluate
|
|
||||||
from smnp.type.model import Type
|
|
||||||
|
|
||||||
|
|
||||||
class MinusEvaluator(Evaluator):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def evaluator(cls, node, environment):
|
|
||||||
value = evaluate(node.value, environment).value
|
|
||||||
try:
|
|
||||||
return {
|
|
||||||
Type.INTEGER: cls.evaluateForInteger,
|
|
||||||
Type.STRING: cls.evaluateForString,
|
|
||||||
Type.LIST: cls.evaluateForList
|
|
||||||
}[value.type](value.value)
|
|
||||||
except KeyError:
|
|
||||||
raise RuntimeException(f"Type {value.type.name.lower()} does not support '{node.operator.value}' operator", node.pos)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def evaluateForInteger(cls, value):
|
|
||||||
|
|
||||||
return Type.integer(-value)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def evaluateForString(cls, value):
|
|
||||||
return Type.string(value[::-1])
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def evaluateForList(cls, value):
|
|
||||||
return Type.list(value[::-1])
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
from smnp.error.runtime import RuntimeException
|
|
||||||
from smnp.runtime.evaluator import Evaluator
|
|
||||||
from smnp.runtime.evaluators.expression import expressionEvaluator
|
|
||||||
from smnp.type.model import Type
|
|
||||||
|
|
||||||
|
|
||||||
class NotEvaluator(Evaluator):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def evaluator(cls, node, environment):
|
|
||||||
value = expressionEvaluator(doAssert=True)(node.value, environment).value
|
|
||||||
|
|
||||||
if value.type != Type.BOOL:
|
|
||||||
raise RuntimeException(f"Operator '{node.operator.value}' is supported only by {Type.BOOL.name.lower()} type", node.value.pos)
|
|
||||||
|
|
||||||
return Type.bool(not value.value)
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
from smnp.error.runtime import RuntimeException
|
|
||||||
from smnp.runtime.evaluator import Evaluator
|
|
||||||
from smnp.runtime.evaluators.expression import expressionEvaluator
|
|
||||||
from smnp.type.model import Type
|
|
||||||
|
|
||||||
|
|
||||||
class PowerEvaluator(Evaluator):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def evaluator(cls, node, environment):
|
|
||||||
left = expressionEvaluator(doAssert=True)(node.left, environment).value
|
|
||||||
right = expressionEvaluator(doAssert=True)(node.right, environment).value
|
|
||||||
|
|
||||||
if left.type != Type.INTEGER:
|
|
||||||
raise RuntimeException( f"Operator '{node.operator.value}' is supported only by {Type.INTEGER.name.lower()} type", node.left.pos)
|
|
||||||
|
|
||||||
if right.type != Type.INTEGER:
|
|
||||||
raise RuntimeException( f"Operator '{node.operator.value}' is supported only by {Type.INTEGER.name.lower()} type", node.right.pos)
|
|
||||||
|
|
||||||
return Type.integer(int(left.value ** right.value))
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
from smnp.error.runtime import RuntimeException
|
|
||||||
from smnp.runtime.evaluator import Evaluator
|
|
||||||
from smnp.runtime.evaluators.expression import expressionEvaluator
|
|
||||||
from smnp.type.model import Type
|
|
||||||
|
|
||||||
|
|
||||||
class ProductEvaluator(Evaluator):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def evaluator(cls, node, environment):
|
|
||||||
left = expressionEvaluator(doAssert=True)(node.left, environment).value
|
|
||||||
right = expressionEvaluator(doAssert=True)(node.right, environment).value
|
|
||||||
|
|
||||||
if left.type != Type.INTEGER:
|
|
||||||
raise RuntimeException(
|
|
||||||
f"Operator '{node.operator.value}' is supported only by {Type.INTEGER.name.lower()} type", node.left.pos)
|
|
||||||
|
|
||||||
if right.type != Type.INTEGER:
|
|
||||||
raise RuntimeException(
|
|
||||||
f"Operator '{node.operator.value}' is supported only by {Type.INTEGER.name.lower()} type", node.right.pos)
|
|
||||||
|
|
||||||
if node.operator.value == "*":
|
|
||||||
return Type.integer(int(left.value * right.value))
|
|
||||||
|
|
||||||
if node.operator.value == "/":
|
|
||||||
if right.value == 0:
|
|
||||||
raise RuntimeException("Attempt to divide by 0", node.right.pos)
|
|
||||||
return Type.integer(int(left.value / right.value))
|
|
||||||
|
|
||||||
raise RuntimeError("This line should never be reached")
|
|
||||||
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
from smnp.error.runtime import RuntimeException
|
|
||||||
from smnp.runtime.evaluator import Evaluator
|
|
||||||
from smnp.runtime.evaluators.expression import expressionEvaluator
|
|
||||||
from smnp.type.model import Type
|
|
||||||
|
|
||||||
|
|
||||||
class RelationEvaluator(Evaluator):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def evaluator(cls, node, environment):
|
|
||||||
left = expressionEvaluator(doAssert=True)(node.left, environment).value
|
|
||||||
right = expressionEvaluator(doAssert=True)(node.right, environment).value
|
|
||||||
|
|
||||||
if node.operator.value == "==":
|
|
||||||
return cls.equalOperatorEvaluator(left, node.operator, right)
|
|
||||||
|
|
||||||
if node.operator.value == "!=":
|
|
||||||
return cls.notEqualOperatorEvaluator(left, node.operator, right)
|
|
||||||
|
|
||||||
return cls.otherRelationOperatorsEvaluator(left, node.operator, right)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def equalOperatorEvaluator(cls, left, operator, right):
|
|
||||||
return Type.bool(left.value == right.value)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def notEqualOperatorEvaluator(cls, left, operator, right):
|
|
||||||
return Type.bool(left.value != right.value)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def otherRelationOperatorsEvaluator(cls, left, operator, right):
|
|
||||||
if left.type == right.type == Type.INTEGER:
|
|
||||||
if operator.value == ">":
|
|
||||||
return Type.bool(left.value > right.value)
|
|
||||||
|
|
||||||
if operator.value == ">=":
|
|
||||||
return Type.bool(left.value >= right.value)
|
|
||||||
|
|
||||||
if operator.value == "<":
|
|
||||||
return Type.bool(left.value < right.value)
|
|
||||||
|
|
||||||
if operator.value == "<=":
|
|
||||||
return Type.bool(left.value < right.value)
|
|
||||||
|
|
||||||
raise RuntimeException(f"Operator {operator.value} is not supported by {left.type.name.lower()} and {right.type.name.lower()} types", operator.pos)
|
|
||||||
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
from smnp.error.runtime import RuntimeException
|
|
||||||
from smnp.runtime.evaluator import Evaluator
|
|
||||||
from smnp.runtime.evaluators.expression import expressionEvaluator
|
|
||||||
from smnp.type.model import Type
|
|
||||||
|
|
||||||
|
|
||||||
class SumEvaluator(Evaluator):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def evaluator(cls, node, environment):
|
|
||||||
left = expressionEvaluator(doAssert=True)(node.left, environment).value
|
|
||||||
right = expressionEvaluator(doAssert=True)(node.right, environment).value
|
|
||||||
|
|
||||||
if left.type == right.type == Type.INTEGER:
|
|
||||||
return cls.integerEvaluator(left, node.operator, right)
|
|
||||||
|
|
||||||
if left.type == right.type == Type.STRING:
|
|
||||||
return cls.stringEvaluator(left, node.operator, right)
|
|
||||||
|
|
||||||
if left.type == right.type == Type.LIST:
|
|
||||||
return cls.listEvaluator(left, node.operator, right)
|
|
||||||
|
|
||||||
if left.type == right.type == Type.MAP:
|
|
||||||
return cls.mapEvaluator(left, node.operator, right)
|
|
||||||
|
|
||||||
raise RuntimeException(f"Operator {node.operator.value} is not supported by {left.type.name.lower()} and {right.type.name.lower()} types", node.operator.pos)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def integerEvaluator(cls, left, operator, right):
|
|
||||||
if operator.value == "+":
|
|
||||||
return Type.integer(left.value + right.value)
|
|
||||||
|
|
||||||
if operator.value == "-":
|
|
||||||
return Type.integer(left.value - right.value)
|
|
||||||
|
|
||||||
raise RuntimeError("This line should never be reached")
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def stringEvaluator(cls, left, operator, right):
|
|
||||||
if operator.value == "+":
|
|
||||||
return Type.string(left.value + right.value)
|
|
||||||
|
|
||||||
if operator.value == "-":
|
|
||||||
raise RuntimeException(f"Operator {operator.value} is not supported by string types", operator.pos)
|
|
||||||
|
|
||||||
raise RuntimeError("This line should never be reached")
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def listEvaluator(cls, left, operator, right):
|
|
||||||
if operator.value == "+":
|
|
||||||
return Type.list(left.value + right.value)
|
|
||||||
|
|
||||||
if operator.value == "-":
|
|
||||||
raise RuntimeException(f"Operator {operator.value} is not supported by list types", operator.pos)
|
|
||||||
|
|
||||||
raise RuntimeError("This line should never be reached")
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def mapEvaluator(cls, left, operator, right):
|
|
||||||
if operator.value == "+":
|
|
||||||
return Type.map({**left.value, **right.value})
|
|
||||||
|
|
||||||
if operator.value == "-":
|
|
||||||
raise RuntimeException(f"Operator {operator.value} is not supported by map types", operator.pos)
|
|
||||||
|
|
||||||
raise RuntimeError("This line should never be reached")
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
from smnp.ast.node.identifier import Identifier, FunctionCall
|
|
||||||
from smnp.error.runtime import RuntimeException
|
|
||||||
from smnp.runtime.evaluator import Evaluator
|
|
||||||
from smnp.runtime.evaluators.expression import expressionEvaluator
|
|
||||||
from smnp.runtime.evaluators.iterable import abstractIterableEvaluator
|
|
||||||
from smnp.runtime.tools.error import updatePos
|
|
||||||
|
|
||||||
|
|
||||||
class UnitEvaluator(Evaluator):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def evaluator(cls, node, environment):
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
class AccessEvaluator(Evaluator):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def evaluator(cls, node, environment):
|
|
||||||
left = expressionEvaluator(doAssert=True)(node.left, environment).value # TODO check if it isn't necessary to verify 'result' attr of EvaluatioNResult
|
|
||||||
right = node.right
|
|
||||||
|
|
||||||
if type(right) == Identifier:
|
|
||||||
try:
|
|
||||||
return left.properties[right.value]
|
|
||||||
except KeyError:
|
|
||||||
raise RuntimeException(f"Unknown property '{right.value}' of type '{left.type.name.lower()}'", right.pos)
|
|
||||||
|
|
||||||
if type(right) == FunctionCall:
|
|
||||||
try:
|
|
||||||
arguments = abstractIterableEvaluator(expressionEvaluator(doAssert=True))(right.arguments, environment)
|
|
||||||
return environment.invokeMethod(left, right.name.value, arguments)
|
|
||||||
except RuntimeException as e:
|
|
||||||
raise updatePos(e, right)
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
from smnp.ast.node import type as ast
|
|
||||||
from smnp.ast.node.none import NoneNode
|
from smnp.ast.node.none import NoneNode
|
||||||
from smnp.ast.node.type import TypesList
|
from smnp.ast.node.type import TypeNode, TypeSpecifier
|
||||||
from smnp.error.runtime import RuntimeException
|
from smnp.error.runtime import RuntimeException
|
||||||
from smnp.function.signature import varargSignature, signature
|
from smnp.function.signature import varargSignature, signature
|
||||||
from smnp.runtime.tools.error import updatePos
|
from smnp.runtime.tools.error import updatePos
|
||||||
@@ -17,9 +16,9 @@ def argumentsNodeToMethodSignature(node):
|
|||||||
argumentsCount = len(node.children)
|
argumentsCount = len(node.children)
|
||||||
for i, child in enumerate(node.children):
|
for i, child in enumerate(node.children):
|
||||||
matchers = {
|
matchers = {
|
||||||
ast.Type: (lambda c: c.type, typeMatcher),
|
TypeNode: (lambda c: c.type, typeMatcher),
|
||||||
NoneNode: (lambda c: c.type, lambda c: allTypes()),
|
NoneNode: (lambda c: c.type, lambda c: allTypes()),
|
||||||
TypesList: (lambda c: c, multipleTypeMatcher)
|
TypeSpecifier: (lambda c: c, multipleTypeMatcher)
|
||||||
}
|
}
|
||||||
evaluatedMatcher = matchers[type(child.type)][1](matchers[type(child.type)][0](child))
|
evaluatedMatcher = matchers[type(child.type)][1](matchers[type(child.type)][0](child))
|
||||||
if child.vararg:
|
if child.vararg:
|
||||||
@@ -50,10 +49,10 @@ def multipleTypeMatcher(typeNode):
|
|||||||
|
|
||||||
def typeMatcher(typeNode):
|
def typeMatcher(typeNode):
|
||||||
if type(typeNode.specifiers) == NoneNode:
|
if type(typeNode.specifiers) == NoneNode:
|
||||||
return ofType(typeNode.type.value)
|
return ofType(typeNode.type)
|
||||||
elif typeNode.type.value == Type.LIST and len(typeNode.specifiers) == 1:
|
elif typeNode.type == Type.LIST and len(typeNode.specifiers) == 1:
|
||||||
return listSpecifier(typeNode.specifiers[0])
|
return listSpecifier(typeNode.specifiers[0])
|
||||||
elif typeNode.type.value == Type.MAP and len(typeNode.specifiers) == 2:
|
elif typeNode.type == Type.MAP and len(typeNode.specifiers) == 2:
|
||||||
return mapSpecifier(typeNode.specifiers[0], typeNode.specifiers[1])
|
return mapSpecifier(typeNode.specifiers[0], typeNode.specifiers[1])
|
||||||
|
|
||||||
raise RuntimeException("Unknown type", typeNode.pos) # Todo: Improve pointing position
|
raise RuntimeException("Unknown type", typeNode.pos) # Todo: Improve pointing position
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from smnp.token.tokenizers.note import noteTokenizer
|
|||||||
from smnp.token.tokenizers.relation import relationOperatorTokenizer
|
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, mapValue
|
from smnp.token.tools import defaultTokenizer, separated, regexPatternTokenizer
|
||||||
from smnp.token.type import TokenType
|
from smnp.token.type import TokenType
|
||||||
|
|
||||||
tokenizers = (
|
tokenizers = (
|
||||||
@@ -39,7 +39,7 @@ tokenizers = (
|
|||||||
defaultTokenizer(TokenType.DOT),
|
defaultTokenizer(TokenType.DOT),
|
||||||
|
|
||||||
# Types
|
# Types
|
||||||
mapValue(separated(regexPatternTokenizer(TokenType.INTEGER, r'\d')), int),
|
separated(regexPatternTokenizer(TokenType.INTEGER, r'\d')),
|
||||||
stringTokenizer,
|
stringTokenizer,
|
||||||
noteTokenizer,
|
noteTokenizer,
|
||||||
boolTokenizer,
|
boolTokenizer,
|
||||||
@@ -51,7 +51,6 @@ 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.WITH)),
|
|
||||||
separated(defaultTokenizer(TokenType.ELSE)),
|
separated(defaultTokenizer(TokenType.ELSE)),
|
||||||
separated(defaultTokenizer(TokenType.AND)),
|
separated(defaultTokenizer(TokenType.AND)),
|
||||||
separated(defaultTokenizer(TokenType.NOT)),
|
separated(defaultTokenizer(TokenType.NOT)),
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from smnp.token.type import TokenType
|
|||||||
from smnp.type.model import Type
|
from smnp.type.model import Type
|
||||||
|
|
||||||
|
|
||||||
typeTokenizer = separated(keywordsTokenizer(TokenType.TYPE, *[type.name.lower() for type in Type], mapKeyword=lambda value: Type[value.upper()]))
|
typeTokenizer = separated(keywordsTokenizer(TokenType.TYPE, *[type.name.lower() for type in Type]))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ def noteTokenizer(input, current, line):
|
|||||||
rawValue = ''
|
rawValue = ''
|
||||||
if input[current] == '@':
|
if input[current] == '@':
|
||||||
rawValue += input[current+consumedChars]
|
rawValue += input[current+consumedChars]
|
||||||
consumedChars += 1 # TODO: Check if next item does even exist
|
consumedChars += 1
|
||||||
if input[current+consumedChars] in ('C', 'c', 'D', 'd', 'E', 'e', 'F', 'f', 'G', 'g', 'A', 'a', 'H', 'h', 'B', 'b'):
|
if input[current+consumedChars] in ('C', 'c', 'D', 'd', 'E', 'e', 'F', 'f', 'G', 'g', 'A', 'a', 'H', 'h', 'B', 'b'):
|
||||||
rawValue += input[current + consumedChars]
|
rawValue += input[current + consumedChars]
|
||||||
notePitch = input[current+consumedChars]
|
notePitch = input[current+consumedChars]
|
||||||
|
|||||||
@@ -3,4 +3,4 @@ from smnp.token.type import TokenType
|
|||||||
|
|
||||||
|
|
||||||
def relationOperatorTokenizer(input, current, line):
|
def relationOperatorTokenizer(input, current, line):
|
||||||
return keywordsTokenizer(TokenType.RELATION, "==", "!=", ">=", "<=")(input, current, line)
|
return keywordsTokenizer(TokenType.RELATION, "==", "!=", ">=", "<=", ">", "<")(input, current, line)
|
||||||
@@ -13,5 +13,5 @@ def stringTokenizer(input, current, line):
|
|||||||
char = input[current + consumedChars]
|
char = input[current + consumedChars]
|
||||||
value += char
|
value += char
|
||||||
consumedChars += 1
|
consumedChars += 1
|
||||||
return (consumedChars, Token(TokenType.STRING, value[1:len(value)-1], (line, current), value))
|
return (consumedChars, Token(TokenType.STRING, value[1:len(value)-1], (line, current)))
|
||||||
return (0, None)
|
return (0, None)
|
||||||
|
|||||||
@@ -16,10 +16,10 @@ def regexPatternTokenizer(type, pattern):
|
|||||||
return tokenizer
|
return tokenizer
|
||||||
|
|
||||||
|
|
||||||
def keywordsTokenizer(type, *keywords, mapKeyword=lambda x: x):
|
def keywordsTokenizer(type, *keywords):
|
||||||
def tokenizer(input, current, line):
|
def tokenizer(input, current, line):
|
||||||
for keyword in keywords:
|
for keyword in keywords:
|
||||||
result = keywordTokenizer(type, keyword, mapKeyword)(input, current, line)
|
result = keywordTokenizer(type, keyword)(input, current, line)
|
||||||
if result[0] > 0:
|
if result[0] > 0:
|
||||||
return result
|
return result
|
||||||
return (0, None)
|
return (0, None)
|
||||||
@@ -27,10 +27,10 @@ def keywordsTokenizer(type, *keywords, mapKeyword=lambda x: x):
|
|||||||
return tokenizer
|
return tokenizer
|
||||||
|
|
||||||
|
|
||||||
def keywordTokenizer(type, keyword, mapKeyword=lambda x: x):
|
def keywordTokenizer(type, keyword):
|
||||||
def tokenizer(input, current, line):
|
def tokenizer(input, current, line):
|
||||||
if len(input) >= current+len(keyword) and input[current:current+len(keyword)] == keyword:
|
if len(input) >= current+len(keyword) and input[current:current+len(keyword)] == keyword:
|
||||||
return (len(keyword), Token(type, mapKeyword(keyword), (line, current)))
|
return (len(keyword), Token(type, keyword, (line, current)))
|
||||||
return (0, None)
|
return (0, None)
|
||||||
return tokenizer
|
return tokenizer
|
||||||
|
|
||||||
@@ -50,14 +50,3 @@ def separated(tokenizer, end=r"\W"):
|
|||||||
return (0, None)
|
return (0, None)
|
||||||
|
|
||||||
return separated
|
return separated
|
||||||
|
|
||||||
|
|
||||||
def mapValue(tokenizer, mapper):
|
|
||||||
def tokenize(input, current, line):
|
|
||||||
consumedChars, token = tokenizer(input, current, line)
|
|
||||||
if consumedChars > 0:
|
|
||||||
return (consumedChars, Token(token.type, mapper(token.value), token.pos))
|
|
||||||
|
|
||||||
return (0, None)
|
|
||||||
|
|
||||||
return tokenize
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from enum import Enum
|
|||||||
|
|
||||||
|
|
||||||
class TokenType(Enum):
|
class TokenType(Enum):
|
||||||
RELATION = '==, !=, >=, <='
|
RELATION = 'relation'
|
||||||
DOUBLE_ASTERISK = '**'
|
DOUBLE_ASTERISK = '**'
|
||||||
OPEN_CURLY = '{'
|
OPEN_CURLY = '{'
|
||||||
CLOSE_CURLY = '}'
|
CLOSE_CURLY = '}'
|
||||||
@@ -36,7 +36,6 @@ class TokenType(Enum):
|
|||||||
EXTEND = 'extend'
|
EXTEND = 'extend'
|
||||||
IMPORT = 'import'
|
IMPORT = 'import'
|
||||||
FROM = 'from'
|
FROM = 'from'
|
||||||
WITH = 'with'
|
|
||||||
ELSE = 'else'
|
ELSE = 'else'
|
||||||
IF = 'if'
|
IF = 'if'
|
||||||
AS = 'as'
|
AS = 'as'
|
||||||
|
|||||||
@@ -73,7 +73,6 @@ class Type(Enum):
|
|||||||
def void():
|
def void():
|
||||||
return Value(Type.VOID, None)
|
return Value(Type.VOID, None)
|
||||||
|
|
||||||
|
|
||||||
def _failStringify(t):
|
def _failStringify(t):
|
||||||
raise RuntimeException(f"Not able to interpret {t.name}'", None)
|
raise RuntimeException(f"Not able to interpret {t.name}'", None)
|
||||||
|
|
||||||
|
|||||||
0
smnp/util/__init__.py
Normal file
0
smnp/util/__init__.py
Normal file
14
smnp/util/singleton.py
Normal file
14
smnp/util/singleton.py
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
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