diff --git a/src/parser/MatchPath.h b/src/parser/MatchPath.h index 487ad0dba8b..e22e4027191 100644 --- a/src/parser/MatchPath.h +++ b/src/parser/MatchPath.h @@ -218,12 +218,13 @@ class MatchNodeLabelList final { class MatchNode final { public: - MatchNode(const std::string& alias, MatchNodeLabelList* labels, Expression* props = nullptr) { + MatchNode(const std::string& alias = "", + MatchNodeLabelList* labels = nullptr, + Expression* props = nullptr) { alias_ = alias; labels_.reset(labels); props_ = static_cast(props); } - MatchNode() = default; void setAlias(const std::string& alias) { alias_ = alias; diff --git a/src/parser/parser.yy b/src/parser/parser.yy index a969625f581..b9708c060a4 100644 --- a/src/parser/parser.yy +++ b/src/parser/parser.yy @@ -1,8 +1,7 @@ // Bison options %language "C++" -%skeleton "glr.cc" -%glr-parser -%no-lines +%skeleton "lalr1.cc" +%no-lines %locations %define api.namespace { nebula } %define api.parser.class { GraphParser } @@ -217,10 +216,11 @@ using namespace nebula; %token KW_MERGE KW_DIVIDE KW_RENAME /* symbols */ -%token L_PAREN R_PAREN L_BRACKET R_BRACKET L_BRACE R_BRACE COMMA -%token PIPE ASSIGN -%token DOT DOT_DOT COLON QM 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 +%token L_PAREN R_PAREN L_BRACKET R_BRACKET L_BRACE R_BRACE COMMA + MINUS_L_BRACKET R_BRACKET_MINUS L_ARROW_L_BRACKET R_BRACKET_R_ARROW PIPE + MINUS_MINUS MINUS_R_ARROW L_ARROW_MINUS L_ARROW_R_ARROW ASSIGN DOT DOT_DOT + COLON QM SEMICOLON L_ARROW R_ARROW AT ID_PROP TYPE_PROP + SRC_ID_PROP DST_ID_PROP RANK_PROP INPUT_REF DST_REF SRC_REF /* token type specification */ %token BOOL @@ -747,10 +747,10 @@ constant_expression ; compound_expression - : match_path_pattern_expression %dprec 2 { + : match_path_pattern_expression { $$ = $1; } - | parenthesized_expression %dprec 1 { + | parenthesized_expression { $$ = $1; } | property_expression { @@ -1797,9 +1797,16 @@ match_path_list } match_node - : L_PAREN match_alias R_PAREN { - $$ = new MatchNode(*$2, nullptr, nullptr); - delete $2; + : L_PAREN R_PAREN { + $$ = new MatchNode(); + } + | parenthesized_expression { + auto& e = $1; + if (e->kind() != Expression::Kind::kLabel) { + delete $1; + throw nebula::GraphParser::syntax_error(@1, "Invalid node pattern"); + } + $$ = new MatchNode(static_cast(e)->name(), nullptr, nullptr); } | L_PAREN match_alias match_node_label_list R_PAREN { $$ = new MatchNode(*$2, $3, nullptr); @@ -1841,31 +1848,40 @@ match_alias ; match_edge - : MINUS match_edge_prop MINUS { + : MINUS_MINUS { + $$ = new MatchEdge(nullptr, storage::cpp2::EdgeDirection::BOTH); + } + | MINUS_R_ARROW { + $$ = new MatchEdge(nullptr, storage::cpp2::EdgeDirection::OUT_EDGE); + } + | L_ARROW_MINUS { + $$ = new MatchEdge(nullptr, storage::cpp2::EdgeDirection::IN_EDGE); + } + | L_ARROW_R_ARROW { + $$ = new MatchEdge(nullptr, storage::cpp2::EdgeDirection::BOTH); + } + | MINUS_L_BRACKET match_edge_prop R_BRACKET_MINUS { $$ = new MatchEdge($2, storage::cpp2::EdgeDirection::BOTH); } - | MINUS match_edge_prop R_ARROW { + | MINUS_L_BRACKET match_edge_prop R_BRACKET_R_ARROW { $$ = new MatchEdge($2, storage::cpp2::EdgeDirection::OUT_EDGE); } - | L_ARROW match_edge_prop MINUS { + | L_ARROW_L_BRACKET match_edge_prop R_BRACKET_MINUS { $$ = new MatchEdge($2, storage::cpp2::EdgeDirection::IN_EDGE); } - | L_ARROW match_edge_prop R_ARROW { + | L_ARROW_L_BRACKET match_edge_prop R_BRACKET_R_ARROW { $$ = new MatchEdge($2, storage::cpp2::EdgeDirection::BOTH); } ; match_edge_prop - : %empty { - $$ = nullptr; - } - | L_BRACKET match_alias opt_match_edge_type_list match_step_range R_BRACKET { - $$ = new MatchEdgeProp(*$2, $3, $4, nullptr); - delete $2; + : match_alias opt_match_edge_type_list match_step_range { + $$ = new MatchEdgeProp(*$1, $2, $3, nullptr); + delete $1; } - | L_BRACKET match_alias opt_match_edge_type_list match_step_range map_expression R_BRACKET { - $$ = new MatchEdgeProp(*$2, $3, $4, $5); - delete $2; + | match_alias opt_match_edge_type_list match_step_range map_expression { + $$ = new MatchEdgeProp(*$1, $2, $3, $4); + delete $1; } ; diff --git a/src/parser/scanner.lex b/src/parser/scanner.lex index cbc40b42b17..283302135ab 100644 --- a/src/parser/scanner.lex +++ b/src/parser/scanner.lex @@ -357,6 +357,16 @@ LABEL_FULL_WIDTH {CN_EN_FULL_WIDTH}{CN_EN_NUM_FULL_WIDTH}* "<-" { return TokenType::L_ARROW; } "->" { return TokenType::R_ARROW; } + +"-[" { return TokenType::MINUS_L_BRACKET; } +"]-" { return TokenType::R_BRACKET_MINUS; } +"<-[" { return TokenType::L_ARROW_L_BRACKET; } +"]->" { return TokenType::R_BRACKET_R_ARROW; } +"--" { return TokenType::MINUS_MINUS; } +"-->" { return TokenType::MINUS_R_ARROW; } +"<--" { return TokenType::L_ARROW_MINUS; } +"<-->" { return TokenType::L_ARROW_R_ARROW; } + "_id" { return TokenType::ID_PROP; } "_type" { return TokenType::TYPE_PROP; } "_src" { return TokenType::SRC_ID_PROP; } diff --git a/tests/tck/features/match/Base.feature b/tests/tck/features/match/Base.feature index 3f93d4be2c6..4b88192217e 100644 --- a/tests/tck/features/match/Base.feature +++ b/tests/tck/features/match/Base.feature @@ -1285,3 +1285,25 @@ Feature: Basic match | ("Tony Parker") | | ("Tracy McGrady") | | ("Marco Belinelli") | + When executing query: + """ + MATCH (v:player{name: 'Tim Duncan'})-[e:like*0..2]-(v2) + WHERE size([ii in e WHERE (v)-[ii]-(v2) | ii])>1 + RETURN count(*) AS cnt + """ + # FIXME(czp): Fix this case after https://github.com/vesoft-inc/nebula/issues/5289 closed + Then a SemanticError should be raised at runtime: PatternExpression are not allowed to introduce new variables: `ii'. + +# Then the result should be, in any order: +# | cnt | +# | 0 | +# When executing query: +# """ +# MATCH (v:player{name: 'Tim Duncan'})-[e:like*0..2]-(v2)-[i]-(v3) +# WHERE size([i in e WHERE (v)-[i]-(v2) | i])>1 +# RETURN count(*) AS cnt +# """ +# FIXME(czp): Fix this case after https://github.com/vesoft-inc/nebula/issues/5289 closed +# Then the result should be, in any order: +# | cnt | +# | 0 | diff --git a/tests/tck/features/match/Unwind.feature b/tests/tck/features/match/Unwind.feature index dc55a12d8e0..e4275af6e4d 100644 --- a/tests/tck/features/match/Unwind.feature +++ b/tests/tck/features/match/Unwind.feature @@ -149,7 +149,7 @@ Feature: Unwind clause Then a SyntaxError should be raised at runtime: syntax error near `WITH' When executing query: """ - MATCH (a:player {name:"Tim Duncan"}) - [e:like] -> (b) + MATCH (a:player {name:"Tim Duncan"})-[e:like]->(b) UNWIND count(b) as num RETURN num """ diff --git a/tests/tck/features/yield/return.feature b/tests/tck/features/yield/return.feature index 468cbe93000..9a74c3ae9cd 100644 --- a/tests/tck/features/yield/return.feature +++ b/tests/tck/features/yield/return.feature @@ -14,6 +14,40 @@ Feature: Return. A standalone return sentence is actually a yield sentence Then the result should be, in any order: | sum | | 2 | + When executing query: + """ + RETURN 1- -1 AS sub + """ + Then the result should be, in any order: + | sub | + | 2 | + When executing query: + """ + RETURN 1--1 AS sub + """ + Then a SyntaxError should be raised at runtime: syntax error near `--' + When executing query: + """ + RETURN [2,3 ] - [3] AS sub + """ + Then a SemanticError should be raised at runtime: `([2,3]-[3])' is not a valid expression, can not apply `-' to `LIST' and `LIST'. + When executing query: + """ + RETURN [2,3 ]-[3] AS sub + """ + Then a SyntaxError should be raised at runtime: syntax error near `]-' + # When executing query: + # """ + # WITH [2,3] AS a, 3 AS b, [2] AS c return (a)-[b]-(c) + # """ + # FIXME(czp): Fix this after https://github.com/vesoft-inc/nebula/issues/5288 closed + # Then a semanticError should be raised at runtime: `a' is defined with type Runtime, but referenced with type Node + # When executing query: + # """ + # WITH [2,3] AS a, 3 AS b, [2] AS c return (a)- [b] -(c) + # """ + # FIXME(czp): Fix this after https://github.com/vesoft-inc/nebula/issues/5288 closed + # Then a semanticError should be raised at runtime: `(a)- [b]' is not a valid expression, can not apply `-' to `LIST' and `LIST'. When executing query: """ RETURN DISTINCT 1+1, '1+1', (int)3.14, (string)(1+1), (string)true diff --git a/tests/tck/features/yield/yield.IntVid.feature b/tests/tck/features/yield/yield.IntVid.feature index a6245d18a08..7955f856c6b 100644 --- a/tests/tck/features/yield/yield.IntVid.feature +++ b/tests/tck/features/yield/yield.IntVid.feature @@ -514,7 +514,7 @@ Feature: Yield Sentence | -9223372036854775808 | When executing query: """ - YIELD --9223372036854775808 + YIELD - -9223372036854775808 """ Then a SemanticError should be raised at runtime: result of -(-9223372036854775808) cannot be represented as an integer When executing query: @@ -656,7 +656,7 @@ Feature: Yield Sentence Scenario: WithComment When executing query: """ - YIELD 1--1 + YIELD 1- -1 """ Then the result should be, in any order: | (1--(1)) | diff --git a/tests/tck/features/yield/yield.feature b/tests/tck/features/yield/yield.feature index db9ad24b36c..d6f092cb00d 100644 --- a/tests/tck/features/yield/yield.feature +++ b/tests/tck/features/yield/yield.feature @@ -524,7 +524,7 @@ Feature: Yield Sentence | -9223372036854775808 | When executing query: """ - YIELD --9223372036854775808 + YIELD - -9223372036854775808 """ Then a SemanticError should be raised at runtime: result of -(-9223372036854775808) cannot be represented as an integer When executing query: @@ -666,7 +666,7 @@ Feature: Yield Sentence Scenario: WithComment When executing query: """ - YIELD 1--1 + YIELD 1- -1 """ Then the result should be, in any order, with relax comparison: | (1--(1)) |