Convert labels test from antlr to AST

Reviewers: florijan, teon.banek

Reviewed By: teon.banek

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D346
This commit is contained in:
Mislav Bradac 2017-05-04 18:07:54 +02:00
parent 3b4e66e0e3
commit 72d4a67c4a
4 changed files with 47 additions and 14 deletions

View File

@ -600,7 +600,7 @@ antlrcpp::Any CypherMainVisitor::visitExpression3a(
antlrcpp::Any CypherMainVisitor::visitExpression3b( antlrcpp::Any CypherMainVisitor::visitExpression3b(
CypherParser::Expression3bContext *ctx) { CypherParser::Expression3bContext *ctx) {
Expression *expression = ctx->expression2()->accept(this); Expression *expression = ctx->expression2a()->accept(this);
for (auto *list_op : ctx->listIndexingOrSlicing()) { for (auto *list_op : ctx->listIndexingOrSlicing()) {
if (list_op->getTokens(kDotsTokenId).size() == 0U) { if (list_op->getTokens(kDotsTokenId).size() == 0U) {
// If there is no '..' then we need to create list indexing operator. // If there is no '..' then we need to create list indexing operator.
@ -631,13 +631,19 @@ antlrcpp::Any CypherMainVisitor::visitListIndexingOrSlicing(
return 0; return 0;
} }
antlrcpp::Any CypherMainVisitor::visitExpression2( antlrcpp::Any CypherMainVisitor::visitExpression2a(
CypherParser::Expression2Context *ctx) { CypherParser::Expression2aContext *ctx) {
if (ctx->nodeLabels().size()) { Expression *expression = ctx->expression2b()->accept(this);
// TODO: Implement this. We don't currently support label checking in if (ctx->nodeLabels()) {
// expresssion. auto labels =
throw utils::NotYetImplemented(); ctx->nodeLabels()->accept(this).as<std::vector<GraphDbTypes::Label>>();
expression = storage_.Create<LabelsTest>(expression, labels);
} }
return expression;
}
antlrcpp::Any CypherMainVisitor::visitExpression2b(
CypherParser::Expression2bContext *ctx) {
Expression *expression = ctx->atom()->accept(this); Expression *expression = ctx->atom()->accept(this);
for (auto *lookup : ctx->propertyLookup()) { for (auto *lookup : ctx->propertyLookup()) {
auto property_lookup = auto property_lookup =

View File

@ -381,12 +381,20 @@ class CypherMainVisitor : public antlropencypher::CypherBaseVisitor {
CypherParser::ListIndexingOrSlicingContext *ctx) override; CypherParser::ListIndexingOrSlicingContext *ctx) override;
/** /**
* Property lookup, test for node labels existence... * Node labels test.
* *
* @return Expression* * @return Expression*
*/ */
antlrcpp::Any visitExpression2( antlrcpp::Any visitExpression2a(
CypherParser::Expression2Context *ctx) override; CypherParser::Expression2aContext *ctx) override;
/**
* Property lookup.
*
* @return Expression*
*/
antlrcpp::Any visitExpression2b(
CypherParser::Expression2bContext *ctx) override;
/** /**
* Literals, params, list comprehension... * Literals, params, list comprehension...

View File

@ -153,15 +153,17 @@ expression5 : expression4 ( SP? '^' SP? expression4 )* ;
expression4 : ( ( '+' | '-' ) SP? )* expression3a ; expression4 : ( ( '+' | '-' ) SP? )* expression3a ;
expression3a : expression3b ( ( ( ( SP? '=~' ) | ( SP IN ) | ( SP STARTS SP WITH ) | ( SP ENDS SP WITH ) | ( SP CONTAINS ) ) SP? expression2 ) | ( SP IS SP CYPHERNULL ) | ( SP IS SP NOT SP CYPHERNULL ) )* ; expression3a : expression3b ( ( ( ( SP? '=~' ) | ( SP IN ) | ( SP STARTS SP WITH ) | ( SP ENDS SP WITH ) | ( SP CONTAINS ) ) SP? expression2a ) | ( SP IS SP CYPHERNULL ) | ( SP IS SP NOT SP CYPHERNULL ) )* ;
expression3b : expression2 ( SP? listIndexingOrSlicing )* ; expression3b : expression2a ( SP? listIndexingOrSlicing )* ;
listIndexingOrSlicing : ( '[' SP? expression SP? ']' ) listIndexingOrSlicing : ( '[' SP? expression SP? ']' )
| ( '[' SP? lower_bound=expression? SP? '..' SP? upper_bound=expression? SP? ']' ) | ( '[' SP? lower_bound=expression? SP? '..' SP? upper_bound=expression? SP? ']' )
; ;
expression2 : atom ( SP? ( propertyLookup | nodeLabels ) )* ; expression2a : expression2b ( SP? nodeLabels )? ;
expression2b : atom ( SP? propertyLookup )* ;
atom : literal atom : literal
| parameter | parameter

View File

@ -19,8 +19,9 @@ namespace {
using namespace query; using namespace query;
using namespace query::frontend; using namespace query::frontend;
using query::TypedValue; using query::TypedValue;
using testing::UnorderedElementsAre;
using testing::Pair; using testing::Pair;
using testing::ElementsAre;
using testing::UnorderedElementsAre;
class AstGenerator { class AstGenerator {
public: public:
@ -68,6 +69,22 @@ TEST(CypherMainVisitorTest, PropertyLookup) {
ast_generator.db_accessor_->property("x")); ast_generator.db_accessor_->property("x"));
} }
TEST(CypherMainVisitorTest, LabelsTest) {
AstGenerator ast_generator("RETURN n:x:y");
auto *query = ast_generator.query_;
ASSERT_EQ(query->clauses_.size(), 1U);
auto *return_clause = dynamic_cast<Return *>(query->clauses_[0]);
auto *labels_test = dynamic_cast<LabelsTest *>(
return_clause->body_.named_expressions[0]->expression_);
ASSERT_TRUE(labels_test->expression_);
auto identifier = dynamic_cast<Identifier *>(labels_test->expression_);
ASSERT_TRUE(identifier);
ASSERT_EQ(identifier->name_, "n");
ASSERT_THAT(labels_test->labels_,
ElementsAre(ast_generator.db_accessor_->label("x"),
ast_generator.db_accessor_->label("y")));
}
TEST(CypherMainVisitorTest, ReturnNoDistinctNoBagSemantics) { TEST(CypherMainVisitorTest, ReturnNoDistinctNoBagSemantics) {
AstGenerator ast_generator("RETURN x"); AstGenerator ast_generator("RETURN x");
auto *query = ast_generator.query_; auto *query = ast_generator.query_;