memgraph/src/query/stripper.hpp
Marko Budiselic 4583d8bde3 antlropencypher + youcompleteme update
Summary: antlropencypher + youcompleteme update

Test Plan: manual

Reviewers: mislav.bradac

Reviewed By: mislav.bradac

Subscribers: pullbot, mislav.bradac, buda

Differential Revision: https://phabricator.memgraph.io/D52
2017-02-20 14:06:25 +01:00

105 lines
3.5 KiB
C++

#pragma once
#include <iostream>
#include <string>
#include <tuple>
#include <unordered_map>
#include <utility>
#include <vector>
#include "logging/loggable.hpp"
#include "query/stripped.hpp"
#include "storage/typed_value_store.hpp"
#include "utils/hashing/fnv.hpp"
#include "utils/string/transform.hpp"
#include "utils/variadic/variadic.hpp"
#include "antlr4-runtime.h"
#include "query/frontend/opencypher/generated/CypherLexer.h"
#include "query/frontend/opencypher/generated/CypherParser.h"
using namespace antlr4;
using namespace antlropencypher;
/**
* @brief QueryStripper
*
* Strips the input query and returns stripped query, stripped arguments and
* stripped query hash.
*/
class QueryStripper : public Loggable {
public:
QueryStripper() : Loggable("QueryStripper") {}
QueryStripper(const QueryStripper &) = delete;
QueryStripper(QueryStripper &&) = delete;
QueryStripper &operator=(const QueryStripper &) = delete;
QueryStripper &operator=(QueryStripper &&) = delete;
/**
* Strips the input query (openCypher query).
*
* @param query input query
* @param separator char that is added between all literals in the stripped
* query because after stripping compiler frontend will use the stripped
* query to AST and literals have to be separated
*
* @return stripped query, stripped arguments and stripped query hash as a
* single object of class StrippedQuery
*/
auto strip(const std::string &query, const std::string &separator = " ") {
// generate tokens
ANTLRInputStream input(query);
CypherLexer lexer(&input);
CommonTokenStream tokens(&lexer);
// initialize data structures that will be populated
TypedValueStore<> stripped_arguments;
std::string stripped_query;
stripped_query.reserve(query.size());
// iterate through tokens -> take arguments and generate stripped query
tokens.fill();
int counter = 0;
for (auto token : tokens.getTokens()) {
int type = token->getType();
if (type == CypherLexer::DecimalInteger ||
type == CypherLexer::StringLiteral ||
type == CypherLexer::RegularDecimalReal) { // TODO: add others
switch (type) {
case CypherLexer::DecimalInteger:
stripped_arguments.set(counter, std::stoi(token->getText()));
break;
case CypherLexer::StringLiteral:
stripped_arguments.set(counter, token->getText());
break;
case CypherLexer::RegularDecimalReal:
stripped_arguments.set(counter, std::stof(token->getText()));
break;
}
stripped_query += std::to_string(counter++) + separator;
} else if (type == CypherLexer::MATCH || type == CypherLexer::CREATE ||
type == CypherLexer::RETURN || type == CypherLexer::DELETE ||
type == CypherLexer::SET ||
type == CypherLexer::WHERE) { // TODO: add others
auto value = token->getText();
std::transform(value.begin(), value.end(), value.begin(), ::tolower);
stripped_query += value + separator;
} else if (type == CypherLexer::SP || type < 0 ||
type > 113) { // SP || EOF // TODO: add others if exist
// pass
} else {
stripped_query += token->getText() + separator;
}
}
// calculate query hash
HashType hash = fnv(stripped_query);
// return stripped query, stripped arguments and stripped query hash
return StrippedQuery(std::move(stripped_query),
std::move(stripped_arguments), hash);
}
};