diff --git a/smnp/ast/node/expression.py b/smnp/ast/node/expression.py index 4d0ea0d..f4b87f5 100644 --- a/smnp/ast/node/expression.py +++ b/smnp/ast/node/expression.py @@ -1,11 +1,22 @@ from smnp.ast.node.operator import BinaryOperator from smnp.ast.node.term import TermParser -from smnp.ast.node.valuable import Valuable from smnp.ast.parser import Parser 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 @@ -16,28 +27,28 @@ def ExpressionParser(input): TermParser, [TokenType.PLUS, TokenType.MINUS], TermParser, - lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right)) + lambda left, op, right: Sum.withValues(left, op, right) ) expr2 = Parser.leftAssociativeOperatorParser( expr1, [TokenType.RELATION, TokenType.OPEN_ANGLE, TokenType.CLOSE_ANGLE], expr1, - lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right)) + lambda left, op, right: Relation.withValues(left, op, right) ) expr3 = Parser.leftAssociativeOperatorParser( expr2, [TokenType.AND], expr2, - lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right)) + lambda left, op, right: And.withValues(left, op, right) ) expr4 = Parser.leftAssociativeOperatorParser( expr3, [TokenType.OR], expr3, - lambda left, op, right: Expression.withValue(BinaryOperator.withValues(left, op, right)) + lambda left, op, right: Or.withValues(left, op, right) ) ifElseExpression = Parser.allOf( diff --git a/smnp/runtime/evaluators/expression.py b/smnp/runtime/evaluators/expression.py index 88abfd0..4259444 100644 --- a/smnp/runtime/evaluators/expression.py +++ b/smnp/runtime/evaluators/expression.py @@ -1,3 +1,4 @@ +from smnp.ast.node.expression import Sum from smnp.ast.node.factor import NotOperator, Power, Loop from smnp.ast.node.identifier import FunctionCall, Assignment 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.product import ProductEvaluator + from smnp.runtime.evaluators.sum import SumEvaluator result = Evaluator.oneOf( Evaluator.forNodes(FunctionCallEvaluator.evaluate, FunctionCall), Evaluator.forNodes(MinusEvaluator.evaluate, MinusOperator), @@ -28,6 +30,7 @@ def expressionEvaluator(doAssert=False): Evaluator.forNodes(LoopEvaluator.evaluate, Loop), Evaluator.forNodes(AssignmentEvaluator.evaluate, Assignment), Evaluator.forNodes(ProductEvaluator.evaluate, Product), + Evaluator.forNodes(SumEvaluator.evaluate, Sum), AtomEvaluator.evaluate )(node, environment) diff --git a/smnp/runtime/evaluators/sum.py b/smnp/runtime/evaluators/sum.py new file mode 100644 index 0000000..bcb7f9f --- /dev/null +++ b/smnp/runtime/evaluators/sum.py @@ -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") \ No newline at end of file