Add support for assignments, function calls and pure identifiers
This commit is contained in:
@@ -1,28 +1,28 @@
|
||||
from smnp.ast.node.expression import ExpressionNode
|
||||
from smnp.ast.node.none import NoneNode
|
||||
|
||||
|
||||
class AssignmentNode(ExpressionNode):
|
||||
def __init__(self, pos):
|
||||
super().__init__(pos)
|
||||
self.children.append(NoneNode())
|
||||
|
||||
@property
|
||||
def target(self):
|
||||
return self[0]
|
||||
|
||||
@target.setter
|
||||
def target(self, value):
|
||||
self[0] = value
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
return self[1]
|
||||
|
||||
@value.setter
|
||||
def value(self, value):
|
||||
self[1] = value
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, input):
|
||||
raise RuntimeError("This class is not supposed to be automatically called")
|
||||
# from smnp.ast.node.expression import ExpressionNode
|
||||
# from smnp.ast.node.none import NoneNode
|
||||
#
|
||||
#
|
||||
# class AssignmentNode(ExpressionNode):
|
||||
# def __init__(self, pos):
|
||||
# super().__init__(pos)
|
||||
# self.children.append(NoneNode())
|
||||
#
|
||||
# @property
|
||||
# def target(self):
|
||||
# return self[0]
|
||||
#
|
||||
# @target.setter
|
||||
# def target(self, value):
|
||||
# self[0] = value
|
||||
#
|
||||
# @property
|
||||
# def value(self):
|
||||
# return self[1]
|
||||
#
|
||||
# @value.setter
|
||||
# def value(self, value):
|
||||
# self[1] = value
|
||||
#
|
||||
# @classmethod
|
||||
# def _parse(cls, input):
|
||||
# raise RuntimeError("This class is not supposed to be automatically called")
|
||||
@@ -38,20 +38,24 @@ class NoteLiteral(Atom):
|
||||
class BoolLiteral(Atom):
|
||||
pass
|
||||
|
||||
integerParser = Parser.oneOf(
|
||||
Parser.terminalParser(TokenType.INTEGER, lambda val, pos: IntegerLiteral.withValue(int(val), pos)),
|
||||
Parser.allOf(
|
||||
Parser.terminalParser(TokenType.MINUS),
|
||||
def AtomParser(input):
|
||||
from smnp.ast.node.identifier import IdentifierParser
|
||||
|
||||
integerParser = Parser.oneOf(
|
||||
Parser.terminalParser(TokenType.INTEGER, lambda val, pos: IntegerLiteral.withValue(int(val), pos)),
|
||||
createNode=lambda minus, integer: IntegerLiteral.withValue(-integer.value, minus.pos)
|
||||
Parser.allOf(
|
||||
Parser.terminalParser(TokenType.MINUS),
|
||||
Parser.terminalParser(TokenType.INTEGER, lambda val, pos: IntegerLiteral.withValue(int(val), pos)),
|
||||
createNode=lambda minus, integer: IntegerLiteral.withValue(-integer.value, minus.pos)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
parser = Parser.oneOf(
|
||||
integerParser,
|
||||
Parser.terminalParser(TokenType.STRING, lambda val, pos: StringLiteral.withValue(val, pos)),
|
||||
Parser.terminalParser(TokenType.NOTE, lambda val, pos: NoteLiteral.withValue(val, pos)),
|
||||
Parser.terminalParser(TokenType.BOOL, lambda val, pos: BoolLiteral.withValue(val, pos)),
|
||||
)
|
||||
parser = Parser.oneOf(
|
||||
integerParser,
|
||||
Parser.terminalParser(TokenType.STRING, lambda val, pos: StringLiteral.withValue(val, pos)),
|
||||
Parser.terminalParser(TokenType.NOTE, lambda val, pos: NoteLiteral.withValue(val, pos)),
|
||||
Parser.terminalParser(TokenType.BOOL, lambda val, pos: BoolLiteral.withValue(val, pos)),
|
||||
IdentifierParser,
|
||||
)
|
||||
|
||||
AtomParser = Parser(parser, "atom", parser)
|
||||
return Parser(parser, "atom", parser)(input)
|
||||
|
||||
@@ -1,53 +1,119 @@
|
||||
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.operator import LeftAssociativeOperatorNode
|
||||
from smnp.ast.node.atom import Atom
|
||||
from smnp.ast.node.expression import MaxPrecedenceExpressionParser
|
||||
from smnp.ast.node.iterable import abstractIterableParser
|
||||
from smnp.ast.node.model import Node
|
||||
from smnp.ast.node.none import NoneNode
|
||||
from smnp.ast.node.operator import BinaryOperator, Operator
|
||||
from smnp.ast.parser import Parser
|
||||
from smnp.token.type import TokenType
|
||||
|
||||
|
||||
class IdentifierNode(LeftAssociativeOperatorNode):
|
||||
class Identifier(Atom):
|
||||
pass
|
||||
|
||||
|
||||
class FunctionCall(Node):
|
||||
def __init__(self, pos):
|
||||
super().__init__(pos)
|
||||
self.children = [None]
|
||||
self.children = [NoneNode(), NoneNode()]
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self[0]
|
||||
|
||||
@name.setter
|
||||
def name(self, value):
|
||||
self[0] = value
|
||||
|
||||
@property
|
||||
def arguments(self):
|
||||
return self[1]
|
||||
|
||||
@arguments.setter
|
||||
def arguments(self, value):
|
||||
self[1] = value
|
||||
|
||||
@classmethod
|
||||
def _lhsParser(cls):
|
||||
return Parser.oneOf(
|
||||
IdentifierNode._functionCallParser(),
|
||||
IdentifierNode._assignmentParser(),
|
||||
IdentifierNode.identifierParser()
|
||||
)
|
||||
def withChildren(cls, name, arguments):
|
||||
node = cls(name.pos)
|
||||
node.name = name
|
||||
node.arguments = arguments
|
||||
return node
|
||||
|
||||
@staticmethod
|
||||
def _assignmentParser():
|
||||
def createNode(target, assignment, value):
|
||||
node = AssignmentNode(assignment.pos)
|
||||
node.target = target
|
||||
node.value = value
|
||||
return node
|
||||
|
||||
return Parser.allOf(
|
||||
IdentifierNode.identifierParser(),
|
||||
Parser.terminalParser(TokenType.ASSIGN),
|
||||
Parser.doAssert(ExpressionNode.parse, "expression"),
|
||||
createNode=createNode
|
||||
)
|
||||
class ArgumentsList(Node):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def _functionCallParser():
|
||||
def createNode(name, arguments):
|
||||
node = FunctionCallNode(name.pos)
|
||||
node.name = name
|
||||
node.arguments = arguments
|
||||
return node
|
||||
|
||||
return Parser.allOf(
|
||||
IdentifierNode.identifierParser(),
|
||||
ArgumentsListNode.parse,
|
||||
createNode=createNode
|
||||
)
|
||||
class Assignment(BinaryOperator):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def identifierParser():
|
||||
return Parser.terminalParser(TokenType.IDENTIFIER, lambda val, pos: IdentifierNode.withValue(val, pos))
|
||||
|
||||
def IdentifierParser(input):
|
||||
identifierLiteralParser = Parser.terminalParser(TokenType.IDENTIFIER, createNode=lambda val, pos: Identifier.withValue(val, pos))
|
||||
|
||||
functionCallParser = Parser.allOf(
|
||||
identifierLiteralParser,
|
||||
abstractIterableParser(ArgumentsList, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN, MaxPrecedenceExpressionParser),
|
||||
createNode=lambda name, arguments: FunctionCall.withChildren(name, arguments)
|
||||
)
|
||||
|
||||
assignmentParser = Parser.allOf(
|
||||
identifierLiteralParser,
|
||||
Parser.terminalParser(TokenType.ASSIGN, lambda val, pos: Operator.withValue(val, pos)),
|
||||
MaxPrecedenceExpressionParser,
|
||||
createNode=lambda identifier, assign, expr: Assignment.withValues(identifier, assign, expr)
|
||||
)
|
||||
|
||||
return Parser.oneOf(
|
||||
assignmentParser,
|
||||
functionCallParser,
|
||||
identifierLiteralParser
|
||||
)(input)
|
||||
|
||||
|
||||
#
|
||||
# def __init__(self, pos):
|
||||
# super().__init__(pos)
|
||||
# self.children = [None]
|
||||
#
|
||||
# @classmethod
|
||||
# def _lhsParser(cls):
|
||||
# return Parser.oneOf(
|
||||
# IdentifierNode._functionCallParser(),
|
||||
# IdentifierNode._assignmentParser(),
|
||||
# IdentifierNode.identifierParser()
|
||||
# )
|
||||
#
|
||||
# @staticmethod
|
||||
# def _assignmentParser():
|
||||
# def createNode(target, assignment, value):
|
||||
# node = AssignmentNode(assignment.pos)
|
||||
# node.target = target
|
||||
# node.value = value
|
||||
# return node
|
||||
#
|
||||
# return Parser.allOf(
|
||||
# IdentifierNode.identifierParser(),
|
||||
# Parser.terminalParser(TokenType.ASSIGN),
|
||||
# Parser.doAssert(ExpressionNode.parse, "expression"),
|
||||
# createNode=createNode
|
||||
# )
|
||||
#
|
||||
# @staticmethod
|
||||
# def _functionCallParser():
|
||||
# def createNode(name, arguments):
|
||||
# node = FunctionCallNode(name.pos)
|
||||
# node.name = name
|
||||
# node.arguments = arguments
|
||||
# return node
|
||||
#
|
||||
# return Parser.allOf(
|
||||
# IdentifierNode.identifierParser(),
|
||||
# ArgumentsListNode.parse,
|
||||
# createNode=createNode
|
||||
# )
|
||||
#
|
||||
# @staticmethod
|
||||
# def identifierParser():
|
||||
# return Parser.terminalParser(TokenType.IDENTIFIER, lambda val, pos: IdentifierNode.withValue(val, pos))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from smnp.ast.node.identifier import IdentifierNode
|
||||
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
|
||||
@@ -58,7 +58,7 @@ class ImportNode(Node):
|
||||
Parser.doAssert(Parser.terminalParser(TokenType.FROM), "'from <source> as <variable name>'"),
|
||||
Parser.doAssert(StringLiteralNode._literalParser(), "source as a string"),
|
||||
Parser.doAssert(Parser.terminalParser(TokenType.AS), "'as <variable name>'"),
|
||||
Parser.doAssert(IdentifierNode.identifierParser(), "variable name"),
|
||||
Parser.doAssert(Identifier.identifierParser(), "variable name"),
|
||||
createNode=createNode
|
||||
)
|
||||
|
||||
|
||||
@@ -1,42 +1,42 @@
|
||||
from smnp.ast.node.expression import ExpressionNode
|
||||
from smnp.ast.node.iterable import abstractIterableParser
|
||||
from smnp.ast.node.model import Node
|
||||
from smnp.ast.node.none import NoneNode
|
||||
from smnp.ast.node.operator import LeftAssociativeOperatorNode
|
||||
from smnp.ast.parser import Parser
|
||||
from smnp.token.type import TokenType
|
||||
|
||||
|
||||
class ArgumentsListNode(Node):
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, input):
|
||||
return abstractIterableParser(ArgumentsListNode, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN,
|
||||
Parser.doAssert(ExpressionNode.parse, "expression"))(input)
|
||||
|
||||
|
||||
class FunctionCallNode(LeftAssociativeOperatorNode):
|
||||
def __init__(self, pos):
|
||||
super().__init__(pos)
|
||||
self.children = [NoneNode(), NoneNode()]
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self[0]
|
||||
|
||||
@name.setter
|
||||
def name(self, value):
|
||||
self[0] = value
|
||||
|
||||
@property
|
||||
def arguments(self):
|
||||
return self[1]
|
||||
|
||||
@arguments.setter
|
||||
def arguments(self, value):
|
||||
self[1] = value
|
||||
|
||||
@classmethod
|
||||
def _parse(cls, input):
|
||||
raise RuntimeError("This class is not supposed to be automatically called")
|
||||
|
||||
# from smnp.ast.node.expression import ExpressionNode
|
||||
# from smnp.ast.node.iterable import abstractIterableParser
|
||||
# from smnp.ast.node.model import Node
|
||||
# from smnp.ast.node.none import NoneNode
|
||||
# from smnp.ast.node.operator import LeftAssociativeOperatorNode
|
||||
# from smnp.ast.parser import Parser
|
||||
# from smnp.token.type import TokenType
|
||||
#
|
||||
#
|
||||
# class ArgumentsListNode(Node):
|
||||
#
|
||||
# @classmethod
|
||||
# def _parse(cls, input):
|
||||
# return abstractIterableParser(ArgumentsListNode, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN,
|
||||
# Parser.doAssert(ExpressionNode.parse, "expression"))(input)
|
||||
#
|
||||
#
|
||||
# class FunctionCallNode(LeftAssociativeOperatorNode):
|
||||
# def __init__(self, pos):
|
||||
# super().__init__(pos)
|
||||
# self.children = [NoneNode(), NoneNode()]
|
||||
#
|
||||
# @property
|
||||
# def name(self):
|
||||
# return self[0]
|
||||
#
|
||||
# @name.setter
|
||||
# def name(self, value):
|
||||
# self[0] = value
|
||||
#
|
||||
# @property
|
||||
# def arguments(self):
|
||||
# return self[1]
|
||||
#
|
||||
# @arguments.setter
|
||||
# def arguments(self, value):
|
||||
# self[1] = value
|
||||
#
|
||||
# @classmethod
|
||||
# def _parse(cls, input):
|
||||
# raise RuntimeError("This class is not supposed to be automatically called")
|
||||
#
|
||||
|
||||
@@ -112,4 +112,10 @@ class Operator(Node):
|
||||
|
||||
@value.setter
|
||||
def value(self, value):
|
||||
self[0] = value
|
||||
self[0] = value
|
||||
|
||||
@classmethod
|
||||
def withValue(cls, value, pos):
|
||||
node = cls(pos)
|
||||
node.value = value
|
||||
return node
|
||||
@@ -15,7 +15,8 @@ def parse(input):
|
||||
|
||||
|
||||
#TODO -> temporary (to remove):
|
||||
MaxPrecedenceExpressionParser
|
||||
MaxPrecedenceExpressionParser,
|
||||
exception=RuntimeError("Nie znam tego wyrazenia")
|
||||
)(input)
|
||||
|
||||
if result.result:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from smnp.ast.node.identifier import IdentifierNode
|
||||
from smnp.ast.node.identifier import Identifier
|
||||
from smnp.ast.node.invocation import FunctionCallNode
|
||||
from smnp.error.runtime import RuntimeException
|
||||
from smnp.runtime.evaluator import Evaluator
|
||||
@@ -14,7 +14,7 @@ class AccessEvaluator(Evaluator):
|
||||
left = expressionEvaluator(doAssert=True)(node.left, environment).value #TODO check if it isn't necessary to verify 'result' attr of EvaluatioNResult
|
||||
right = node.right
|
||||
|
||||
if type(right) == IdentifierNode:
|
||||
if type(right) == Identifier:
|
||||
try:
|
||||
return left.properties[right.value]
|
||||
except KeyError:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from smnp.ast.node.identifier import IdentifierNode
|
||||
from smnp.ast.node.identifier import Identifier
|
||||
from smnp.runtime.evaluator import evaluate, Evaluator, EvaluationResult
|
||||
from smnp.runtime.evaluators.expression import expressionEvaluator
|
||||
from smnp.type.model import Type
|
||||
@@ -40,7 +40,7 @@ class AsteriskEvaluator(Evaluator):
|
||||
|
||||
@classmethod
|
||||
def _automaticNamedVariable(cls, iteratorNode, environment, prefix=''):
|
||||
if type(iteratorNode) == IdentifierNode:
|
||||
if type(iteratorNode) == Identifier:
|
||||
return cls._automaticVariableName(environment, prefix, iteratorNode.value, False)
|
||||
else:
|
||||
return cls._automaticVariableName(environment, prefix, '', True)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from smnp.ast.node.assignment import AssignmentNode
|
||||
from smnp.ast.node.asterisk import AsteriskNode
|
||||
from smnp.ast.node.bool import BoolLiteralNode
|
||||
from smnp.ast.node.identifier import IdentifierNode
|
||||
from smnp.ast.node.identifier import Identifier
|
||||
from smnp.ast.node.integer import IntegerLiteralNode
|
||||
from smnp.ast.node.invocation import FunctionCallNode
|
||||
from smnp.ast.node.list import List
|
||||
@@ -37,7 +37,7 @@ def expressionEvaluator(doAssert=False):
|
||||
Evaluator.forNodes(NoteEvaluator.evaluate, NoteLiteralNode),
|
||||
Evaluator.forNodes(BoolEvaluator.evaluate, BoolLiteralNode),
|
||||
Evaluator.forNodes(TypeEvaluator.evaluate, TypeNode),
|
||||
Evaluator.forNodes(IdentifierEvaluator.evaluate, IdentifierNode),
|
||||
Evaluator.forNodes(IdentifierEvaluator.evaluate, Identifier),
|
||||
Evaluator.forNodes(ListEvaluator.evaluate, List),
|
||||
Evaluator.forNodes(AccessEvaluator.evaluate, LeftAssociativeOperatorNode),
|
||||
Evaluator.forNodes(AssignmentEvaluator.evaluate, AssignmentNode),
|
||||
|
||||
Reference in New Issue
Block a user