logic: added query syntax and filtering system for search
This change allows the user to use a simple query syntax in the search field to filter the results using names,
operators and predefined filters.
The class QueryTree is capable of parsing a simple query language consiting of QueryNodes, subclassed as
QueryOperators, QueryCommands and QueryTokens. QueryToken identifies a Token by name. QueryCommand represents predefined
filters. QueryOperator defines the syntactic relationship.
QueryNode examples:
"A" -> QueryToken that identifies the Token named A
class -> QueryCommand that filters all Nodes that are classes
. -> QueryOperator that concatenates filters
QueryExamples:
"A".class -> All Tokens named A that are classes
method.(private|protected) -> All methods that are private or protected
"A".member -> All members of A
"A":field.!const -> All fields of A that are not const (':' can be used instead of '.member')
QueryTree checks for correct operator precedence and validity of the query.
All QueryCommands can be found in data/query/QueryCommand.cpp
All QueryOperators can be found in data/query/QueryOperator.cpp
The parsed QueryTree is then passed to the class GraphFilterConductor, which is capable of applying the query on a
Graph. Each part of the query gets assigned a GraphFilter that filters the input Graph in order of node precedence. The
class SubGraph is used as intermediate container, only holding bare pointers to Nodes and Edges. The output Graph holds
all Nodes that match the query.
MessageActivateTokens is used to show all of the results in the CodeView. The GraphView currently only shows the first
Node of the results.
bug id = #6
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
#include "data/query/QueryCommand.h"
|
||||
|
||||
QueryCommand::QueryCommand(const std::string& name)
|
||||
: m_type(COMMAND_INVALID)
|
||||
, m_name(name)
|
||||
{
|
||||
std::map<std::string, CommandType> commandMap = getCommandTypeMap();
|
||||
std::map<std::string, CommandType>::iterator it = commandMap.find(name);
|
||||
|
||||
if (it != commandMap.end())
|
||||
{
|
||||
m_type = it->second;
|
||||
}
|
||||
}
|
||||
|
||||
QueryCommand::~QueryCommand()
|
||||
{
|
||||
}
|
||||
|
||||
bool QueryCommand::isCommand() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QueryCommand::isOperator() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QueryCommand::isToken() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QueryCommand::isComplete() const
|
||||
{
|
||||
return m_type != COMMAND_INVALID;
|
||||
}
|
||||
|
||||
void QueryCommand::print(std::ostream& ostream) const
|
||||
{
|
||||
ostream << m_name;
|
||||
|
||||
if (!isComplete())
|
||||
{
|
||||
ostream << " INVALID";
|
||||
}
|
||||
}
|
||||
|
||||
QueryCommand::CommandType QueryCommand::getType() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
std::map<std::string, QueryCommand::CommandType> QueryCommand::getCommandTypeMap()
|
||||
{
|
||||
static std::map<std::string, CommandType> commandMap;
|
||||
|
||||
if (commandMap.size())
|
||||
{
|
||||
return commandMap;
|
||||
}
|
||||
|
||||
commandMap.emplace("member", COMMAND_MEMBER);
|
||||
commandMap.emplace("child", COMMAND_MEMBER);
|
||||
|
||||
commandMap.emplace("parent", COMMAND_PARENT);
|
||||
|
||||
commandMap.emplace("function", COMMAND_FUNCTION);
|
||||
commandMap.emplace("variable", COMMAND_GLOBAL_VARIABLE);
|
||||
commandMap.emplace("global", COMMAND_GLOBAL_VARIABLE);
|
||||
commandMap.emplace("class", COMMAND_CLASS);
|
||||
commandMap.emplace("method", COMMAND_METHOD);
|
||||
commandMap.emplace("field", COMMAND_FIELD);
|
||||
commandMap.emplace("namespace", COMMAND_NAMESPACE);
|
||||
commandMap.emplace("struct", COMMAND_STRUCT);
|
||||
commandMap.emplace("enum", COMMAND_ENUM);
|
||||
commandMap.emplace("typedef", COMMAND_TYPEDEF);
|
||||
|
||||
commandMap.emplace("const", COMMAND_CONST);
|
||||
commandMap.emplace("static", COMMAND_STATIC);
|
||||
commandMap.emplace("virtual", COMMAND_VIRTUAL);
|
||||
commandMap.emplace("abstract", COMMAND_PURE_VIRTUAL);
|
||||
commandMap.emplace("pure-virtual", COMMAND_PURE_VIRTUAL);
|
||||
|
||||
commandMap.emplace("public", COMMAND_PUBLIC);
|
||||
commandMap.emplace("protected", COMMAND_PROTECTED);
|
||||
commandMap.emplace("private", COMMAND_PRIVATE);
|
||||
|
||||
commandMap.emplace("caller", COMMAND_CALLER);
|
||||
commandMap.emplace("callee", COMMAND_CALLEE);
|
||||
|
||||
commandMap.emplace("usage", COMMAND_USAGE);
|
||||
|
||||
commandMap.emplace("base", COMMAND_SUPER_CLASS);
|
||||
commandMap.emplace("super", COMMAND_SUPER_CLASS);
|
||||
commandMap.emplace("derived", COMMAND_SUB_CLASS);
|
||||
commandMap.emplace("subclass", COMMAND_SUB_CLASS);
|
||||
|
||||
return commandMap;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
#ifndef QUERY_COMMAND_H
|
||||
#define QUERY_COMMAND_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "data/query/QueryNode.h"
|
||||
|
||||
class QueryCommand
|
||||
: public QueryNode
|
||||
{
|
||||
public:
|
||||
enum CommandType
|
||||
{
|
||||
COMMAND_INVALID,
|
||||
|
||||
COMMAND_MEMBER,
|
||||
COMMAND_PARENT,
|
||||
COMMAND_FUNCTION,
|
||||
COMMAND_GLOBAL_VARIABLE,
|
||||
COMMAND_CLASS,
|
||||
COMMAND_METHOD,
|
||||
COMMAND_FIELD,
|
||||
COMMAND_NAMESPACE,
|
||||
COMMAND_STRUCT,
|
||||
COMMAND_ENUM,
|
||||
COMMAND_TYPEDEF,
|
||||
|
||||
COMMAND_CONST,
|
||||
COMMAND_STATIC,
|
||||
COMMAND_VIRTUAL,
|
||||
COMMAND_PURE_VIRTUAL,
|
||||
|
||||
COMMAND_PUBLIC,
|
||||
COMMAND_PROTECTED,
|
||||
COMMAND_PRIVATE,
|
||||
|
||||
COMMAND_CALLER,
|
||||
COMMAND_CALLEE,
|
||||
|
||||
COMMAND_USAGE,
|
||||
|
||||
COMMAND_SUPER_CLASS,
|
||||
COMMAND_SUB_CLASS
|
||||
};
|
||||
|
||||
QueryCommand(const std::string& name);
|
||||
~QueryCommand();
|
||||
|
||||
virtual bool isCommand() const;
|
||||
virtual bool isOperator() const;
|
||||
virtual bool isToken() const;
|
||||
|
||||
virtual bool isComplete() const;
|
||||
|
||||
virtual void print(std::ostream& ostream) const;
|
||||
|
||||
CommandType getType() const;
|
||||
|
||||
private:
|
||||
static std::map<std::string, CommandType> getCommandTypeMap();
|
||||
|
||||
CommandType m_type;
|
||||
const std::string m_name;
|
||||
};
|
||||
|
||||
#endif // QUERY_COMMAND_H
|
||||
@@ -0,0 +1,42 @@
|
||||
#include "data/query/QueryNode.h"
|
||||
|
||||
QueryNode::QueryNode()
|
||||
: m_isGroup(false)
|
||||
{
|
||||
}
|
||||
|
||||
QueryNode::~QueryNode()
|
||||
{
|
||||
}
|
||||
|
||||
void QueryNode::print(std::ostream& ostream, int n) const
|
||||
{
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
ostream << '\t';
|
||||
}
|
||||
|
||||
if (isGroup())
|
||||
{
|
||||
ostream << '(';
|
||||
}
|
||||
|
||||
print(ostream);
|
||||
|
||||
if (isGroup())
|
||||
{
|
||||
ostream << ')';
|
||||
}
|
||||
|
||||
ostream << '\n';
|
||||
}
|
||||
|
||||
bool QueryNode::isGroup() const
|
||||
{
|
||||
return m_isGroup;
|
||||
}
|
||||
|
||||
void QueryNode::setIsGroup(bool isGroup)
|
||||
{
|
||||
m_isGroup = isGroup;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef QUERY_NODE_H
|
||||
#define QUERY_NODE_H
|
||||
|
||||
#include <ostream>
|
||||
|
||||
class QueryNode
|
||||
{
|
||||
public:
|
||||
QueryNode();
|
||||
virtual ~QueryNode();
|
||||
|
||||
virtual bool isCommand() const = 0;
|
||||
virtual bool isOperator() const = 0;
|
||||
virtual bool isToken() const = 0;
|
||||
|
||||
virtual bool isComplete() const = 0;
|
||||
|
||||
virtual void print(std::ostream& ostream) const = 0;
|
||||
virtual void print(std::ostream& ostream, int n) const;
|
||||
|
||||
bool isGroup() const;
|
||||
void setIsGroup(bool isGroup);
|
||||
|
||||
private:
|
||||
bool m_isGroup;
|
||||
};
|
||||
|
||||
#endif // QUERY_NODE_H
|
||||
@@ -0,0 +1,135 @@
|
||||
#include "data/query/QueryOperator.h"
|
||||
|
||||
const std::map<char, QueryOperator::OperatorType>& QueryOperator::getOperatorTypeMap()
|
||||
{
|
||||
static std::map<char, OperatorType> operatorMap;
|
||||
|
||||
if (operatorMap.size())
|
||||
{
|
||||
return operatorMap;
|
||||
}
|
||||
|
||||
operatorMap.emplace(' ', OPERATOR_NONE);
|
||||
|
||||
operatorMap.emplace('!', OPERATOR_NOT);
|
||||
operatorMap.emplace('.', OPERATOR_SUB);
|
||||
operatorMap.emplace(':', OPERATOR_HAS);
|
||||
operatorMap.emplace('&', OPERATOR_AND);
|
||||
operatorMap.emplace('|', OPERATOR_OR);
|
||||
|
||||
operatorMap.emplace('"', OPERATOR_NAME);
|
||||
operatorMap.emplace('(', OPERATOR_GROUP_OPEN);
|
||||
operatorMap.emplace(')', OPERATOR_GROUP_CLOSE);
|
||||
|
||||
return operatorMap;
|
||||
}
|
||||
|
||||
QueryOperator::OperatorType QueryOperator::getOperatorType(char c)
|
||||
{
|
||||
const std::map<char, OperatorType>& operatorMap = getOperatorTypeMap();
|
||||
std::map<char, OperatorType>::const_iterator it = operatorMap.find(c);
|
||||
|
||||
if (it != operatorMap.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return OPERATOR_NONE;
|
||||
}
|
||||
|
||||
char QueryOperator::getOperator(OperatorType t)
|
||||
{
|
||||
for (const std::pair<char, OperatorType>& p : getOperatorTypeMap())
|
||||
{
|
||||
if (p.second == t)
|
||||
{
|
||||
return p.first;
|
||||
}
|
||||
}
|
||||
|
||||
return '\0';
|
||||
}
|
||||
|
||||
QueryOperator::QueryOperator(OperatorType type)
|
||||
: m_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
QueryOperator::~QueryOperator()
|
||||
{
|
||||
}
|
||||
|
||||
bool QueryOperator::isCommand() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QueryOperator::isOperator() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QueryOperator::isToken() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QueryOperator::isComplete() const
|
||||
{
|
||||
if (m_type == OPERATOR_NOT)
|
||||
{
|
||||
return bool(getRight());
|
||||
}
|
||||
|
||||
return getLeft() && getRight();
|
||||
}
|
||||
|
||||
void QueryOperator::print(std::ostream& ostream) const
|
||||
{
|
||||
ostream << m_type;
|
||||
}
|
||||
|
||||
void QueryOperator::print(std::ostream& ostream, int n) const
|
||||
{
|
||||
if (m_left)
|
||||
{
|
||||
m_left->print(ostream, n + 1);
|
||||
}
|
||||
|
||||
QueryNode::print(ostream, n);
|
||||
|
||||
if (m_right)
|
||||
{
|
||||
m_right->print(ostream, n + 1);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<QueryNode> QueryOperator::getLeft() const
|
||||
{
|
||||
return m_left;
|
||||
}
|
||||
|
||||
void QueryOperator::setLeft(std::shared_ptr<QueryNode> node)
|
||||
{
|
||||
m_left = node;
|
||||
}
|
||||
|
||||
std::shared_ptr<QueryNode> QueryOperator::getRight() const
|
||||
{
|
||||
return m_right;
|
||||
}
|
||||
|
||||
void QueryOperator::setRight(std::shared_ptr<QueryNode> node)
|
||||
{
|
||||
m_right = node;
|
||||
}
|
||||
|
||||
QueryOperator::OperatorType QueryOperator::getType() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
bool QueryOperator::lowerPrecedence(const QueryOperator& other)
|
||||
{
|
||||
return m_type < other.m_type;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#ifndef QUERY_OPERATOR_H
|
||||
#define QUERY_OPERATOR_H
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include "data/query/QueryNode.h"
|
||||
|
||||
class QueryOperator
|
||||
: public QueryNode
|
||||
{
|
||||
public:
|
||||
enum OperatorType
|
||||
{
|
||||
OPERATOR_NONE,
|
||||
|
||||
OPERATOR_NOT,
|
||||
OPERATOR_SUB,
|
||||
OPERATOR_HAS,
|
||||
OPERATOR_AND,
|
||||
OPERATOR_OR,
|
||||
|
||||
OPERATOR_NAME,
|
||||
OPERATOR_GROUP_OPEN,
|
||||
OPERATOR_GROUP_CLOSE
|
||||
};
|
||||
|
||||
static const std::map<char, OperatorType>& getOperatorTypeMap();
|
||||
static OperatorType getOperatorType(char c);
|
||||
static char getOperator(OperatorType t);
|
||||
|
||||
QueryOperator(OperatorType type);
|
||||
~QueryOperator();
|
||||
|
||||
virtual bool isCommand() const;
|
||||
virtual bool isOperator() const;
|
||||
virtual bool isToken() const;
|
||||
|
||||
virtual bool isComplete() const;
|
||||
|
||||
virtual void print(std::ostream& ostream) const;
|
||||
virtual void print(std::ostream& ostream, int n) const;
|
||||
|
||||
std::shared_ptr<QueryNode> getLeft() const;
|
||||
void setLeft(std::shared_ptr<QueryNode> node);
|
||||
|
||||
std::shared_ptr<QueryNode> getRight() const;
|
||||
void setRight(std::shared_ptr<QueryNode> node);
|
||||
|
||||
OperatorType getType() const;
|
||||
|
||||
bool lowerPrecedence(const QueryOperator& other);
|
||||
|
||||
private:
|
||||
std::shared_ptr<QueryNode> m_left;
|
||||
std::shared_ptr<QueryNode> m_right;
|
||||
|
||||
const OperatorType m_type;
|
||||
};
|
||||
|
||||
#endif // QUERY_OPERATOR_H
|
||||
@@ -0,0 +1,40 @@
|
||||
#include "data/query/QueryToken.h"
|
||||
|
||||
QueryToken::QueryToken(const std::string& name)
|
||||
: m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
QueryToken::~QueryToken()
|
||||
{
|
||||
}
|
||||
|
||||
bool QueryToken::isCommand() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QueryToken::isOperator() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QueryToken::isToken() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QueryToken::isComplete() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void QueryToken::print(std::ostream& ostream) const
|
||||
{
|
||||
ostream << '"' << m_name << '"';
|
||||
}
|
||||
|
||||
const std::string& QueryToken::getName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef QUERY_TOKEN_H
|
||||
#define QUERY_TOKEN_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "data/query/QueryNode.h"
|
||||
|
||||
class QueryToken
|
||||
: public QueryNode
|
||||
{
|
||||
public:
|
||||
QueryToken(const std::string& name);
|
||||
~QueryToken();
|
||||
|
||||
virtual bool isCommand() const;
|
||||
virtual bool isOperator() const;
|
||||
virtual bool isToken() const;
|
||||
virtual bool isComplete() const;
|
||||
|
||||
virtual void print(std::ostream& ostream) const;
|
||||
|
||||
const std::string& getName() const;
|
||||
|
||||
private:
|
||||
const std::string m_name;
|
||||
};
|
||||
|
||||
#endif // QUERY_TOKEN_H
|
||||
@@ -0,0 +1,207 @@
|
||||
#include "data/query/QueryTree.h"
|
||||
|
||||
#include "data/query/QueryCommand.h"
|
||||
#include "data/query/QueryNode.h"
|
||||
#include "data/query/QueryOperator.h"
|
||||
#include "data/query/QueryToken.h"
|
||||
#include "utility/utilityString.h"
|
||||
|
||||
QueryTree::QueryTree(std::string query)
|
||||
: m_valid(true)
|
||||
{
|
||||
std::deque<std::string> tokens =
|
||||
utility::split<std::deque<std::string>>(query, QueryOperator::getOperator(QueryOperator::OPERATOR_NONE));
|
||||
|
||||
for (const std::pair<char, QueryOperator::OperatorType>& p : QueryOperator::getOperatorTypeMap())
|
||||
{
|
||||
tokens = utility::tokenize<std::deque<std::string>>(tokens, p.first);
|
||||
}
|
||||
|
||||
for (std::string str : tokens)
|
||||
{
|
||||
m_query += str + ' ';
|
||||
}
|
||||
|
||||
m_root = buildTree(tokens, nullptr);
|
||||
}
|
||||
|
||||
QueryTree::~QueryTree()
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<QueryNode> QueryTree::getRoot() const
|
||||
{
|
||||
return m_root;
|
||||
}
|
||||
|
||||
bool QueryTree::isValid() const
|
||||
{
|
||||
return m_valid;
|
||||
}
|
||||
|
||||
void QueryTree::print(std::ostream& ostream) const
|
||||
{
|
||||
ostream << m_query;
|
||||
|
||||
if (!m_valid)
|
||||
{
|
||||
ostream << " INVALID";
|
||||
}
|
||||
|
||||
ostream << '\n';
|
||||
|
||||
if (m_root)
|
||||
{
|
||||
m_root->print(ostream, 0);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<QueryNode> QueryTree::buildTree(std::deque<std::string>& tokens, std::shared_ptr<QueryNode> frontNode)
|
||||
{
|
||||
std::shared_ptr<QueryNode> node = getNextNode(tokens);
|
||||
std::shared_ptr<QueryOperator> operatorNode = std::dynamic_pointer_cast<QueryOperator>(node);
|
||||
|
||||
if (frontNode)
|
||||
{
|
||||
if (node->isComplete())
|
||||
{
|
||||
std::shared_ptr<QueryOperator> subNode = std::make_shared<QueryOperator>(QueryOperator::OPERATOR_SUB);
|
||||
subNode->setLeft(frontNode);
|
||||
subNode->setRight(node);
|
||||
node = subNode;
|
||||
}
|
||||
else if (node->isOperator() && operatorNode)
|
||||
{
|
||||
operatorNode->setLeft(frontNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (tokens.size())
|
||||
{
|
||||
if (node->isComplete())
|
||||
{
|
||||
node = buildTree(tokens, node);
|
||||
}
|
||||
else if (node->isOperator() && operatorNode)
|
||||
{
|
||||
std::shared_ptr<QueryNode> rightNode = buildTree(tokens, nullptr);
|
||||
std::shared_ptr<QueryOperator> rightOperatorNode = std::dynamic_pointer_cast<QueryOperator>(rightNode);
|
||||
|
||||
if (rightNode->isOperator() && !rightNode->isGroup() &&
|
||||
operatorNode->lowerPrecedence(*rightOperatorNode.get()))
|
||||
{
|
||||
operatorNode->setRight(rightOperatorNode->getLeft());
|
||||
rightOperatorNode->setLeft(operatorNode);
|
||||
node = rightNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
operatorNode->setRight(rightNode);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!node->isComplete())
|
||||
{
|
||||
m_valid = false;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
std::shared_ptr<QueryNode> QueryTree::buildGroup(std::deque<std::string>& tokens, QueryOperator::OperatorType closeType)
|
||||
{
|
||||
std::deque<std::string> group;
|
||||
std::string name;
|
||||
char delimiter = QueryOperator::getOperator(closeType);
|
||||
while (tokens.front() != std::string(1, delimiter) && tokens.size())
|
||||
{
|
||||
group.push_back(tokens.front());
|
||||
name += tokens.front();
|
||||
tokens.pop_front();
|
||||
}
|
||||
|
||||
if (tokens.size())
|
||||
{
|
||||
tokens.pop_front();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_valid = false;
|
||||
}
|
||||
|
||||
if (!group.size())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (closeType == QueryOperator::OPERATOR_NAME)
|
||||
{
|
||||
return std::make_shared<QueryToken>(name);
|
||||
}
|
||||
|
||||
std::shared_ptr<QueryNode> groupNode = buildTree(group, nullptr);
|
||||
groupNode->setIsGroup(true);
|
||||
|
||||
return groupNode;
|
||||
}
|
||||
|
||||
std::shared_ptr<QueryNode> QueryTree::getNextNode(std::deque<std::string>& tokens)
|
||||
{
|
||||
while (tokens.size())
|
||||
{
|
||||
std::string token = tokens.front();
|
||||
tokens.pop_front();
|
||||
|
||||
QueryOperator::OperatorType type = QueryOperator::getOperatorType(token[0]);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case QueryOperator::OPERATOR_NOT:
|
||||
case QueryOperator::OPERATOR_SUB:
|
||||
case QueryOperator::OPERATOR_HAS:
|
||||
case QueryOperator::OPERATOR_AND:
|
||||
case QueryOperator::OPERATOR_OR:
|
||||
return std::make_shared<QueryOperator>(type);
|
||||
|
||||
case QueryOperator::OPERATOR_NAME:
|
||||
return buildGroup(tokens, QueryOperator::OPERATOR_NAME);
|
||||
case QueryOperator::OPERATOR_GROUP_OPEN:
|
||||
return buildGroup(tokens, QueryOperator::OPERATOR_GROUP_CLOSE);
|
||||
case QueryOperator::OPERATOR_GROUP_CLOSE:
|
||||
m_valid = false;
|
||||
break;
|
||||
|
||||
case QueryOperator::OPERATOR_NONE:
|
||||
return createCommand(token);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<QueryNode> QueryTree::createCommand(std::string name)
|
||||
{
|
||||
std::shared_ptr<QueryCommand> node = std::make_shared<QueryCommand>(name);
|
||||
|
||||
if (node->getType() == QueryCommand::COMMAND_INVALID)
|
||||
{
|
||||
m_valid = false;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& ostream, const QueryTree& tree)
|
||||
{
|
||||
tree.print(ostream);
|
||||
return ostream;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef QUERY_TREE_H
|
||||
#define QUERY_TREE_H
|
||||
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
#include "data/query/QueryOperator.h"
|
||||
|
||||
class QueryNode;
|
||||
|
||||
class QueryTree
|
||||
{
|
||||
public:
|
||||
QueryTree(std::string query);
|
||||
~QueryTree();
|
||||
|
||||
std::shared_ptr<QueryNode> getRoot() const;
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
void print(std::ostream& ostream) const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<QueryNode> buildTree(std::deque<std::string>& tokens, std::shared_ptr<QueryNode> frontNode);
|
||||
std::shared_ptr<QueryNode> buildGroup(std::deque<std::string>& tokens, QueryOperator::OperatorType closeType);
|
||||
std::shared_ptr<QueryNode> getNextNode(std::deque<std::string>& tokens);
|
||||
std::shared_ptr<QueryNode> createCommand(std::string name);
|
||||
|
||||
std::shared_ptr<QueryNode> m_root;
|
||||
std::string m_query;
|
||||
bool m_valid;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& ostream, const QueryTree& tree);
|
||||
|
||||
#endif // QUERY_TREE_H
|
||||
Reference in New Issue
Block a user