From cd9126aae8922e6cb47da1308d800e8746ffdd9f Mon Sep 17 00:00:00 2001
From: laura-ding <48548375+laura-ding@users.noreply.github.com>
Date: Thu, 12 Sep 2019 09:39:24 +0800
Subject: [PATCH] Add logic xor and Arithmetic ^ (#858)

---
 src/executor/test/YieldTest.cpp | 54 +++++++++++++++++++++++++++++++++
 src/parser/parser.yy            | 41 +++++++++++++++++++------
 src/parser/scanner.lex          |  5 +++
 src/parser/test/ScannerTest.cpp |  9 ++++++
 4 files changed, 100 insertions(+), 9 deletions(-)

diff --git a/src/executor/test/YieldTest.cpp b/src/executor/test/YieldTest.cpp
index 94788f05..865635ed 100644
--- a/src/executor/test/YieldTest.cpp
+++ b/src/executor/test/YieldTest.cpp
@@ -149,5 +149,59 @@ TEST_F(YieldTest, hashCall) {
     }
 }
 
+TEST_F(YieldTest, Logic) {
+    auto client = gEnv->getClient();
+    ASSERT_NE(nullptr, client);
+    {
+        cpp2::ExecutionResponse resp;
+        std::string query = "YIELD NOT 0 || 0 AND 0 XOR 0";
+        auto code = client->execute(query, resp);
+        ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
+        std::vector<std::tuple<int64_t>> expected{
+            1
+        };
+        ASSERT_TRUE(verifyResult(resp, expected));
+    }
+    {
+        cpp2::ExecutionResponse resp;
+        std::string query = "YIELD !0 OR 0 && 0 XOR 1";
+        auto code = client->execute(query, resp);
+        ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
+        std::vector<std::tuple<int64_t>> expected{
+            0
+        };
+        ASSERT_TRUE(verifyResult(resp, expected));
+    }
+    {
+        cpp2::ExecutionResponse resp;
+        std::string query = "YIELD (NOT 0 || 0) AND 0 XOR 1";
+        auto code = client->execute(query, resp);
+        ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
+        std::vector<std::tuple<int64_t>> expected{
+            1
+        };
+        ASSERT_TRUE(verifyResult(resp, expected));
+    }
+    {
+        cpp2::ExecutionResponse resp;
+        std::string query = "YIELD 2.5 % 1.2 ^ 1.6";
+        auto code = client->execute(query, resp);
+        ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
+        std::vector<std::tuple<double>> expected{
+            2.5
+        };
+        ASSERT_TRUE(verifyResult(resp, expected));
+    }
+    {
+        cpp2::ExecutionResponse resp;
+        std::string query = "YIELD (5 % 3) ^ 1";
+        auto code = client->execute(query, resp);
+        ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
+        std::vector<std::tuple<int64_t>> expected{
+            3
+        };
+        ASSERT_TRUE(verifyResult(resp, expected));
+    }
+}
 }   // namespace graph
 }   // namespace nebula
diff --git a/src/parser/parser.yy b/src/parser/parser.yy
index 78739af2..670d2f7a 100644
--- a/src/parser/parser.yy
+++ b/src/parser/parser.yy
@@ -92,7 +92,7 @@ class GraphScanner;
 %destructor { delete $$; } <*>
 
 /* keywords */
-%token KW_GO KW_AS KW_TO KW_OR KW_USE KW_SET KW_FROM KW_WHERE KW_ALTER
+%token KW_GO KW_AS KW_TO KW_OR KW_AND KW_XOR KW_USE KW_SET KW_FROM KW_WHERE KW_ALTER
 %token KW_MATCH KW_INSERT KW_VALUES KW_YIELD KW_RETURN KW_CREATE KW_VERTEX
 %token KW_EDGE KW_EDGES KW_UPDATE KW_STEPS KW_OVER KW_UPTO KW_REVERSELY KW_SPACE KW_DELETE KW_FIND
 %token KW_INT KW_BIGINT KW_DOUBLE KW_STRING KW_BOOL KW_TAG KW_TAGS KW_UNION KW_INTERSECT KW_MINUS
@@ -109,7 +109,7 @@ class GraphScanner;
 %token KW_BALANCE KW_LEADER
 /* symbols */
 %token L_PAREN R_PAREN L_BRACKET R_BRACKET L_BRACE R_BRACE COMMA
-%token PIPE OR AND LT LE GT GE EQ NE PLUS MINUS MUL DIV MOD NOT NEG ASSIGN
+%token PIPE OR AND XOR LT LE GT GE EQ NE PLUS MINUS MUL DIV MOD NOT NEG ASSIGN
 %token DOT COLON SEMICOLON L_ARROW R_ARROW AT
 %token ID_PROP TYPE_PROP SRC_ID_PROP DST_ID_PROP RANK_PROP INPUT_REF DST_REF SRC_REF
 
@@ -120,8 +120,8 @@ class GraphScanner;
 %token <strval> STRING VARIABLE LABEL
 
 %type <strval> name_label unreserved_keyword
-%type <expr> expression logic_or_expression logic_and_expression
-%type <expr> relational_expression multiplicative_expression additive_expression
+%type <expr> expression logic_xor_expression logic_or_expression logic_and_expression
+%type <expr> relational_expression multiplicative_expression additive_expression arithmetic_xor_expression
 %type <expr> unary_expression primary_expression equality_expression
 %type <expr> src_ref_expression
 %type <expr> dst_ref_expression
@@ -353,6 +353,9 @@ unary_expression
     | NOT unary_expression {
         $$ = new UnaryExpression(UnaryExpression::NOT, $2);
     }
