Compare commits
5 Commits
add-polyph
...
add-bool
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a1bc422fba | ||
|
|
98d710ac97 | ||
|
|
d6fb101337 | ||
|
|
e008be7952 | ||
|
|
0a7d29d4a1 |
@@ -1,5 +1,5 @@
|
||||
from smnp.ast.node.expression import ExpressionNode
|
||||
from smnp.ast.node.ignore import IgnoredNode
|
||||
from smnp.ast.node.none import NoneNode
|
||||
from smnp.ast.parser import Parser
|
||||
from smnp.error.syntax import SyntaxException
|
||||
from smnp.token.type import TokenType
|
||||
@@ -8,7 +8,7 @@ from smnp.token.type import TokenType
|
||||
class AccessNode(ExpressionNode):
|
||||
def __init__(self, pos):
|
||||
super().__init__(pos)
|
||||
self.children.append(IgnoredNode(pos))
|
||||
self.children = [ NoneNode(), NoneNode() ]
|
||||
|
||||
@property
|
||||
def left(self):
|
||||
@@ -27,30 +27,30 @@ class AccessNode(ExpressionNode):
|
||||
self[1] = value
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, input):
|
||||
def createNode(left, right):
|
||||
def accessParser(cls):
|
||||
def createNode(left, operator, right):
|
||||
node = AccessNode(right.pos)
|
||||
node.left = left
|
||||
node.right = right
|
||||
return node
|
||||
|
||||
return Parser.leftAssociativeOperatorParser(
|
||||
cls._literalParser(),
|
||||
cls._accessLhs(),
|
||||
TokenType.DOT,
|
||||
cls._parseAccessingProperty(),
|
||||
cls._accessRhs(),
|
||||
createNode=createNode
|
||||
)(input)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def _literalParser(cls):
|
||||
pass
|
||||
def _accessLhs(cls):
|
||||
raise RuntimeError(f"_accessLhs() is not implemented in {cls.__name__} class")
|
||||
|
||||
@staticmethod
|
||||
def _parseAccessingProperty():
|
||||
def _accessRhs():
|
||||
from smnp.ast.node.identifier import IdentifierNode
|
||||
|
||||
return Parser.oneOf(
|
||||
IdentifierNode._literalParser(),
|
||||
IdentifierNode._functionCallParser(),
|
||||
IdentifierNode.functionCallParser(),
|
||||
IdentifierNode.identifierParser(),
|
||||
exception=lambda input: SyntaxException(f"Expected property name or method call, found '{input.current().rawValue}'", input.currentPos())
|
||||
)
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
from smnp.ast.node.access import AccessNode
|
||||
from smnp.ast.node.literal import LiteralNode
|
||||
from smnp.ast.node.relation import RelationOperatorNode
|
||||
from smnp.ast.parser import Parser
|
||||
from smnp.token.type import TokenType
|
||||
|
||||
|
||||
class BoolLiteralNode(LiteralNode, AccessNode):
|
||||
class BoolLiteralNode(LiteralNode, AccessNode, RelationOperatorNode):
|
||||
def __init__(self, pos):
|
||||
super().__init__(pos)
|
||||
del self.children[1]
|
||||
@@ -11,3 +13,20 @@ class BoolLiteralNode(LiteralNode, AccessNode):
|
||||
@classmethod
|
||||
def _getTokenType(cls):
|
||||
return TokenType.BOOL
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, input):
|
||||
x = Parser.oneOf(
|
||||
cls.accessParser(),
|
||||
cls.relationParser(),
|
||||
cls.literalParser()
|
||||
)(input)
|
||||
return x
|
||||
|
||||
@classmethod
|
||||
def _accessLhs(cls):
|
||||
return cls.literalParser()
|
||||
|
||||
@classmethod
|
||||
def _relationLhs(cls):
|
||||
return cls.literalParser()
|
||||
@@ -50,22 +50,17 @@ class ExpressionNode(Node):
|
||||
|
||||
@classmethod
|
||||
def _expressionParser(cls):
|
||||
from smnp.ast.node.integer import IntegerLiteralNode
|
||||
from smnp.ast.node.string import StringLiteralNode
|
||||
from smnp.ast.node.note import NoteLiteralNode
|
||||
from smnp.ast.node.bool import BoolLiteralNode
|
||||
from smnp.ast.node.identifier import IdentifierNode
|
||||
from smnp.ast.node.list import ListNode
|
||||
from smnp.ast.node.map import MapNode
|
||||
from smnp.ast.node.type import TypeNode
|
||||
|
||||
from smnp.ast.node.identifier import IdentifierNode
|
||||
from smnp.ast.node.string import StringLiteralNode
|
||||
return Parser.oneOf(
|
||||
IntegerLiteralNode.parse,
|
||||
#IntegerLiteralNode.parse,
|
||||
StringLiteralNode.parse,
|
||||
NoteLiteralNode.parse,
|
||||
#NoteLiteralNode.parse,
|
||||
BoolLiteralNode.parse,
|
||||
IdentifierNode.parse,
|
||||
MapNode.parse,
|
||||
ListNode.parse,
|
||||
TypeNode.parse,
|
||||
#MapNode.parse,
|
||||
#ListNode.parse,
|
||||
#TypeNode.parse,
|
||||
)
|
||||
@@ -2,19 +2,39 @@ from smnp.ast.node.access import AccessNode
|
||||
from smnp.ast.node.assignment import AssignmentNode
|
||||
from smnp.ast.node.expression import ExpressionNode
|
||||
from smnp.ast.node.invocation import FunctionCallNode, ArgumentsListNode
|
||||
from smnp.ast.node.relation import RelationOperatorNode
|
||||
from smnp.ast.parser import Parser
|
||||
from smnp.token.type import TokenType
|
||||
|
||||
|
||||
class IdentifierNode(AccessNode):
|
||||
class IdentifierNode(AccessNode, RelationOperatorNode):
|
||||
def __init__(self, pos):
|
||||
super().__init__(pos)
|
||||
del self.children[1]
|
||||
|
||||
@classmethod
|
||||
def _literalParser(cls):
|
||||
def _parse(cls, input):
|
||||
return Parser.oneOf(
|
||||
IdentifierNode._functionCallParser(),
|
||||
cls.relationParser(),
|
||||
cls.accessParser(),
|
||||
cls.literalParser()
|
||||
)(input)
|
||||
|
||||
@classmethod
|
||||
def _accessLhs(cls):
|
||||
return cls.literalParser()
|
||||
|
||||
@classmethod
|
||||
def _relationLhs(cls):
|
||||
return Parser.oneOf(
|
||||
cls.accessParser(),
|
||||
cls.literalParser()
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def literalParser(cls):
|
||||
return Parser.oneOf(
|
||||
IdentifierNode.functionCallParser(),
|
||||
IdentifierNode._assignmentParser(),
|
||||
IdentifierNode.identifierParser()
|
||||
)
|
||||
@@ -35,7 +55,7 @@ class IdentifierNode(AccessNode):
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _functionCallParser():
|
||||
def functionCallParser():
|
||||
def createNode(name, arguments):
|
||||
node = FunctionCallNode(name.pos)
|
||||
node.name = name
|
||||
|
||||
@@ -56,7 +56,7 @@ class ImportNode(Node):
|
||||
Parser.terminalParser(TokenType.IMPORT),
|
||||
TypeNode.parse,
|
||||
Parser.doAssert(Parser.terminalParser(TokenType.FROM), "'from <source> as <variable name>'"),
|
||||
Parser.doAssert(StringLiteralNode._literalParser(), "source as a string"),
|
||||
Parser.doAssert(StringLiteralNode.literalParser(), "source as a string"),
|
||||
Parser.doAssert(Parser.terminalParser(TokenType.AS), "'as <variable name>'"),
|
||||
Parser.doAssert(IdentifierNode.identifierParser(), "variable name"),
|
||||
createNode=createNode
|
||||
@@ -71,6 +71,6 @@ class ImportNode(Node):
|
||||
|
||||
return Parser.allOf(
|
||||
Parser.terminalParser(TokenType.IMPORT),
|
||||
Parser.doAssert(StringLiteralNode._literalParser(), "source as a string"),
|
||||
Parser.doAssert(StringLiteralNode.literalParser(), "source as a string"),
|
||||
createNode=createNode
|
||||
)
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
from smnp.ast.node.access import AccessNode
|
||||
from smnp.ast.node.expression import ExpressionNode
|
||||
from smnp.ast.parser import Parser
|
||||
from smnp.token.type import TokenType
|
||||
|
||||
|
||||
class IntegerLiteralNode(AccessNode):
|
||||
class IntegerLiteralNode(ExpressionNode):
|
||||
def __init__(self, pos):
|
||||
super().__init__(pos)
|
||||
del self.children[1]
|
||||
#TODO del self.children[1]
|
||||
|
||||
|
||||
# TODO: To Remove
|
||||
@classmethod
|
||||
def _parse(cls, input):
|
||||
return cls._literalParser()(input)
|
||||
|
||||
@classmethod
|
||||
def _literalParser(cls):
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
from smnp.ast.node.access import AccessNode
|
||||
from smnp.ast.node.expression import ExpressionNode
|
||||
from smnp.ast.node.iterable import abstractIterableParser
|
||||
from smnp.ast.parser import Parser
|
||||
from smnp.token.type import TokenType
|
||||
|
||||
|
||||
class ListNode(AccessNode):
|
||||
class ListNode(ExpressionNode):
|
||||
|
||||
# TODO: To Remove
|
||||
@classmethod
|
||||
def _parse(cls, input):
|
||||
return cls._literalParser()(input)
|
||||
|
||||
@classmethod
|
||||
def _literalParser(cls):
|
||||
|
||||
@@ -13,6 +13,6 @@ class LiteralNode(ExpressionNode):
|
||||
return value
|
||||
|
||||
@classmethod
|
||||
def _literalParser(cls):
|
||||
def literalParser(cls):
|
||||
createNode = lambda val, pos: cls.withValue(cls._processValue(val), pos)
|
||||
return Parser.terminalParser(cls._getTokenType(), createNode)
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
from smnp.ast.node.access import AccessNode
|
||||
from smnp.ast.node.literal import LiteralNode
|
||||
from smnp.token.type import TokenType
|
||||
|
||||
|
||||
class NoteLiteralNode(LiteralNode, AccessNode):
|
||||
class NoteLiteralNode(LiteralNode):
|
||||
def __init__(self, pos):
|
||||
super().__init__(pos)
|
||||
del self.children[1]
|
||||
#TODO del self.children[1]
|
||||
|
||||
|
||||
# TODO: To Remove
|
||||
@classmethod
|
||||
def _parse(cls, input):
|
||||
return cls.literalParser()(input)
|
||||
|
||||
@classmethod
|
||||
def _getTokenType(cls):
|
||||
|
||||
15
smnp/ast/node/operator.py
Normal file
15
smnp/ast/node/operator.py
Normal file
@@ -0,0 +1,15 @@
|
||||
from smnp.ast.node.model import Node
|
||||
|
||||
|
||||
class OperatorNode(Node):
|
||||
def __init__(self, pos):
|
||||
super().__init__(pos)
|
||||
self.children = [None]
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
return self[0]
|
||||
|
||||
@value.setter
|
||||
def value(self, value):
|
||||
self[0] = value
|
||||
68
smnp/ast/node/relation.py
Normal file
68
smnp/ast/node/relation.py
Normal file
@@ -0,0 +1,68 @@
|
||||
from smnp.ast.node.expression import ExpressionNode
|
||||
from smnp.ast.node.none import NoneNode
|
||||
from smnp.ast.parser import Parser
|
||||
from smnp.token.type import TokenType
|
||||
|
||||
|
||||
class RelationOperatorNode(ExpressionNode):
|
||||
def __init__(self, pos):
|
||||
super().__init__(pos)
|
||||
self.children = [ NoneNode(), NoneNode(), NoneNode()]
|
||||
|
||||
@property
|
||||
def left(self):
|
||||
return self[0]
|
||||
|
||||
@left.setter
|
||||
def left(self, value):
|
||||
self[0] = value
|
||||
|
||||
@property
|
||||
def operator(self):
|
||||
return self[1]
|
||||
|
||||
@operator.setter
|
||||
def operator(self, value):
|
||||
self[1] = value
|
||||
|
||||
@property
|
||||
def right(self):
|
||||
return self[2]
|
||||
|
||||
@right.setter
|
||||
def right(self, value):
|
||||
self[2] = value
|
||||
|
||||
@classmethod
|
||||
def relationParser(cls):
|
||||
def createNode(left, operator, right):
|
||||
node = RelationOperatorNode(right.pos)
|
||||
node.left = left
|
||||
node.operator = operator
|
||||
node.right = right
|
||||
return node
|
||||
|
||||
return Parser.leftAssociativeOperatorParser(
|
||||
cls._relationLhs(),
|
||||
TokenType.EQUAL,
|
||||
cls._relationRhs(),
|
||||
createNode=createNode
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def _relationLhs(cls):
|
||||
raise RuntimeError(f"_relationLhs() is not implemented in {cls.__name__} class")
|
||||
|
||||
@staticmethod
|
||||
def _relationRhs():
|
||||
from smnp.ast.node.bool import BoolLiteralNode
|
||||
from smnp.ast.node.identifier import IdentifierNode
|
||||
|
||||
from smnp.ast.node.string import StringLiteralNode
|
||||
return Parser.doAssert(Parser.oneOf(
|
||||
BoolLiteralNode.accessParser(),
|
||||
BoolLiteralNode.literalParser(),
|
||||
IdentifierNode.parse,
|
||||
StringLiteralNode.accessParser(),
|
||||
StringLiteralNode.literalParser()
|
||||
), "expression")
|
||||
@@ -1,13 +1,31 @@
|
||||
from smnp.ast.node.access import AccessNode
|
||||
from smnp.ast.node.literal import LiteralNode
|
||||
from smnp.ast.node.relation import RelationOperatorNode
|
||||
from smnp.ast.parser import Parser
|
||||
from smnp.token.type import TokenType
|
||||
|
||||
|
||||
class StringLiteralNode(LiteralNode, AccessNode):
|
||||
class StringLiteralNode(AccessNode, RelationOperatorNode, LiteralNode):
|
||||
def __init__(self, pos):
|
||||
super().__init__(pos)
|
||||
del self.children[1]
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, input):
|
||||
return Parser.oneOf(
|
||||
cls.accessParser(),
|
||||
cls.relationParser(),
|
||||
cls.literalParser()
|
||||
)(input)
|
||||
|
||||
@classmethod
|
||||
def _accessLhs(cls):
|
||||
return cls.literalParser()
|
||||
|
||||
@classmethod
|
||||
def _relationLhs(cls):
|
||||
return cls.literalParser()
|
||||
|
||||
@classmethod
|
||||
def _getTokenType(cls):
|
||||
return TokenType.STRING
|
||||
@@ -1,6 +1,7 @@
|
||||
from smnp.ast.node.ignore import IgnoredNode
|
||||
from smnp.ast.node.model import ParseResult, Node
|
||||
from smnp.ast.node.none import NoneNode
|
||||
from smnp.ast.node.operator import OperatorNode
|
||||
from smnp.error.syntax import SyntaxException
|
||||
|
||||
|
||||
@@ -41,6 +42,7 @@ class Parser:
|
||||
value = parser(input)
|
||||
if value.result:
|
||||
return value
|
||||
input.reset(snap)
|
||||
|
||||
if exception is not None:
|
||||
if callable(exception):
|
||||
@@ -96,12 +98,16 @@ class Parser:
|
||||
def leftAssociativeOperatorParser(leftParser, operatorTokenType, rightParser, createNode):
|
||||
def parse(input):
|
||||
left = leftParser(input)
|
||||
oneAtLeast = False
|
||||
if left.result:
|
||||
while Parser.terminalParser(operatorTokenType)(input).result:
|
||||
operator = Parser.terminalParser(operatorTokenType, lambda val, pos: OperatorNode.withChildren([val], pos))(input)
|
||||
while operator.result:
|
||||
oneAtLeast = True
|
||||
right = rightParser(input)
|
||||
left = ParseResult.OK(createNode(left.node, right.node))
|
||||
|
||||
return left
|
||||
left = ParseResult.OK(createNode(left.node, operator.node, right.node))
|
||||
operator = Parser.terminalParser(operatorTokenType, lambda val, pos: OperatorNode.withChildren([val], pos))(input)
|
||||
if oneAtLeast:
|
||||
return left
|
||||
|
||||
return ParseResult.FAIL()
|
||||
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import sys
|
||||
|
||||
from smnp.error.base import SmnpException
|
||||
from smnp.library.loader import loadStandardLibrary
|
||||
from smnp.program.interpreter import Interpreter
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
stdLibraryEnv = loadStandardLibrary()
|
||||
Interpreter.interpretFile(sys.argv[1], printTokens=False, printAst=True, baseEnvironment=stdLibraryEnv)
|
||||
#stdLibraryEnv = loadStandardLibrary()
|
||||
Interpreter.interpretFile(sys.argv[1], printTokens=False, printAst=True, baseEnvironment=None)
|
||||
|
||||
except SmnpException as e:
|
||||
print(e.message())
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
from smnp.ast.node.block import BlockNode
|
||||
from smnp.ast.node.extend import ExtendNode
|
||||
from smnp.ast.node.function import FunctionDefinitionNode
|
||||
from smnp.ast.node.imports import ImportNode
|
||||
from smnp.ast.node.program import Program
|
||||
from smnp.ast.node.ret import ReturnNode
|
||||
from smnp.error.runtime import RuntimeException
|
||||
from smnp.type.model import Type
|
||||
|
||||
@@ -70,18 +65,13 @@ def evaluate(node, environment):
|
||||
from smnp.runtime.evaluators.program import ProgramEvaluator
|
||||
from smnp.runtime.evaluators.expression import expressionEvaluator
|
||||
|
||||
from smnp.runtime.evaluators.function import FunctionDefinitionEvaluator
|
||||
from smnp.runtime.evaluators.extend import ExtendEvaluator
|
||||
from smnp.runtime.evaluators.block import BlockEvaluator
|
||||
from smnp.runtime.evaluators.imports import ImportEvaluator
|
||||
from smnp.runtime.evaluators.function import ReturnEvaluator
|
||||
result = Evaluator.oneOf(
|
||||
Evaluator.forNodes(ProgramEvaluator.evaluate, Program),
|
||||
Evaluator.forNodes(ImportEvaluator.evaluate, ImportNode),
|
||||
Evaluator.forNodes(FunctionDefinitionEvaluator.evaluate, FunctionDefinitionNode),
|
||||
Evaluator.forNodes(ExtendEvaluator.evaluate, ExtendNode),
|
||||
Evaluator.forNodes(BlockEvaluator.evaluate, BlockNode),
|
||||
Evaluator.forNodes(ReturnEvaluator.evaluate, ReturnNode),
|
||||
#Evaluator.forNodes(ImportEvaluator.evaluate, ImportNode),
|
||||
#Evaluator.forNodes(FunctionDefinitionEvaluator.evaluate, FunctionDefinitionNode),
|
||||
#Evaluator.forNodes(ExtendEvaluator.evaluate, ExtendNode),
|
||||
#Evaluator.forNodes(BlockEvaluator.evaluate, BlockNode),
|
||||
#Evaluator.forNodes(ReturnEvaluator.evaluate, ReturnNode),
|
||||
expressionEvaluator()
|
||||
)(node, environment)
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ from smnp.token.tools import defaultTokenizer, separated, regexPatternTokenizer
|
||||
from smnp.token.type import TokenType
|
||||
|
||||
tokenizers = (
|
||||
defaultTokenizer(TokenType.EQUAL),
|
||||
|
||||
# Characters
|
||||
defaultTokenizer(TokenType.OPEN_CURLY),
|
||||
defaultTokenizer(TokenType.CLOSE_CURLY),
|
||||
|
||||
@@ -2,6 +2,7 @@ from enum import Enum
|
||||
|
||||
|
||||
class TokenType(Enum):
|
||||
EQUAL = '=='
|
||||
OPEN_CURLY = '{'
|
||||
CLOSE_CURLY = '}'
|
||||
OPEN_PAREN = '('
|
||||
|
||||
Reference in New Issue
Block a user