diff --git a/src/antlr4/Cypher.g4 b/src/antlr4/Cypher.g4 index 6a4002efb6..fcd123bca7 100644 --- a/src/antlr4/Cypher.g4 +++ b/src/antlr4/Cypher.g4 @@ -334,8 +334,13 @@ oC_StringListNullOperatorExpression : oC_PropertyOrLabelsExpression ( oC_StringOperatorExpression | oC_ListOperatorExpression | oC_NullOperatorExpression )? ; oC_ListOperatorExpression - : ( SP ? '[' oC_Expression ']' ) - | ( SP ? '[' oC_Expression? ':' oC_Expression? ']' ); + : ( kU_ListExtractOperatorExpression | kU_ListSliceOperatorExpression ) oC_ListOperatorExpression ? ; + +kU_ListExtractOperatorExpression + : SP ? '[' oC_Expression ']' ; + +kU_ListSliceOperatorExpression + : SP ? '[' oC_Expression? ':' oC_Expression? ']' ; oC_StringOperatorExpression : ( ( SP STARTS SP WITH ) | ( SP ENDS SP WITH ) | ( SP CONTAINS ) ) SP? oC_PropertyOrLabelsExpression ; diff --git a/src/parser/include/transformer.h b/src/parser/include/transformer.h index da2f24f683..e67293966d 100644 --- a/src/parser/include/transformer.h +++ b/src/parser/include/transformer.h @@ -128,6 +128,14 @@ class Transformer { CypherParser::OC_ListOperatorExpressionContext& ctx, unique_ptr propertyExpression); + unique_ptr transformListSliceOperatorExpression( + CypherParser::KU_ListSliceOperatorExpressionContext& ctx, + unique_ptr propertyExpression); + + unique_ptr transformListExtractOperatorExpression( + CypherParser::KU_ListExtractOperatorExpressionContext& ctx, + unique_ptr propertyExpression); + unique_ptr transformNullOperatorExpression( CypherParser::OC_NullOperatorExpressionContext& ctx, unique_ptr propertyExpression); diff --git a/src/parser/transformer.cpp b/src/parser/transformer.cpp index f7f52c0009..883bab8415 100644 --- a/src/parser/transformer.cpp +++ b/src/parser/transformer.cpp @@ -498,36 +498,62 @@ unique_ptr Transformer::transformListOperatorExpression( CypherParser::OC_ListOperatorExpressionContext& ctx, unique_ptr propertyExpression) { auto rawExpression = propertyExpression->getRawName() + " " + ctx.getText(); + unique_ptr listOperator; + if (ctx.kU_ListSliceOperatorExpression()) { + listOperator = transformListSliceOperatorExpression( + *ctx.kU_ListSliceOperatorExpression(), move(propertyExpression)); + } else { + listOperator = transformListExtractOperatorExpression( + *ctx.kU_ListExtractOperatorExpression(), move(propertyExpression)); + } + if (ctx.oC_ListOperatorExpression()) { + return transformListOperatorExpression( + *ctx.oC_ListOperatorExpression(), move(listOperator)); + } else { + return listOperator; + } +} - if (ctx.children[1]->getText() == ":" || ctx.children[2]->getText() == ":") { - auto listSlice = - make_unique(LIST_SLICE_FUNC_NAME, move(rawExpression)); - listSlice->addChild(move(propertyExpression)); - if (ctx.children[1]->getText() == ":") { - listSlice->addChild(getZeroLiteral()); - if (ctx.oC_Expression(0)) { - listSlice->addChild(transformExpression(*ctx.oC_Expression(0))); - } else { - listSlice->addChild(getZeroLiteral()); - } +unique_ptr Transformer::transformListSliceOperatorExpression( + CypherParser::KU_ListSliceOperatorExpressionContext& ctx, + unique_ptr propertyExpression) { + auto rawExpression = propertyExpression->getRawName() + " " + ctx.getText(); + auto listSlice = + make_unique(LIST_SLICE_FUNC_NAME, move(rawExpression)); + listSlice->addChild(move(propertyExpression)); + if (ctx.children[1]->getText() == ":") { + listSlice->addChild(getZeroLiteral()); + // Parsing [:right] syntax. + if (ctx.oC_Expression(0)) { + listSlice->addChild(transformExpression(*ctx.oC_Expression(0))); + // Parsing [:] syntax. } else { - if (ctx.oC_Expression(1)) { - listSlice->addChild(transformExpression(*ctx.oC_Expression(0))); - listSlice->addChild(transformExpression(*ctx.oC_Expression(1))); - } else { - listSlice->addChild(transformExpression(*ctx.oC_Expression(0))); - listSlice->addChild(getZeroLiteral()); - } + listSlice->addChild(getZeroLiteral()); } - return listSlice; } else { - auto listExtract = - make_unique(LIST_EXTRACT_FUNC_NAME, move(rawExpression)); - listExtract->addChild(move(propertyExpression)); - listExtract->addChild(transformExpression(*ctx.oC_Expression(0))); - return listExtract; + // Parsing [left:right] syntax. + if (ctx.oC_Expression(1)) { + listSlice->addChild(transformExpression(*ctx.oC_Expression(0))); + listSlice->addChild(transformExpression(*ctx.oC_Expression(1))); + // Parsing [left:] syntax. + } else { + listSlice->addChild(transformExpression(*ctx.oC_Expression(0))); + listSlice->addChild(getZeroLiteral()); + } } -} + return listSlice; +}; + +unique_ptr Transformer::transformListExtractOperatorExpression( + CypherParser::KU_ListExtractOperatorExpressionContext& ctx, + unique_ptr propertyExpression) { + auto rawExpression = propertyExpression->getRawName() + " " + ctx.getText(); + auto listExtract = + make_unique(LIST_EXTRACT_FUNC_NAME, move(rawExpression)); + listExtract->addChild(move(propertyExpression)); + listExtract->addChild(transformExpression(*ctx.oC_Expression())); + return listExtract; +}; unique_ptr Transformer::transformNullOperatorExpression( CypherParser::OC_NullOperatorExpressionContext& ctx, diff --git a/test/test_files/tinySNB/function/list.test b/test/test_files/tinySNB/function/list.test index f308d6a247..e5480f4908 100644 --- a/test/test_files/tinySNB/function/list.test +++ b/test/test_files/tinySNB/function/list.test @@ -150,6 +150,31 @@ Fesdwe Grad Ad +-NAME ListExtractDoubleExtract +-QUERY MATCH (a:person) RETURN a.courseScoresPerTerm[1][1] +---- 8 +10 +8 +8 +7 +6 +8 +10 +7 + +-NAME ListExtractSliceListOfStrings +-QUERY MATCH (a:person) RETURN a.usedNames[1][3:7] +---- 8 +da +bby +rmen +lfesc +n +sdwe +ad + + + -NAME ListLenStructuredListOfInts -QUERY MATCH (a:person) RETURN len(a.workedHours) ---- 8 @@ -665,6 +690,18 @@ ABFsUni CsWork DEsWork +-NAME ListSliceStructuredStringDoubleSlice +-QUERY MATCH (a:person) RETURN a.fName[3:][2:4] +---- 8 +ce + +ol + +zab +ooq +g +ert + -NAME ListCreateFromLiteral1 -QUERY RETURN [[100,200],[200,300],[300,400]] ---- 1