+    | KW_NOT unary_expression {
+        $$ = new UnaryExpression(UnaryExpression::NOT, $2);
+    }
     | L_PAREN type_spec R_PAREN unary_expression {
         $$ = new TypeCastingExpression($2, $4);
     }
@@ -367,15 +370,22 @@ type_spec
     | KW_TIMESTAMP { $$ = ColumnType::TIMESTAMP; }
     ;
 
-multiplicative_expression
+arithmetic_xor_expression
     : unary_expression { $$ = $1; }
-    | multiplicative_expression MUL unary_expression {
+    | arithmetic_xor_expression XOR unary_expression {
+        $$ = new ArithmeticExpression($1, ArithmeticExpression::XOR, $3);
+    }
+    ;
+
+multiplicative_expression
+    : arithmetic_xor_expression { $$ = $1; }
+    | multiplicative_expression MUL arithmetic_xor_expression {
         $$ = new ArithmeticExpression($1, ArithmeticExpression::MUL, $3);
     }
-    | multiplicative_expression DIV unary_expression {
+    | multiplicative_expression DIV arithmetic_xor_expression {
         $$ = new ArithmeticExpression($1, ArithmeticExpression::DIV, $3);
     }
-    | multiplicative_expression MOD unary_expression {
+    | multiplicative_expression MOD arithmetic_xor_expression {
         $$ = new ArithmeticExpression($1, ArithmeticExpression::MOD, $3);
     }
     ;
@@ -421,6 +431,9 @@ logic_and_expression
     | logic_and_expression AND equality_expression {
         $$ = new LogicalExpression($1, LogicalExpression::AND, $3);
     }
+    | logic_and_expression KW_AND equality_expression {
+        $$ = new LogicalExpression($1, LogicalExpression::AND, $3);
+    }
     ;
 
 logic_or_expression
@@ -428,10 +441,20 @@ logic_or_expression
     | logic_or_expression OR logic_and_expression {
         $$ = new LogicalExpression($1, LogicalExpression::OR, $3);
     }
+    | logic_or_expression KW_OR logic_and_expression {
+        $$ = new LogicalExpression($1, LogicalExpression::OR, $3);
+    }
     ;
 
-expression
+logic_xor_expression
     : logic_or_expression { $$ = $1; }
+    | logic_xor_expression KW_XOR logic_or_expression {
+        $$ = new LogicalExpression($1, LogicalExpression::XOR, $3);
+    }
+    ;
+
+expression
+    : logic_xor_expression { $$ = $1; }
     ;
 
 go_sentence
diff --git a/src/parser/scanner.lex b/src/parser/scanner.lex
index 5b4e7f72..104484da 100644
--- a/src/parser/scanner.lex
+++ b/src/parser/scanner.lex
@@ -28,6 +28,8 @@ GO                          ([Gg][Oo])
 AS                          ([Aa][Ss])
 TO                          ([Tt][Oo])
 OR                          ([Oo][Rr])
+AND                         ([Aa][Nn][Dd])
+XOR                         ([Xx][Oo][Rr])
 USE                         ([Uu][Ss][Ee])
 SET                         ([Ss][Ee][Tt])
 FROM                        ([Ff][Rr][Oo][Mm])
@@ -132,6 +134,8 @@ IP_OCTET                    ([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])
 {AS}                        { return TokenType::KW_AS; }
 {TO}                        { return TokenType::KW_TO; }
 {OR}                        { return TokenType::KW_OR; }
+{AND}                       { return TokenType::KW_AND; }
+{XOR}                       { return TokenType::KW_XOR; }
 {USE}                       { return TokenType::KW_USE; }
 {SET}                       { return TokenType::KW_SET; }
 {FROM}                      { return TokenType::KW_FROM; }
@@ -232,6 +236,7 @@ IP_OCTET                    ([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])
 "/"                         { return TokenType::DIV; }
 "%"                         { return TokenType::MOD; }
 "!"                         { return TokenType::NOT; }
+"^"                         { return TokenType::XOR; }
 
 "<"                         { return TokenType::LT; }
 "<="                        { return TokenType::LE; }
diff --git a/src/parser/test/ScannerTest.cpp b/src/parser/test/ScannerTest.cpp
index e8a8d663..0fa0f776 100644
--- a/src/parser/test/ScannerTest.cpp
+++ b/src/parser/test/ScannerTest.cpp
@@ -278,6 +278,15 @@ TEST(Scanner, Basic) {
         CHECK_SEMANTIC_TYPE("NOT", TokenType::KW_NOT),
         CHECK_SEMANTIC_TYPE("Not", TokenType::KW_NOT),
         CHECK_SEMANTIC_TYPE("not", TokenType::KW_NOT),
+        CHECK_SEMANTIC_TYPE("OR", TokenType::KW_OR),
+        CHECK_SEMANTIC_TYPE("Or", TokenType::KW_OR),
+        CHECK_SEMANTIC_TYPE("or", TokenType::KW_OR),
+        CHECK_SEMANTIC_TYPE("AND", TokenType::KW_AND),
+        CHECK_SEMANTIC_TYPE("And", TokenType::KW_AND),
+        CHECK_SEMANTIC_TYPE("and", TokenType::KW_AND),
+        CHECK_SEMANTIC_TYPE("XOR", TokenType::KW_XOR),
+        CHECK_SEMANTIC_TYPE("Xor", TokenType::KW_XOR),
+        CHECK_SEMANTIC_TYPE("xor", TokenType::KW_XOR),
         CHECK_SEMANTIC_TYPE("EXISTS", TokenType::KW_EXISTS),
         CHECK_SEMANTIC_TYPE("Exists", TokenType::KW_EXISTS),
         CHECK_SEMANTIC_TYPE("exists", TokenType::KW_EXISTS),
-- 
GitLab