some renamings for clarity and consistency
This commit is contained in:
parent
86c8a11074
commit
21fc06173e
|
|
@ -8,25 +8,25 @@
|
|||
|
||||
namespace matador::rsql {
|
||||
enum class binary_operator {
|
||||
EQUALS,
|
||||
NOT_EQUALS,
|
||||
GREATER_THAN,
|
||||
GREATER_THAN_OR_EQUAL,
|
||||
LESS_THAN,
|
||||
LESS_THAN_OR_EQUAL,
|
||||
Equals,
|
||||
NotEquals,
|
||||
GreaterThan,
|
||||
GreaterThanOrEqual,
|
||||
LessThan,
|
||||
LessThanOrEqual,
|
||||
};
|
||||
|
||||
static const std::map<std::string, binary_operator> binary_operators = {
|
||||
{ "==", binary_operator::EQUALS },
|
||||
{ "!=", binary_operator::NOT_EQUALS },
|
||||
{ ">", binary_operator::GREATER_THAN },
|
||||
{ "=gt*", binary_operator::GREATER_THAN },
|
||||
{ ">=", binary_operator::GREATER_THAN_OR_EQUAL },
|
||||
{ "=ge=", binary_operator::GREATER_THAN_OR_EQUAL },
|
||||
{ "<", binary_operator::LESS_THAN },
|
||||
{ "=lt=", binary_operator::LESS_THAN },
|
||||
{ "<=", binary_operator::LESS_THAN_OR_EQUAL },
|
||||
{ "=le=", binary_operator::LESS_THAN_OR_EQUAL }
|
||||
{ "==", binary_operator::Equals },
|
||||
{ "!=", binary_operator::NotEquals },
|
||||
{ ">", binary_operator::GreaterThan },
|
||||
{ "=gt*", binary_operator::GreaterThan },
|
||||
{ ">=", binary_operator::GreaterThanOrEqual },
|
||||
{ "=ge=", binary_operator::GreaterThanOrEqual },
|
||||
{ "<", binary_operator::LessThan },
|
||||
{ "=lt=", binary_operator::LessThan },
|
||||
{ "<=", binary_operator::LessThanOrEqual },
|
||||
{ "=le=", binary_operator::LessThanOrEqual }
|
||||
};
|
||||
|
||||
class node_visitor;
|
||||
|
|
@ -36,9 +36,9 @@ public:
|
|||
|
||||
void accept(node_visitor& visitor) const override;
|
||||
|
||||
const std::string& field() const;
|
||||
binary_operator operand() const;
|
||||
const std::string& value() const;
|
||||
[[nodiscard]] const std::string& field() const;
|
||||
[[nodiscard]] binary_operator operand() const;
|
||||
[[nodiscard]] const std::string& value() const;
|
||||
|
||||
private:
|
||||
std::string field_;
|
||||
|
|
|
|||
|
|
@ -9,13 +9,13 @@
|
|||
|
||||
namespace matador::rsql {
|
||||
enum class collection_operator {
|
||||
IN,
|
||||
OUT
|
||||
In,
|
||||
Out
|
||||
};
|
||||
|
||||
static const std::map<std::string, collection_operator> collection_operators = {
|
||||
{ "=in=", collection_operator::IN },
|
||||
{ "=out=", collection_operator::OUT }
|
||||
{ "=in=", collection_operator::In },
|
||||
{ "=out=", collection_operator::Out }
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -25,9 +25,9 @@ public:
|
|||
|
||||
void accept(node_visitor& visitor) const override;
|
||||
|
||||
const std::string& field() const;
|
||||
collection_operator operand() const;
|
||||
const std::vector<std::string>& values() const;
|
||||
[[nodiscard]] const std::string& field() const;
|
||||
[[nodiscard]] collection_operator operand() const;
|
||||
[[nodiscard]] const std::vector<std::string>& values() const;
|
||||
|
||||
private:
|
||||
std::string field_;
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@
|
|||
|
||||
namespace matador::rsql {
|
||||
enum class logical_operator {
|
||||
AND,
|
||||
OR,
|
||||
And,
|
||||
Or,
|
||||
};
|
||||
|
||||
class node_visitor;
|
||||
|
|
@ -20,8 +20,8 @@ public:
|
|||
explicit logical_node(logical_operator op);
|
||||
void accept(node_visitor& visitor) const override;
|
||||
|
||||
const std::vector<std::shared_ptr<node>>& children() const;
|
||||
logical_operator operand() const;
|
||||
[[nodiscard]] const std::vector<std::shared_ptr<node>>& children() const;
|
||||
[[nodiscard]] logical_operator operand() const;
|
||||
|
||||
private:
|
||||
friend class parser;
|
||||
|
|
|
|||
|
|
@ -3,14 +3,14 @@
|
|||
|
||||
namespace matador::rsql {
|
||||
enum class token_type {
|
||||
IDENTIFIER,
|
||||
OPERATOR,
|
||||
VALUE,
|
||||
LOGICAL_AND,
|
||||
LOGICAL_OR,
|
||||
OPEN_PAREN,
|
||||
CLOSE_PAREN,
|
||||
UNKNOWN
|
||||
Identifier,
|
||||
Operator,
|
||||
Value,
|
||||
LogicalAnd,
|
||||
LogicalOr,
|
||||
OpenParen,
|
||||
CloseParen,
|
||||
Unknown
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
36
src/main.cpp
36
src/main.cpp
|
|
@ -25,7 +25,7 @@ public:
|
|||
}
|
||||
|
||||
void visit(const matador::rsql::logical_node& node) override {
|
||||
std::cout << "Logical (" << (node.operand() == matador::rsql::logical_operator::AND ? "AND" : "OR") << ")\n";
|
||||
std::cout << "Logical (" << (node.operand() == matador::rsql::logical_operator::And ? "AND" : "OR") << ")\n";
|
||||
for (const auto& child : node.children()) {
|
||||
child->accept(*this);
|
||||
}
|
||||
|
|
@ -34,12 +34,12 @@ public:
|
|||
private:
|
||||
static std::string to_string(const matador::rsql::binary_operator op) {
|
||||
static std::map<matador::rsql::binary_operator, std::string> bin_to_string {
|
||||
{ matador::rsql::binary_operator::EQUALS, "==" },
|
||||
{ matador::rsql::binary_operator::NOT_EQUALS, "!=" },
|
||||
{ matador::rsql::binary_operator::GREATER_THAN, ">" },
|
||||
{ matador::rsql::binary_operator::GREATER_THAN_OR_EQUAL, ">=" },
|
||||
{ matador::rsql::binary_operator::LESS_THAN, "<" },
|
||||
{ matador::rsql::binary_operator::LESS_THAN_OR_EQUAL, "<=" },
|
||||
{ matador::rsql::binary_operator::Equals, "==" },
|
||||
{ matador::rsql::binary_operator::NotEquals, "!=" },
|
||||
{ matador::rsql::binary_operator::GreaterThan, ">" },
|
||||
{ matador::rsql::binary_operator::GreaterThanOrEqual, ">=" },
|
||||
{ matador::rsql::binary_operator::LessThan, "<" },
|
||||
{ matador::rsql::binary_operator::LessThanOrEqual, "<=" },
|
||||
};
|
||||
|
||||
return bin_to_string.at(op);
|
||||
|
|
@ -47,8 +47,8 @@ private:
|
|||
|
||||
static std::string to_string(const matador::rsql::collection_operator op) {
|
||||
static std::map<matador::rsql::collection_operator, std::string> col_to_string {
|
||||
{ matador::rsql::collection_operator::IN, "=IN=" },
|
||||
{ matador::rsql::collection_operator::OUT, "=OUT=" }
|
||||
{ matador::rsql::collection_operator::In, "=IN=" },
|
||||
{ matador::rsql::collection_operator::Out, "=OUT=" }
|
||||
};
|
||||
|
||||
return col_to_string.at(op);
|
||||
|
|
@ -76,7 +76,7 @@ public:
|
|||
child->accept(sub);
|
||||
parts.push_back(sub.result);
|
||||
}
|
||||
const std::string operand = (node.operand() == matador::rsql::logical_operator::AND ? " AND " : " OR ");
|
||||
const std::string operand = (node.operand() == matador::rsql::logical_operator::And ? " AND " : " OR ");
|
||||
result += "(";
|
||||
for (size_t i = 0; i < parts.size(); ++i) {
|
||||
result += parts[i];
|
||||
|
|
@ -130,17 +130,17 @@ private:
|
|||
static std::string binary_op_string(const matador::rsql::binary_operator op, const std::string& val) {
|
||||
using namespace matador::rsql;
|
||||
switch (op) {
|
||||
case binary_operator::EQUALS:
|
||||
case binary_operator::Equals:
|
||||
return "= " + quote(val);
|
||||
case binary_operator::NOT_EQUALS:
|
||||
case binary_operator::NotEquals:
|
||||
return "<> " + quote(val);
|
||||
case binary_operator::GREATER_THAN:
|
||||
case binary_operator::GreaterThan:
|
||||
return "> " + quote(val);
|
||||
case binary_operator::GREATER_THAN_OR_EQUAL:
|
||||
case binary_operator::GreaterThanOrEqual:
|
||||
return ">= " + quote(val);
|
||||
case binary_operator::LESS_THAN:
|
||||
case binary_operator::LessThan:
|
||||
return "< " + quote(val);
|
||||
case binary_operator::LESS_THAN_OR_EQUAL:
|
||||
case binary_operator::LessThanOrEqual:
|
||||
return "<= " + quote(val);
|
||||
default:
|
||||
return "??";
|
||||
|
|
@ -149,7 +149,7 @@ private:
|
|||
|
||||
static std::string collection_op_string(const matador::rsql::collection_operator op, const std::vector<std::string>& list) {
|
||||
if (list.empty()) {
|
||||
return (op == matador::rsql::collection_operator::OUT ? "NOT IN (NULL)" : "IN (NULL)");
|
||||
return (op == matador::rsql::collection_operator::Out ? "NOT IN (NULL)" : "IN (NULL)");
|
||||
}
|
||||
std::string joined;
|
||||
joined += "(";
|
||||
|
|
@ -158,7 +158,7 @@ private:
|
|||
if (i + 1 < list.size()) joined += ", ";
|
||||
}
|
||||
joined += ")";
|
||||
if (op == matador::rsql::collection_operator::OUT) {
|
||||
if (op == matador::rsql::collection_operator::Out) {
|
||||
return "IN " + joined;
|
||||
}
|
||||
return "NOT IN " + joined;
|
||||
|
|
|
|||
|
|
@ -6,30 +6,30 @@ std::vector<token> tokenize( const std::string& input ) {
|
|||
std::vector<token> tokens;
|
||||
|
||||
// Pattern catches: =in=, =out=, operators, quoted strings, identifiers, parentheses, commas/semicolons
|
||||
std::regex tokenRegex(R"((=in=|=out=|[=!><~]+)|('[^']*'|"[^"]*")|(\()|(\))|(;|,)|([A-Za-z_]\w*)|([^ \t\n\r]+))");
|
||||
auto begin = std::sregex_iterator(input.begin(), input.end(), tokenRegex);
|
||||
auto end = std::sregex_iterator();
|
||||
const std::regex tokenRegex(R"((=in=|=out=|[=!><~]+)|('[^']*'|"[^"]*")|(\()|(\))|(;|,)|([A-Za-z_]\w*)|([^ \t\n\r]+))");
|
||||
const auto begin = std::sregex_iterator(input.begin(), input.end(), tokenRegex);
|
||||
const auto end = std::sregex_iterator();
|
||||
|
||||
for (auto it = begin; it != end; ++it) {
|
||||
const std::smatch& m = *it;
|
||||
|
||||
if (std::string match = m.str(); match == ";") {
|
||||
tokens.push_back({token_type::LOGICAL_AND, match});
|
||||
tokens.push_back({token_type::LogicalAnd, match});
|
||||
} else if (match == ",") {
|
||||
tokens.push_back({token_type::LOGICAL_OR, match});
|
||||
tokens.push_back({token_type::LogicalOr, match});
|
||||
} else if (match == "(") {
|
||||
tokens.push_back({token_type::OPEN_PAREN, match});
|
||||
tokens.push_back({token_type::OpenParen, match});
|
||||
} else if (match == ")") {
|
||||
tokens.push_back({token_type::CLOSE_PAREN, match});
|
||||
tokens.push_back({token_type::CloseParen, match});
|
||||
} else if (std::regex_match(match, std::regex(R"(=in=|=out=|[=!><~]+)"))) {
|
||||
tokens.push_back({token_type::OPERATOR, match});
|
||||
tokens.push_back({token_type::Operator, match});
|
||||
} else if ((match.size() >= 2 && ((match.front() == '\'' && match.back() == '\'') ||
|
||||
(match.front() == '"' && match.back() == '"')))) {
|
||||
tokens.push_back({token_type::VALUE, match.substr(1, match.size() - 2)});
|
||||
tokens.push_back({token_type::Value, match.substr(1, match.size() - 2)});
|
||||
} else if (std::regex_match(match, std::regex(R"([A-Za-z_]\w*)"))) {
|
||||
tokens.push_back({token_type::IDENTIFIER, match});
|
||||
tokens.push_back({token_type::Identifier, match});
|
||||
} else {
|
||||
tokens.push_back({token_type::VALUE, match});
|
||||
tokens.push_back({token_type::Value, match});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,9 +25,9 @@ std::shared_ptr<node> parser::parse() {
|
|||
|
||||
std::shared_ptr<node> parser::parse_or_expression() {
|
||||
auto node = parse_and_expression();
|
||||
while (match({token_type::LOGICAL_OR})) {
|
||||
while (match({token_type::LogicalOr})) {
|
||||
std::string op = previous().value;
|
||||
const auto logical = std::make_shared<logical_node>(logical_operator::OR);
|
||||
const auto logical = std::make_shared<logical_node>(logical_operator::Or);
|
||||
logical->children_.push_back(node);
|
||||
logical->children_.push_back(parse_and_expression());
|
||||
node = logical;
|
||||
|
|
@ -37,9 +37,9 @@ std::shared_ptr<node> parser::parse_or_expression() {
|
|||
|
||||
std::shared_ptr<node> parser::parse_and_expression() {
|
||||
auto node = parse_primary();
|
||||
while (match({token_type::LOGICAL_AND})) {
|
||||
while (match({token_type::LogicalAnd})) {
|
||||
std::string op = previous().value;
|
||||
const auto logical = std::make_shared<logical_node>(logical_operator::AND);
|
||||
const auto logical = std::make_shared<logical_node>(logical_operator::And);
|
||||
logical->children_.push_back(node);
|
||||
logical->children_.push_back(parse_primary());
|
||||
node = logical;
|
||||
|
|
@ -48,9 +48,9 @@ std::shared_ptr<node> parser::parse_and_expression() {
|
|||
}
|
||||
|
||||
std::shared_ptr<node> parser::parse_primary() {
|
||||
if (match({token_type::OPEN_PAREN})) {
|
||||
if (match({token_type::OpenParen})) {
|
||||
auto node = parse_or_expression();
|
||||
if (!match({token_type::CLOSE_PAREN})) {
|
||||
if (!match({token_type::CloseParen})) {
|
||||
throw std::runtime_error("Missing closing parenthesis");
|
||||
}
|
||||
return node;
|
||||
|
|
@ -59,30 +59,30 @@ std::shared_ptr<node> parser::parse_primary() {
|
|||
}
|
||||
|
||||
std::shared_ptr<node> parser::parse_condition() {
|
||||
if (!match({token_type::IDENTIFIER})) {
|
||||
if (!match({token_type::Identifier})) {
|
||||
throw std::runtime_error("Expected field name");
|
||||
}
|
||||
std::string field = previous().value;
|
||||
|
||||
if (!match({token_type::OPERATOR})) {
|
||||
if (!match({token_type::Operator})) {
|
||||
throw std::runtime_error("Expected operator after field");
|
||||
}
|
||||
|
||||
const std::string op = previous().value;
|
||||
if (op == "=in=" || op == "=out=") {
|
||||
if (!match({token_type::OPEN_PAREN})) {
|
||||
if (!match({token_type::OpenParen})) {
|
||||
throw std::runtime_error("Expected '(' after " + op);
|
||||
}
|
||||
std::vector<std::string> values;
|
||||
bool first = true;
|
||||
while (!match({token_type::CLOSE_PAREN})) {
|
||||
while (!match({token_type::CloseParen})) {
|
||||
if (!first) {
|
||||
// accept comma as separator: tokens use LOGICAL_OR for comma in lexer
|
||||
if (!match({token_type::LOGICAL_OR})) {
|
||||
if (!match({token_type::LogicalOr})) {
|
||||
throw std::runtime_error("Expected ',' between list values");
|
||||
}
|
||||
}
|
||||
if (!match({token_type::VALUE, token_type::IDENTIFIER})) {
|
||||
if (!match({token_type::Value, token_type::Identifier})) {
|
||||
throw std::runtime_error("Expected value in list");
|
||||
}
|
||||
values.push_back(previous().value);
|
||||
|
|
@ -91,7 +91,7 @@ std::shared_ptr<node> parser::parse_condition() {
|
|||
return std::make_shared<collection_condition_node>(field, collection_operators.at(op), values);
|
||||
}
|
||||
|
||||
if (!match({token_type::VALUE, token_type::IDENTIFIER})) {
|
||||
if (!match({token_type::Value, token_type::Identifier})) {
|
||||
throw std::runtime_error("Expected value after operator");
|
||||
}
|
||||
return std::make_shared<binary_condition_node>(field, binary_operators.at(op), previous().value);
|
||||
|
|
|
|||
Loading…
Reference in New Issue