From 8f51893f534267d97c82197c6e0320f0f8549bd3 Mon Sep 17 00:00:00 2001 From: Kodjo Sossouvi Date: Thu, 11 Mar 2021 11:50:23 +0100 Subject: [PATCH] Working on #48 : Updating ExpressionParser.py --- src/parsers/ExpressionParser.py | 5 +++-- src/parsers/LogicalOperatorParser.py | 6 ++++-- src/parsers/RelationalOperatorParser.py | 2 +- tests/parsers/test_ExpressionParser.py | 17 +++++++++++++++-- 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/parsers/ExpressionParser.py b/src/parsers/ExpressionParser.py index 2891eaa..d9437be 100644 --- a/src/parsers/ExpressionParser.py +++ b/src/parsers/ExpressionParser.py @@ -20,8 +20,8 @@ class ExpressionParser(BaseExprParser): super().__init__(ExpressionParser.NAME, 60, False, yield_eof=False) self.variable_parser = VariableOrNamesParser() self.function_parser = FunctionParser() - self.relational_parser = RelationalOperatorParser() - self.logical_parser = LogicalOperatorParser(expr_parser=self.variable_parser) + self.relational_parser = RelationalOperatorParser(expr_parser=self.variable_parser) + self.logical_parser = LogicalOperatorParser(expr_parser=self.relational_parser) def parse(self, context, parser_input: ParserInput): """ @@ -64,6 +64,7 @@ class ExpressionParser(BaseExprParser): def parse_input(self, context, parser_input, error_sink): pos = parser_input.pos for parser in [self.logical_parser, + self.relational_parser, self.variable_parser]: # [self.logical_parser, self.relational_parser, self.function_parser]: parser_input.seek(pos) # reset position res = parser.parse_input(context, parser_input, error_sink) diff --git a/src/parsers/LogicalOperatorParser.py b/src/parsers/LogicalOperatorParser.py index a8ad62a..8874988 100644 --- a/src/parsers/LogicalOperatorParser.py +++ b/src/parsers/LogicalOperatorParser.py @@ -185,7 +185,8 @@ class LogicalOperatorParser(BaseExprParser): def parse_not(self, context, parser_input, error_sink): token = parser_input.token start = parser_input.pos - if token.type == TokenKind.IDENTIFIER and token.value == "not": + if (token.type == TokenKind.IDENTIFIER and token.value == "not" and + parser_input.the_token_after(True).value != "in"): parser_input.next_token() parsed = self.parse_not(context, parser_input, error_sink) node = parsed.node if isinstance(parsed, ParenthesisNode) else parsed @@ -201,7 +202,8 @@ class LogicalOperatorParser(BaseExprParser): def stop(): return token.type == TokenKind.EOF or \ paren_count == 0 and token.type == TokenKind.RPAR or \ - token.type == TokenKind.IDENTIFIER and token.value in ("and", "or", "not") + token.type == TokenKind.IDENTIFIER and token.value in ("and", "or") or \ + token.value == "not" and parser_input.the_token_after(True).value != "in" token = parser_input.token if token.type == TokenKind.EOF: diff --git a/src/parsers/RelationalOperatorParser.py b/src/parsers/RelationalOperatorParser.py index ba26c75..e655ed1 100644 --- a/src/parsers/RelationalOperatorParser.py +++ b/src/parsers/RelationalOperatorParser.py @@ -167,7 +167,7 @@ class RelationalOperatorParser(BaseExprParser): @staticmethod def eat_comparison(parser_input, eat=True): token = parser_input.token - if token.type == TokenKind.EQUALSEQUALS: + if token.type in (TokenKind.EQUALS, TokenKind.EQUALSEQUALS): if eat: parser_input.next_token() return ComparisonType.EQUALS diff --git a/tests/parsers/test_ExpressionParser.py b/tests/parsers/test_ExpressionParser.py index e7bd1ef..075b7b3 100644 --- a/tests/parsers/test_ExpressionParser.py +++ b/tests/parsers/test_ExpressionParser.py @@ -7,7 +7,8 @@ from parsers.BaseParser import ErrorSink from parsers.ExpressionParser import ExpressionParser from parsers.expressions import VariableNode from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka -from tests.parsers.parsers_utils import get_expr_node_from_test_node, VAR, EXPR, AND +from tests.parsers.parsers_utils import get_expr_node_from_test_node, VAR, EXPR, AND, OR, NOT, GT, GTE, LT, LTE, EQ, \ + NEQ, IN, NIN class TestExpressionParser(TestUsingMemoryBasedSheerka): @@ -34,7 +35,19 @@ class TestExpressionParser(TestUsingMemoryBasedSheerka): ("var1 + var2", EXPR("var1 + var2")), ("variable", VAR("variable")), ("var.attr", VAR("var.attr")), - ("var1 and var2", AND(VAR("var1"), VAR("var2"))) + ("var1 and var2", AND(VAR("var1"), VAR("var2"))), + ("var1 or var2", OR(VAR("var1"), VAR("var2"))), + ("not var", NOT(VAR("var"))), + ("var1 > var2", GT(VAR("var1"), VAR("var2"))), + ("var1 >= var2", GTE(VAR("var1"), VAR("var2"))), + ("var1 < var2", LT(VAR("var1"), VAR("var2"))), + ("var1 <= var2", LTE(VAR("var1"), VAR("var2"))), + ("var1 = var2", EQ(VAR("var1"), VAR("var2"))), + ("var1 == var2", EQ(VAR("var1"), VAR("var2"))), + ("var1 != var2", NEQ(VAR("var1"), VAR("var2"))), + ("var1 in (var2.attr2, var3.attr3)", IN(VAR("var1"), EXPR("var2.attr2, var3.attr3"))), + ("var1 not in (var2.attr2, var3.attr3)", NIN(VAR("var1"), EXPR("var2.attr2, var3.attr3"))), + ]) def test_i_can_parse_input(self, expression, expected): sheerka, context, parser, parser_input, error_sink = self.input_parser_with_source(expression)