Add support for assignments, function calls and pure identifiers

This commit is contained in:
Bartłomiej Pluta
2019-07-10 23:19:46 +02:00
parent 24b1012c7c
commit 18884eb5d9
10 changed files with 210 additions and 133 deletions

View File

@@ -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")

View File

@@ -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)

View File

@@ -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))

View File

@@ -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
)

View File

@@ -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")
#

View File

@@ -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

View File

@@ -15,7 +15,8 @@ def parse(input):
#TODO -> temporary (to remove):
MaxPrecedenceExpressionParser
MaxPrecedenceExpressionParser,
exception=RuntimeError("Nie znam tego wyrazenia")
)(input)
if result.result:

View File

@@ -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:

View File

@@ -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)

View File

@@ -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),