Create evaluator for sum (sum, subtraction and string concatenation)

This commit is contained in:
Bartłomiej Pluta
2019-07-12 20:56:42 +02:00
parent 1094c071fb
commit dc3387c685
3 changed files with 60 additions and 6 deletions

View File

@@ -1,11 +1,22 @@
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 Expression(Valuable): class Sum(BinaryOperator):
pass
class Relation(BinaryOperator):
pass
class And(BinaryOperator):
pass
class Or(BinaryOperator):
pass pass
@@ -16,28 +27,28 @@ def ExpressionParser(input):
TermParser, TermParser,
[TokenType.PLUS, TokenType.MINUS], [TokenType.PLUS, TokenType.MINUS],
TermParser, TermParser,
lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right)) lambda left, op, right: Sum.withValues(left, op, right)
) )
expr2 = Parser.leftAssociativeOperatorParser( expr2 = Parser.leftAssociativeOperatorParser(
expr1, expr1,
[TokenType.RELATION, TokenType.OPEN_ANGLE, TokenType.CLOSE_ANGLE], [TokenType.RELATION, TokenType.OPEN_ANGLE, TokenType.CLOSE_ANGLE],
expr1, expr1,
lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right)) lambda left, op, right: Relation.withValues(left, op, right)
) )
expr3 = Parser.leftAssociativeOperatorParser( expr3 = Parser.leftAssociativeOperatorParser(
expr2, expr2,
[TokenType.AND], [TokenType.AND],
expr2, expr2,
lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right)) lambda left, op, right: And.withValues(left, op, right)
) )
expr4 = Parser.leftAssociativeOperatorParser( expr4 = Parser.leftAssociativeOperatorParser(
expr3, expr3,
[TokenType.OR], [TokenType.OR],
expr3, expr3,
lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right)) lambda left, op, right: Or.withValues(left, op, right)
) )
ifElseExpression = Parser.allOf( ifElseExpression = Parser.allOf(

View File

@@ -1,3 +1,4 @@
from smnp.ast.node.expression import Sum
from smnp.ast.node.factor import NotOperator, Power, Loop from smnp.ast.node.factor import NotOperator, Power, Loop
from smnp.ast.node.identifier import FunctionCall, Assignment from smnp.ast.node.identifier import FunctionCall, Assignment
from smnp.ast.node.term import Product from smnp.ast.node.term import Product
@@ -19,6 +20,7 @@ def expressionEvaluator(doAssert=False):
from smnp.runtime.evaluators.assignment import AssignmentEvaluator from smnp.runtime.evaluators.assignment import AssignmentEvaluator
from smnp.runtime.evaluators.product import ProductEvaluator from smnp.runtime.evaluators.product import ProductEvaluator
from smnp.runtime.evaluators.sum import SumEvaluator
result = Evaluator.oneOf( result = Evaluator.oneOf(
Evaluator.forNodes(FunctionCallEvaluator.evaluate, FunctionCall), Evaluator.forNodes(FunctionCallEvaluator.evaluate, FunctionCall),
Evaluator.forNodes(MinusEvaluator.evaluate, MinusOperator), Evaluator.forNodes(MinusEvaluator.evaluate, MinusOperator),
@@ -28,6 +30,7 @@ def expressionEvaluator(doAssert=False):
Evaluator.forNodes(LoopEvaluator.evaluate, Loop), Evaluator.forNodes(LoopEvaluator.evaluate, Loop),
Evaluator.forNodes(AssignmentEvaluator.evaluate, Assignment), Evaluator.forNodes(AssignmentEvaluator.evaluate, Assignment),
Evaluator.forNodes(ProductEvaluator.evaluate, Product), Evaluator.forNodes(ProductEvaluator.evaluate, Product),
Evaluator.forNodes(SumEvaluator.evaluate, Sum),
AtomEvaluator.evaluate AtomEvaluator.evaluate
)(node, environment) )(node, environment)

View File

@@ -0,0 +1,40 @@
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)
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")