From 023649ca4d802d69bc7718c7756ecf1f715f7f4e Mon Sep 17 00:00:00 2001 From: Vladislav Pavlov Date: Thu, 1 Jun 2023 03:44:17 +0300 Subject: [PATCH] added clang-format and clang-tidy, ComponentException is inherited from runtime error, minor corrections --- server/lib/query_language/include/classes.hpp | 147 ++--- .../lib/query_language/include/exception.hpp | 12 +- .../query_language/include/interpreter.hpp | 66 +-- server/lib/query_language/include/parser.hpp | 46 +- .../lib/query_language/include/querying.hpp | 2 +- server/lib/query_language/include/scaner.hpp | 155 ++--- .../query_lang_tests/src/test_query_lang.cpp | 88 ++- server/lib/query_language/src/classes.cpp | 97 ++- server/lib/query_language/src/exception.cpp | 5 +- server/lib/query_language/src/interpreter.cpp | 560 +++++++++--------- server/lib/query_language/src/parser.cpp | 264 +++++---- server/lib/query_language/src/scaner.cpp | 318 +++++----- 12 files changed, 936 insertions(+), 824 deletions(-) diff --git a/server/lib/query_language/include/classes.hpp b/server/lib/query_language/include/classes.hpp index 7461293..b280759 100644 --- a/server/lib/query_language/include/classes.hpp +++ b/server/lib/query_language/include/classes.hpp @@ -17,108 +17,111 @@ using Value = // интерпретатор аст дерева обязан определить // все функции для посещения его вершин class ExprVisitor { -public: - virtual ~ExprVisitor() = default; - virtual Value visit(Binary *Expr) = 0; - virtual Value visit(Unary *Expr) = 0; - virtual Value visit(Literal *Expr) = 0; - virtual Value visit(LogicalExpr *Expr) = 0; - virtual Value visit(FuncIn *Expr) = 0; - virtual Value visit(Grouping *Expr) = 0; + public: + virtual ~ExprVisitor() = default; + virtual Value visit(Binary *Expr) = 0; + virtual Value visit(Unary *Expr) = 0; + virtual Value visit(Literal *Expr) = 0; + virtual Value visit(LogicalExpr *Expr) = 0; + virtual Value visit(FuncIn *Expr) = 0; + virtual Value visit(Grouping *Expr) = 0; }; // базовый класс аст дерева class Expr { -public: - virtual ~Expr() = default; - virtual Value accept(ExprVisitor *visitor) = 0; + public: + virtual ~Expr() = default; + virtual Value accept(ExprVisitor *visitor) = 0; }; // класс для переменной, считанной из запроса class Literal : public Expr { -public: - explicit Literal(std::string v); - explicit Literal(double d); - explicit Literal(bool b); - explicit Literal(std::vector json_namevec); - Literal(); - - Value &get_value(); - std::vector get_json_namevec(); - Value accept(ExprVisitor *visitor) override; - -private: - std::vector json_namevec; - Value val; + public: + explicit Literal(std::string v); + explicit Literal(double d); + explicit Literal(bool b); + explicit Literal(std::vector json_namevec); + Literal(); + + Value &get_value(); + std::vector get_json_namevec(); + Value accept(ExprVisitor *visitor) override; + + private: + std::vector json_namevec; + Value val; }; // класс бинарных операций class Binary : public Expr { -public: - Binary(std::unique_ptr left_, token tok, std::unique_ptr right_); - - Expr *get_leftptr(); - Expr *get_rightptr(); - token get_opername(); - Value accept(ExprVisitor *visitor) override; - -private: - std::unique_ptr left; - std::unique_ptr right; - token oper; + public: + Binary(std::unique_ptr left_, + token tok, + std::unique_ptr right_); + + Expr *get_leftptr(); + Expr *get_rightptr(); + token get_opername(); + Value accept(ExprVisitor *visitor) override; + + private: + std::unique_ptr left; + std::unique_ptr right; + token oper; }; class FuncIn : public Expr { -public: - FuncIn(std::unique_ptr left_, std::unique_ptr right_); + public: + FuncIn(std::unique_ptr left_, std::unique_ptr right_); - Expr *get_leftptr(); - Expr *get_rightptr(); - Value accept(ExprVisitor *visitor) override; + Expr *get_leftptr(); + Expr *get_rightptr(); + Value accept(ExprVisitor *visitor) override; -private: - std::unique_ptr left; - std::unique_ptr right; + private: + std::unique_ptr left; + std::unique_ptr right; }; // элементарный класс унарных операций class Unary : public Expr { -public: - Unary(std::unique_ptr Expression_, token tok); + public: + Unary(std::unique_ptr Expression_, token tok); - Expr *get_expr(); - token get_opername(); - Value accept(ExprVisitor *visitor) override; + Expr *get_expr(); + token get_opername(); + Value accept(ExprVisitor *visitor) override; -private: - std::unique_ptr expression; - token oper; + private: + std::unique_ptr expression; + token oper; }; class LogicalExpr : public Expr { -public: - LogicalExpr(std::unique_ptr left_, token tok, - std::unique_ptr right_); - - Expr *get_leftptr(); - Expr *get_rightptr(); - token get_opername(); - Value accept(ExprVisitor *visitor) override; - -private: - std::unique_ptr left; - std::unique_ptr right; - token oper; + public: + LogicalExpr(std::unique_ptr left_, + token tok, + std::unique_ptr right_); + + Expr *get_leftptr(); + Expr *get_rightptr(); + token get_opername(); + Value accept(ExprVisitor *visitor) override; + + private: + std::unique_ptr left; + std::unique_ptr right; + token oper; }; // класс для выражений в скобках class Grouping : public Expr { -public: - Grouping(std::unique_ptr Expression_); + public: + Grouping(std::unique_ptr Expression_); - Expr *get_expr(); - Value accept(ExprVisitor *visitor); + Expr *get_expr(); + Value accept(ExprVisitor *visitor); -private: - std::unique_ptr expression; + private: + std::unique_ptr expression; }; diff --git a/server/lib/query_language/include/exception.hpp b/server/lib/query_language/include/exception.hpp index efb1f29..b7ed514 100644 --- a/server/lib/query_language/include/exception.hpp +++ b/server/lib/query_language/include/exception.hpp @@ -2,12 +2,12 @@ #include // Базовый класс исключений для компонентов (сканер, парсер, интерпретатор) -class ComponentException : public std::exception { -public: - explicit ComponentException(const char *message); +class ComponentException : public std::runtime_error { + public: + explicit ComponentException(const char *message); - const char *what() const throw() override; + const char *what() const throw() override; -private: - std::string message_; + private: + std::string message_; }; \ No newline at end of file diff --git a/server/lib/query_language/include/interpreter.hpp b/server/lib/query_language/include/interpreter.hpp index cca3aaa..3e1b5d7 100644 --- a/server/lib/query_language/include/interpreter.hpp +++ b/server/lib/query_language/include/interpreter.hpp @@ -2,38 +2,38 @@ #include "parser.hpp" class interpreter : ExprVisitor { -public: - interpreter(); - Value interpret(Expr *expression, nlohmann::json card_); + public: + interpreter(); + Value interpret(Expr *expression, nlohmann::json card_); -private: - nlohmann::json card; - Value result; - auto evaluate(Expr *expression) -> Value; - auto is_truthy(const Value &val) -> bool; - auto is_equal(const Value &left, const Value &right) -> bool; - Value visit(Binary *expr) override; - Value visit(Grouping *expr) override; - Value visit(Unary *expr) override; - Value visit(Literal *expr) override; - Value visit(FuncIn *expr) override; - Value visit(LogicalExpr *ex) override; - auto find_word_inJson(std::string word, nlohmann::json jsonValue) -> bool; - void check_json_operand(const Value &operand); - void check_number_operand(const Value &operand); - void check_number_operands(token oper, const Value &left, const Value &right); - auto find_json_value(const nlohmann::json &card, std::vector) - -> nlohmann::json; - auto json_length(const nlohmann::json &jsonValue) -> double; - auto split_string(const std::string &str) -> std::vector; - auto split_json(const nlohmann::json &jsonValue) -> nlohmann::json; - auto upper_json_string(const nlohmann::json &data) -> nlohmann::json; - auto lower_json_string(const nlohmann::json &data) -> nlohmann::json; - auto reduce_json(const nlohmann::json &jsonElem) -> nlohmann::json; - auto get_self_keys(const nlohmann::json &json_Value) -> nlohmann::json; - auto handle_any_key(const nlohmann::json &json_Value, - const std::vector &levels_vec, - size_t current_index) -> nlohmann::json; - auto mergeJson(const nlohmann::json &jsonLeft, - const nlohmann::json &jsonRight) -> nlohmann::json; + private: + nlohmann::json card; + Value result; + auto evaluate(Expr *expression) -> Value; + auto is_truthy(const Value &val) -> bool; + auto is_equal(const Value &left, const Value &right) -> bool; + Value visit(Binary *expr) override; + Value visit(Grouping *expr) override; + Value visit(Unary *expr) override; + Value visit(Literal *expr) override; + Value visit(FuncIn *expr) override; + Value visit(LogicalExpr *ex) override; + auto find_word_inJson(std::string word, nlohmann::json jsonValue) -> bool; + void check_json_operand(const Value &operand); + void check_json_is_number(const Value &operand); + void check_number_operand(const Value &operand); + auto find_json_value(const nlohmann::json &card, std::vector) + -> nlohmann::json; + auto json_length(const nlohmann::json &jsonValue) -> double; + auto split_string(const std::string &str) -> std::vector; + auto split_json(const nlohmann::json &jsonValue) -> nlohmann::json; + auto upper_json_string(const nlohmann::json &data) -> nlohmann::json; + auto lower_json_string(const nlohmann::json &data) -> nlohmann::json; + auto reduce_json(const nlohmann::json &jsonElem) -> nlohmann::json; + auto get_self_keys(const nlohmann::json &json_Value) -> nlohmann::json; + auto handle_any_key(const nlohmann::json &json_Value, + const std::vector &levels_vec, + size_t current_index) -> nlohmann::json; + auto mergeJson(const nlohmann::json &jsonLeft, + const nlohmann::json &jsonRight) -> nlohmann::json; }; diff --git a/server/lib/query_language/include/parser.hpp b/server/lib/query_language/include/parser.hpp index c050ecf..13e37dd 100644 --- a/server/lib/query_language/include/parser.hpp +++ b/server/lib/query_language/include/parser.hpp @@ -3,28 +3,28 @@ #include "classes.hpp" class parser { -public: - parser(std::vector &t); - std::unique_ptr parse(); + public: + parser(std::vector &t); + std::unique_ptr parse(); -private: - std::vector tokens; - std::vector read_json_elem(); - int current = 0; - bool is_at_end(); - bool check(token_type type); - bool match(std::vector types); - token peek(); - token previous(); - token advance(); - std::unique_ptr primary(); - std::unique_ptr func_in(); - std::unique_ptr unar(); - std::unique_ptr multiplication(); - std::unique_ptr addition(); - std::unique_ptr comparison(); - std::unique_ptr equality(); - std::unique_ptr and_expr(); - std::unique_ptr or_expr(); - std::unique_ptr expression(); + private: + std::vector tokens; + std::vector read_json_elem(); + int current = 0; + bool is_at_end(); + bool check(token_type type); + bool match(std::vector types); + token peek(); + token previous(); + token advance(); + std::unique_ptr primary(); + std::unique_ptr func_in(); + std::unique_ptr unar(); + std::unique_ptr multiplication(); + std::unique_ptr addition(); + std::unique_ptr comparison(); + std::unique_ptr equality(); + std::unique_ptr and_expr(); + std::unique_ptr or_expr(); + std::unique_ptr expression(); }; diff --git a/server/lib/query_language/include/querying.hpp b/server/lib/query_language/include/querying.hpp index 8a57799..e1f36bf 100644 --- a/server/lib/query_language/include/querying.hpp +++ b/server/lib/query_language/include/querying.hpp @@ -8,4 +8,4 @@ auto prepare_filter(const std::string &query) -> std::function(const nlohmann::json &json_card)>; -#endif // !QUERYING_H +#endif // !QUERYING_H diff --git a/server/lib/query_language/include/scaner.hpp b/server/lib/query_language/include/scaner.hpp index d497e86..b5d2699 100644 --- a/server/lib/query_language/include/scaner.hpp +++ b/server/lib/query_language/include/scaner.hpp @@ -7,94 +7,97 @@ #include enum token_type { - LEFT_PAREN, - RIGHT_PAREN, - LEFT_BRACKET, - RIGHT_BRACKET, - COMMA, - DOT, - MINUS, - PLUS, - SEMICOLON, - SLASH, - STAR, - QMARK, - COLON, + LEFT_PAREN, + RIGHT_PAREN, + LEFT_BRACKET, + RIGHT_BRACKET, + COMMA, + DOT, + MINUS, + PLUS, + SEMICOLON, + SLASH, + STAR, + QMARK, + COLON, - BANG, - BANG_EQUAL, - EQUAL, - EQUAL_EQUAL, - GREATER, - GREATER_EQUAL, - LESS, - LESS_EQUAL, + BANG, + BANG_EQUAL, + EQUAL, + EQUAL_EQUAL, + GREATER, + GREATER_EQUAL, + LESS, + LESS_EQUAL, - // Literals - IDENTIFIER, - STRING, - NUMBER, - JSON, - BOOL, - EMPTY, - DOUBLE, + // Literals + IDENTIFIER, + STRING, + NUMBER, + JSON, + BOOL, + EMPTY, + DOUBLE, - // logic - NOT, - AND, - OR, - ANY, - ALL, - FALSE, - TRUE, + // logic + NOT, + AND, + OR, + ANY, + ALL, + FALSE, + TRUE, - // func - IN, - LEN, - SPLIT, - LOWER, - UPPER, - REDUCE, - EOTF, - NUL + // func + IN, + LEN, + SPLIT, + LOWER, + UPPER, + REDUCE, + EOTF, + NUM, + NUL }; using tt = token_type; struct token { - token(); - token(token_type type); - token(token_type type, const std::string &lexeme); - token(token_type type, const std::string &lexeme, const std::string &literal); - token_type type; - std::string lexeme; - std::string literal; + token(); + token(token_type type); + token(token_type type, const std::string &lexeme); + token(token_type type, + const std::string &lexeme, + const std::string &literal); + token_type type; + std::string lexeme; + std::string literal; }; class scanner { -public: - scanner(const std::string &s); - std::vector scan_tokens(); + public: + scanner(const std::string &s); + std::vector scan_tokens(); -private: - std::string source; - std::vector tokens; - std::map keywords; - int start = 0; - int current = 0; + private: + std::string source; + std::vector tokens; + std::map keywords; + int start = 0; + int current = 0; - void init_keywords(); - bool has_next(size_t i = 0); - bool is_digit(char ch); - void add_token(token_type type); - void add_token(token_type type, const std::string &literal); - char advance(); - bool match(const std::string &expected); - char peek(); - char peek_next(); - void number(); - void read_json_level(); - void read_json_keyword(); - void string(); - void scan_token(); + void init_keywords(); + bool has_next(size_t i = 0); + bool is_digit(char ch); + void add_token(token_type type); + void add_token(token_type type, const std::string &literal); + char advance(); + bool match(const std::string &expected); + char peek(); + char peek_next(); + void number(); + void read_json_level(); + void read_json_keyword(); + void string(); + void scan_token(); }; diff --git a/server/lib/query_language/query_lang_tests/src/test_query_lang.cpp b/server/lib/query_language/query_lang_tests/src/test_query_lang.cpp index 9e920af..748b8d9 100644 --- a/server/lib/query_language/query_lang_tests/src/test_query_lang.cpp +++ b/server/lib/query_language/query_lang_tests/src/test_query_lang.cpp @@ -1,10 +1,10 @@ +#include "interpreter.hpp" #include -#include "interpreter.hpp" TEST(QueryLangTest, ScannerTest1) { - scanner scan("1 + 2"); + scanner scan("1 + 2"); std::vector tokens = scan.scan_tokens(); - + ASSERT_EQ(tokens.size(), 4); ASSERT_EQ(tokens[0].type, tt::NUMBER); ASSERT_EQ(tokens[1].type, tt::PLUS); @@ -12,7 +12,7 @@ TEST(QueryLangTest, ScannerTest1) { } TEST(QueryLangTest, ScannerTest2) { - scanner scan("\"A2\" in tags[level]"); + scanner scan("\"A2\" in tags[level]"); std::vector result = scan.scan_tokens(); ASSERT_EQ(result.size(), 7); ASSERT_EQ(result[0].type, tt::STRING); @@ -24,42 +24,68 @@ TEST(QueryLangTest, ScannerTest2) { } nlohmann::json jsonCard = { - {"word", "example"}, - {"special", {"special1", "special2"}}, - {"definition", "This is an example"}, - {"examples", {"Example 1", "Example 2"}}, - {"image_links", {"image1.jpg", "image2.jpg"}}, - {"audio_links", {"audio1.mp3", "audio2.mp3"}}, - {"tags", { - {"tag1", {"value1", "moscow"}}, - {"level", {"A1"}} - }}, - {"other", { - {"key1", "value1 слово pnfvinv 345"}, - {"key2", "value2"}, - {"key3", "value3"} - }} + {"word", "example" }, + {"special", {"special1", "special2"} }, + {"definition", "This is an example" }, + {"examples", {"Example 1", "Example 2"} }, + {"image_links", {"image1.jpg", "image2.jpg"} }, + {"audio_links", {"audio1.mp3", "audio2.mp3"} }, + {"tags", {{"tag1", {"value1", "moscow"}}, {"level", {"A1"}}} }, + {"other", + {{"key1", "value1 слово pnfvinv 345"}, {"key2", 5}, {"key3", "value3"}}} }; TEST(QueryLangTest, InterpreterTestFuncInTrue) { - scanner scan("\"A1\" in tags[level]"); - std::vector tokens = scan.scan_tokens(); - parser par(tokens); + scanner scan("\"A1\" in tags[level]"); + std::vector tokens = scan.scan_tokens(); + parser par(tokens); std::unique_ptr exp = par.parse(); - interpreter inter; - Value result = inter.interpret(exp.get(), jsonCard); - bool containsBool = std::holds_alternative(result); + interpreter inter; + Value result = inter.interpret(exp.get(), jsonCard); + bool containsBool = std::holds_alternative(result); ASSERT_TRUE(std::get(result)); } TEST(QueryLangTest, InterpreterTestFuncInFalse) { - scanner scan("\"A2\" in tags[level]"); - std::vector tokens = scan.scan_tokens(); - parser par(tokens); + scanner scan("\"A2\" in tags[level]"); + std::vector tokens = scan.scan_tokens(); + parser par(tokens); std::unique_ptr exp = par.parse(); - interpreter inter; - Value result = inter.interpret(exp.get(), jsonCard); - bool containsBool = std::holds_alternative(result); + interpreter inter; + Value result = inter.interpret(exp.get(), jsonCard); + bool containsBool = std::holds_alternative(result); ASSERT_FALSE(std::get(result)); } +TEST(QueryLangTest, InterpreterTestFuncInAnd) { + scanner scan("\"A1\" in tags[level] and \"value3\" in other[key3]"); + std::vector tokens = scan.scan_tokens(); + parser par(tokens); + std::unique_ptr exp = par.parse(); + interpreter inter; + Value result = inter.interpret(exp.get(), jsonCard); + bool containsBool = std::holds_alternative(result); + ASSERT_TRUE(std::get(result)); +} + +TEST(QueryLangTest, InterpreterTestNumber) { + scanner scan("1 + 3/(4-1)*(2+1)"); + std::vector tokens = scan.scan_tokens(); + parser par(tokens); + std::unique_ptr exp = par.parse(); + interpreter inter; + Value result = inter.interpret(exp.get(), jsonCard); + double containsDouble = std::holds_alternative(result); + ASSERT_EQ(std::get(result), 4); +} + +TEST(QueryLangTest, InterpreterTestFuncNum) { + scanner scan("num(other[key2])"); + std::vector tokens = scan.scan_tokens(); + parser par(tokens); + std::unique_ptr exp = par.parse(); + interpreter inter; + Value result = inter.interpret(exp.get(), jsonCard); + double containsDouble = std::holds_alternative(result); + ASSERT_EQ(std::get(result), 5); +} diff --git a/server/lib/query_language/src/classes.cpp b/server/lib/query_language/src/classes.cpp index 61b33e7..6fb26d5 100644 --- a/server/lib/query_language/src/classes.cpp +++ b/server/lib/query_language/src/classes.cpp @@ -1,67 +1,112 @@ #include "classes.hpp" -Literal::Literal(std::string v) : val(std::move(v)) {} +Literal::Literal(std::string v) : val(std::move(v)) { +} -Literal::Literal(double d) : val(d) {} +Literal::Literal(double d) : val(d) { +} -Literal::Literal(bool b) : val(b) {} +Literal::Literal(bool b) : val(b) { +} Literal::Literal(std::vector json_namevec_) - : json_namevec(std::move(json_namevec_)) {} + : json_namevec(std::move(json_namevec_)) { +} -Literal::Literal() : val(std::monostate{}) {} +Literal::Literal() : val(std::monostate{}) { +} -Value &Literal::get_value() { return val; } +Value &Literal::get_value() { + return val; +} -std::vector Literal::get_json_namevec() { return json_namevec; } +std::vector Literal::get_json_namevec() { + return json_namevec; +} -Value Literal::accept(ExprVisitor *visitor) { return visitor->visit(this); } +Value Literal::accept(ExprVisitor *visitor) { + return visitor->visit(this); +} -Binary::Binary(std::unique_ptr left_, token tok, +Binary::Binary(std::unique_ptr left_, + token tok, std::unique_ptr right_) : left(std::move(left_)), oper(tok), right(std::move(right_)){}; -Value Binary::accept(ExprVisitor *visitor) { return visitor->visit(this); } +Value Binary::accept(ExprVisitor *visitor) { + return visitor->visit(this); +} -Expr *Binary::get_leftptr() { return left.get(); } +Expr *Binary::get_leftptr() { + return left.get(); +} -Expr *Binary::get_rightptr() { return right.get(); } +Expr *Binary::get_rightptr() { + return right.get(); +} -token Binary::get_opername() { return oper; } +token Binary::get_opername() { + return oper; +} Unary::Unary(std::unique_ptr expr_, token tok) : expression(std::move(expr_)), oper(tok){}; -Expr *Unary::get_expr() { return expression.get(); } +Expr *Unary::get_expr() { + return expression.get(); +} -token Unary::get_opername() { return oper; } +token Unary::get_opername() { + return oper; +} -Value Unary::accept(ExprVisitor *visitor) { return visitor->visit(this); } +Value Unary::accept(ExprVisitor *visitor) { + return visitor->visit(this); +} -LogicalExpr::LogicalExpr(std::unique_ptr left_, token tok, +LogicalExpr::LogicalExpr(std::unique_ptr left_, + token tok, std::unique_ptr right_) : left(std::move(left_)), oper(tok), right(std::move(right_)){}; -Value LogicalExpr::accept(ExprVisitor *visitor) { return visitor->visit(this); } +Value LogicalExpr::accept(ExprVisitor *visitor) { + return visitor->visit(this); +} -Expr *LogicalExpr::get_leftptr() { return left.get(); } +Expr *LogicalExpr::get_leftptr() { + return left.get(); +} -Expr *LogicalExpr::get_rightptr() { return right.get(); } +Expr *LogicalExpr::get_rightptr() { + return right.get(); +} -token LogicalExpr::get_opername() { return oper; } +token LogicalExpr::get_opername() { + return oper; +} FuncIn::FuncIn(std::unique_ptr left_, std::unique_ptr right_) : left(std::move(left_)), right(std::move(right_)){}; -Value FuncIn::accept(ExprVisitor *visitor) { return visitor->visit(this); } +Value FuncIn::accept(ExprVisitor *visitor) { + return visitor->visit(this); +} -Expr *FuncIn::get_leftptr() { return left.get(); } +Expr *FuncIn::get_leftptr() { + return left.get(); +} -Expr *FuncIn::get_rightptr() { return right.get(); } +Expr *FuncIn::get_rightptr() { + return right.get(); +} Grouping::Grouping(std::unique_ptr Expr_) : expression(std::move(Expr_)){}; -Value Grouping::accept(ExprVisitor *visitor) { return visitor->visit(this); } +Value Grouping::accept(ExprVisitor *visitor) { + return visitor->visit(this); +} -Expr *Grouping::get_expr() { return expression.get(); } \ No newline at end of file +Expr *Grouping::get_expr() { + return expression.get(); +} \ No newline at end of file diff --git a/server/lib/query_language/src/exception.cpp b/server/lib/query_language/src/exception.cpp index d188a83..053fbed 100644 --- a/server/lib/query_language/src/exception.cpp +++ b/server/lib/query_language/src/exception.cpp @@ -2,8 +2,9 @@ #include ComponentException::ComponentException(const char *message) - : message_(message) {} + : std::runtime_error(message), message_(message) { +} const char *ComponentException::what() const throw() { - return message_.c_str(); + return message_.c_str(); } \ No newline at end of file diff --git a/server/lib/query_language/src/interpreter.cpp b/server/lib/query_language/src/interpreter.cpp index 42a32b7..98ae357 100644 --- a/server/lib/query_language/src/interpreter.cpp +++ b/server/lib/query_language/src/interpreter.cpp @@ -3,407 +3,405 @@ interpreter::interpreter(){}; Value interpreter::interpret(Expr *expression, nlohmann::json card_) { - card = card_; - return evaluate(expression); + card = card_; + return evaluate(expression); } Value interpreter::evaluate(Expr *expression) { - return expression->accept(this); + return expression->accept(this); } bool interpreter::is_truthy(const Value &val) { - if (std::holds_alternative(val)) { - return false; - } - if (std::holds_alternative(val)) { - return std::get(val) != 0; - } - if (std::holds_alternative(val)) { - return std::get(val); - } - - return true; + if (std::holds_alternative(val)) { + return false; + } + if (std::holds_alternative(val)) { + return std::get(val) != 0; + } + if (std::holds_alternative(val)) { + return std::get(val); + } + + return true; } bool interpreter::is_equal(const Value &left, const Value &right) { - if (std::holds_alternative(left) && - std::holds_alternative(right)) { + if (std::holds_alternative(left) && + std::holds_alternative(right)) { - return std::get(left) == std::get(right); + return std::get(left) == std::get(right); - } else if (std::holds_alternative(left) && - std::holds_alternative(right)) { + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { - return std::get(left) == std::get(right); + return std::get(left) == std::get(right); - } else if (std::holds_alternative(left) && - std::holds_alternative(right)) { + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { - return std::get(left) == std::get(right); + return std::get(left) == + std::get(right); - } else if (std::holds_alternative(left) && - std::holds_alternative(right)) { + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { - return true; // Если оба значения имеют тип std::monostate, считаем их - // равными - } + return true; // Если оба значения имеют тип std::monostate, считаем их + // равными + } - return false; // Если типы не совпадают, считаем значения неравными + return false; // Если типы не совпадают, считаем значения неравными } void interpreter::check_number_operand(const Value &operand) { - if (!std::holds_alternative(operand)) { - throw ComponentException("Invalid operand type"); - } + if (!std::holds_alternative(operand)) { + throw ComponentException("Invalid operand type"); + } } void interpreter::check_json_operand(const Value &operand) { - if (!std::holds_alternative(operand)) { - throw ComponentException("Expected JSON"); - } + if (!std::holds_alternative(operand)) { + throw ComponentException("Expected JSON"); + } } -/* -void interpreter::check_number_operands(token oper, const Value& left, const -Value& right) { std::visit([&](auto&& left_, auto&& right_) { using LeftType = -std::decay_t; using RightType = std::decay_t; - - if constexpr (std::is_same_v && -std::is_same_v) { if (right_ == 0 && oper.type == tt::SLASH) -{ throw ComponentException("Division by zero"); - } - } else { - throw ComponentException("Invalid operand type"); - } - }, left, right); +void interpreter::check_json_is_number(const Value &operand) { + if (!std::get(operand).is_number()) { + throw ComponentException("JSON is not a number"); + } } -*/ Value interpreter::visit(Binary *expr) { - Value left = evaluate(expr->get_leftptr()); - Value right = evaluate(expr->get_rightptr()); + Value left = evaluate(expr->get_leftptr()); + Value right = evaluate(expr->get_rightptr()); - if (std::holds_alternative(left) && - std::holds_alternative(right)) { - double left_ = std::get(left); - double right_ = std::get(right); - switch (expr->get_opername().type) { - case PLUS: - return Value(left_ + right_); - case MINUS: - return Value(left_ - right_); + if (std::holds_alternative(left) && + std::holds_alternative(right)) { + double left_ = std::get(left); + double right_ = std::get(right); + switch (expr->get_opername().type) { + case PLUS: + return Value(left_ + right_); + case MINUS: + return Value(left_ - right_); - case STAR: - return Value(left_ * right_); + case STAR: + return Value(left_ * right_); - case SLASH: - return Value(left_ / right_); + case SLASH: + return Value(left_ / right_); - case LESS: - return Value(left_ < right_); + case LESS: + return Value(left_ < right_); - case LESS_EQUAL: - return Value(left_ <= right_); + case LESS_EQUAL: + return Value(left_ <= right_); - case GREATER: - return Value(left_ > right_); + case GREATER: + return Value(left_ > right_); - case GREATER_EQUAL: - return Value(left >= right); + case GREATER_EQUAL: + return Value(left >= right); - case BANG_EQUAL: - return Value(!is_equal(left_, right_)); + case BANG_EQUAL: + return Value(!is_equal(left_, right_)); - case EQUAL_EQUAL: - return Value(is_equal(left_, right_)); + case EQUAL_EQUAL: + return Value(is_equal(left_, right_)); - default: - throw ComponentException("Invalid operand type"); - } - } else if (std::holds_alternative(left) && - std::holds_alternative(right)) { - nlohmann::json left_ = std::get(left); - nlohmann::json right_ = std::get(right); - if (expr->get_opername().type == PLUS) { - return Value(mergeJson(left_, right_)); + default: + throw ComponentException("Invalid operand type"); + } + } else if (std::holds_alternative(left) && + std::holds_alternative(right)) { + nlohmann::json left_ = std::get(left); + nlohmann::json right_ = std::get(right); + if (expr->get_opername().type == PLUS) { + return Value(mergeJson(left_, right_)); + } else { + throw ComponentException("Invalid operand type"); + } } else { - throw ComponentException("Invalid operand type"); + throw ComponentException("Invalid operand type"); } - } else { - throw ComponentException("Invalid operand type"); - } } Value interpreter::visit(Grouping *expr) { - return expr->get_expr()->accept(this); + return expr->get_expr()->accept(this); } Value interpreter::visit(FuncIn *expr) { - Value left = evaluate(expr->get_leftptr()); - Value right = evaluate(expr->get_rightptr()); - - if (std::holds_alternative(left) && - std::holds_alternative(right)) { - - std::string left_ = std::get(left); - nlohmann::json right_ = std::get(right); - return Value(find_word_inJson(left_, right_)); - } else { - return Value(false); - } + Value left = evaluate(expr->get_leftptr()); + Value right = evaluate(expr->get_rightptr()); + + if (std::holds_alternative(left) && + std::holds_alternative(right)) { + + std::string left_ = std::get(left); + nlohmann::json right_ = std::get(right); + return Value(find_word_inJson(left_, right_)); + } else { + return Value(false); + } } Value interpreter::visit(Unary *expr) { - Value right = evaluate(expr->get_expr()); - - switch (expr->get_opername().type) { - case tt::MINUS: - check_number_operand(right); - return Value(-std::get(right)); - case tt::NOT: - return Value(!is_truthy(right)); - case tt::LEN: - check_json_operand(right); - return Value(json_length(std::get(right))); - case tt::SPLIT: - check_json_operand(right); - return Value(split_json(std::get(right))); - case tt::UPPER: - check_json_operand(right); - return Value(upper_json_string(std::get(right))); - case tt::LOWER: - check_json_operand(right); - return Value(lower_json_string(std::get(right))); - case tt::REDUCE: - check_json_operand(right); - return Value(reduce_json(std::get(right))); - default: - throw ComponentException("Invalid operand type"); - } + Value right = evaluate(expr->get_expr()); + + switch (expr->get_opername().type) { + case tt::MINUS: + check_number_operand(right); + return Value(-std::get(right)); + case tt::NOT: + return Value(!is_truthy(right)); + case tt::LEN: + check_json_operand(right); + return Value(json_length(std::get(right))); + case tt::SPLIT: + check_json_operand(right); + return Value(split_json(std::get(right))); + case tt::UPPER: + check_json_operand(right); + return Value(upper_json_string(std::get(right))); + case tt::LOWER: + check_json_operand(right); + return Value(lower_json_string(std::get(right))); + case tt::REDUCE: + check_json_operand(right); + return Value(reduce_json(std::get(right))); + case tt::NUM: + check_json_operand(right); + check_json_is_number(right); + return Value(std::get(right).get()); + default: + throw ComponentException("Invalid operand type"); + } } Value interpreter::visit(LogicalExpr *ex) { - Value left = evaluate(ex->get_leftptr()); - if (ex->get_opername().type == OR) { - if (is_truthy(left)) { - return left; - } - } else { - if (!is_truthy(left)) { - return left; + Value left = evaluate(ex->get_leftptr()); + if (ex->get_opername().type == OR) { + if (is_truthy(left)) { + return left; + } + } else { + if (!is_truthy(left)) { + return left; + } } - } - return evaluate(ex->get_rightptr()); + return evaluate(ex->get_rightptr()); } Value interpreter::visit(Literal *expr) { - if (!expr->get_json_namevec().empty()) { - nlohmann::json json_val = find_json_value(card, expr->get_json_namevec()); - if (!json_val.empty()) { - expr->get_value() = Value(json_val); - } else { - expr->get_value() = Value(); + if (!expr->get_json_namevec().empty()) { + nlohmann::json json_val = + find_json_value(card, expr->get_json_namevec()); + if (!json_val.empty()) { + expr->get_value() = Value(json_val); + } else { + expr->get_value() = Value(); + } } - } - return expr->get_value(); + return expr->get_value(); } nlohmann::json interpreter::upper_json_string(const nlohmann::json &data) { - if (data.is_string()) { - std::string str = data.get(); - std::transform(str.begin(), str.end(), str.begin(), ::toupper); - return str; - } + if (data.is_string()) { + std::string str = data.get(); + std::transform(str.begin(), str.end(), str.begin(), ::toupper); + return str; + } - if (data.is_array()) { - nlohmann::json result = nlohmann::json::array(); - for (const auto &item : data) { - result.push_back(upper_json_string(item)); + if (data.is_array()) { + nlohmann::json result = nlohmann::json::array(); + for (const auto &item : data) { + result.push_back(upper_json_string(item)); + } + return result; } - return result; - } - return data; + return data; } nlohmann::json interpreter::lower_json_string(const nlohmann::json &data) { - if (data.is_string()) { - std::string str = data.get(); - std::transform(str.begin(), str.end(), str.begin(), ::tolower); - return str; - } + if (data.is_string()) { + std::string str = data.get(); + std::transform(str.begin(), str.end(), str.begin(), ::tolower); + return str; + } - if (data.is_array()) { - nlohmann::json result = nlohmann::json::array(); - for (const auto &item : data) { - result.push_back(lower_json_string(item)); + if (data.is_array()) { + nlohmann::json result = nlohmann::json::array(); + for (const auto &item : data) { + result.push_back(lower_json_string(item)); + } + return result; } - return result; - } - return data; + return data; } std::vector interpreter::split_string(const std::string &str) { - std::vector words; - std::string word; - std::istringstream iss(str); - while (iss >> word) { - words.push_back(word); - } - return words; + std::vector words; + std::string word; + std::istringstream iss(str); + while (iss >> word) { + words.push_back(word); + } + return words; } // Рекурсивная функция для разделения JSON элемента nlohmann::json interpreter::split_json(const nlohmann::json &jsonValue) { - if (jsonValue.is_null()) { - throw ComponentException("Element is null"); - } - - if (jsonValue.is_string()) { - std::string str = jsonValue.get(); - return split_string(str); - } - - if (jsonValue.is_array()) { - nlohmann::json result = nlohmann::json::array(); - for (const auto &item : jsonValue) { - if (item.is_string()) { - std::string str = item.get(); - result.push_back(split_string(str)); - } + if (jsonValue.is_null()) { + throw ComponentException("Element is null"); + } + + if (jsonValue.is_string()) { + std::string str = jsonValue.get(); + return split_string(str); + } + + if (jsonValue.is_array()) { + nlohmann::json result = nlohmann::json::array(); + for (const auto &item : jsonValue) { + if (item.is_string()) { + std::string str = item.get(); + result.push_back(split_string(str)); + } + } + return result; } - return result; - } - throw ComponentException("Invalid operation"); + throw ComponentException("Invalid operation"); } double interpreter::json_length(const nlohmann::json &jsonValue) { - if (jsonValue.is_null()) { - throw ComponentException("Element is null"); - } + if (jsonValue.is_null()) { + throw ComponentException("Element is null"); + } - if (jsonValue.is_array() || jsonValue.is_object()) { - return jsonValue.size(); - } + if (jsonValue.is_array() || jsonValue.is_object()) { + return jsonValue.size(); + } - return 1; // неитерируемый объект, например число или строка + return 1; // неитерируемый объект, например число или строка } bool interpreter::find_word_inJson(std::string word, nlohmann::json jsonValue) { - if (jsonValue.is_string()) { - return jsonValue.get() == word; - } + if (jsonValue.is_string()) { + return jsonValue.get() == word; + } - if (!jsonValue.is_array()) { - return false; - } + if (!jsonValue.is_array()) { + return false; + } - bool found = std::ranges::any_of(jsonValue, [&](const auto &element) { - return find_word_inJson(word, element); - }); + bool found = std::ranges::any_of(jsonValue, [&](const auto &element) { + return find_word_inJson(word, element); + }); - if (found) { - return true; - } + if (found) { + return true; + } - return false; + return false; } nlohmann::json -interpreter::find_json_value(const nlohmann::json &card, +interpreter::find_json_value(const nlohmann::json &card, std::vector levels_vec) { - nlohmann::json current_json = card; - - for (size_t i = 0; i < levels_vec.size(); ++i) { - std::string key = levels_vec[i]; - - if (current_json.is_object()) { - if (current_json.contains(key)) { - current_json = current_json[key]; - } else if (key == "$ANY") { - return handle_any_key(current_json, levels_vec, i); - } else if (key == "$SELF") { - return get_self_keys(current_json); - } else { - throw ComponentException("Invalid operand type"); - } - } else { - throw ComponentException("Invalid operand type"); + nlohmann::json current_json = card; + + for (size_t i = 0; i < levels_vec.size(); ++i) { + std::string key = levels_vec[i]; + + if (current_json.is_object()) { + if (current_json.contains(key)) { + current_json = current_json[key]; + } else if (key == "$ANY") { + return handle_any_key(current_json, levels_vec, i); + } else if (key == "$SELF") { + return get_self_keys(current_json); + } else { + throw ComponentException("Invalid operand type"); + } + } else { + throw ComponentException("Invalid operand type"); + } } - } - return current_json; + return current_json; } nlohmann::json -interpreter::handle_any_key(const nlohmann::json &json_Value, +interpreter::handle_any_key(const nlohmann::json &json_Value, const std::vector &levels_vec, - size_t current_index) { - nlohmann::json any_values; + size_t current_index) { + nlohmann::json any_values; - for (auto it = json_Value.begin(); it != json_Value.end(); ++it) { - const auto &result = find_json_value( - it.value(), - std::vector(levels_vec.begin() + current_index + 1, - levels_vec.end())); + for (auto it = json_Value.begin(); it != json_Value.end(); ++it) { + const auto &result = find_json_value( + it.value(), + std::vector(levels_vec.begin() + current_index + 1, + levels_vec.end())); - if (!result.is_null()) { - any_values.push_back(result); + if (!result.is_null()) { + any_values.push_back(result); + } } - } - if (any_values.size() == 1) { // возвращаем элемент, а не массив - return any_values[0]; - } else { - return any_values; - } + if (any_values.size() == 1) { // возвращаем элемент, а не массив + return any_values[0]; + } else { + return any_values; + } } nlohmann::json interpreter::get_self_keys(const nlohmann::json &json_Value) { - nlohmann::json self_keys; + nlohmann::json self_keys; - for (auto it = json_Value.begin(); it != json_Value.end(); ++it) { - self_keys.push_back(it.key()); - } + for (auto it = json_Value.begin(); it != json_Value.end(); ++it) { + self_keys.push_back(it.key()); + } - return self_keys; + return self_keys; } nlohmann::json interpreter::reduce_json(const nlohmann::json &jsonElem) { - if (jsonElem.is_null()) { - throw ComponentException("Element is null"); - } + if (jsonElem.is_null()) { + throw ComponentException("Element is null"); + } - nlohmann::json result; + nlohmann::json result; - for (const auto &item : jsonElem) { - if (item.is_array()) { - for (const auto &nestedItem : item) { - result.push_back(nestedItem); - } - } else { - result.push_back(item); + for (const auto &item : jsonElem) { + if (item.is_array()) { + for (const auto &nestedItem : item) { + result.push_back(nestedItem); + } + } else { + result.push_back(item); + } } - } - return result; + return result; } nlohmann::json interpreter::mergeJson(const nlohmann::json &jsonLeft, const nlohmann::json &jsonRight) { - nlohmann::json mergedJson = nlohmann::json::object(); - - for (nlohmann::json::const_iterator it = jsonLeft.begin(); - it != jsonLeft.end(); ++it) { - mergedJson[it.key()] = it.value(); - } - for (nlohmann::json::const_iterator it = jsonRight.begin(); - it != jsonRight.end(); ++it) { - mergedJson[it.key()] = it.value(); - } - return mergedJson; + nlohmann::json mergedJson = nlohmann::json::object(); + + for (nlohmann::json::const_iterator it = jsonLeft.begin(); + it != jsonLeft.end(); + ++it) { + mergedJson[it.key()] = it.value(); + } + for (nlohmann::json::const_iterator it = jsonRight.begin(); + it != jsonRight.end(); + ++it) { + mergedJson[it.key()] = it.value(); + } + return mergedJson; } diff --git a/server/lib/query_language/src/parser.cpp b/server/lib/query_language/src/parser.cpp index 6939a30..ec9223b 100644 --- a/server/lib/query_language/src/parser.cpp +++ b/server/lib/query_language/src/parser.cpp @@ -2,174 +2,196 @@ parser::parser(std::vector &t) : tokens(t){}; -bool parser::is_at_end() { return tokens[current].type == token_type::EOTF; } +bool parser::is_at_end() { + return tokens[current].type == token_type::EOTF; +} -token parser::peek() { return tokens[current]; } +token parser::peek() { + return tokens[current]; +} -token parser::previous() { return tokens[current - 1]; } +token parser::previous() { + return tokens[current - 1]; +} token parser::advance() { - if (!is_at_end()) - current++; - return previous(); + if (!is_at_end()) + current++; + return previous(); } bool parser::check(token_type type) { - return !is_at_end() && peek().type == type; + return !is_at_end() && peek().type == type; } bool parser::match(std::vector types) { - return std::ranges::any_of(types, [this](const token_type &type) { - if (check(type)) { - advance(); - return true; - } - return false; - }); + return std::ranges::any_of(types, [this](const token_type &type) { + if (check(type)) { + advance(); + return true; + } + return false; + }); } std::unique_ptr parser::primary() { - token_type type = peek().type; - advance(); - - switch (type) { - case tt::FALSE: - return std::make_unique(false); - case tt::TRUE: - return std::make_unique(true); - case tt::NUMBER: - return std::make_unique(std::stod(previous().literal)); - case tt::STRING: - return std::make_unique(previous().literal); - case tt::LEFT_PAREN: { - std::unique_ptr Expr = expression(); - if (match({tt::RIGHT_PAREN})) { - return std::make_unique(std::move(Expr)); - } - throw ComponentException("Missing closing parenthesis for grouping."); - } - case tt::IDENTIFIER: { - std::vector json_fields = read_json_elem(); - if (!json_fields.empty()) { - return std::make_unique(json_fields); + token_type type = peek().type; + advance(); + + switch (type) { + case tt::FALSE: + return std::make_unique(false); + case tt::TRUE: + return std::make_unique(true); + case tt::NUMBER: + return std::make_unique(std::stod(previous().literal)); + case tt::STRING: + return std::make_unique(previous().literal); + case tt::LEFT_PAREN: { + std::unique_ptr Expr = expression(); + if (match({tt::RIGHT_PAREN})) { + return std::make_unique(std::move(Expr)); + } + throw ComponentException( + "Missing closing parenthesis for grouping."); + } + case tt::IDENTIFIER: { + std::vector json_fields = read_json_elem(); + if (!json_fields.empty()) { + return std::make_unique(json_fields); + } + throw ComponentException("Invalid JSON element."); + } + default: + throw ComponentException("Unexpected token encountered."); } - throw ComponentException("Invalid JSON element."); - } - default: - throw ComponentException("Unexpected token encountered."); - } } std::vector parser::read_json_elem() { - std::vector json_fields; - json_fields.push_back(previous().lexeme); - while (match({tt::LEFT_BRACKET})) { - if (match({tt::IDENTIFIER})) { - json_fields.push_back(previous().lexeme); - } else { - return std::vector(); + std::vector json_fields; + json_fields.push_back(previous().lexeme); + while (match({tt::LEFT_BRACKET})) { + if (match({tt::IDENTIFIER})) { + json_fields.push_back(previous().lexeme); + } else { + return std::vector(); + } + + if (!match({tt::RIGHT_BRACKET})) { + throw ComponentException("Missing closing parenthesis for JSON."); + } } - - if (!match({tt::RIGHT_BRACKET})) { - throw ComponentException("Missing closing parenthesis for JSON."); - } - } - return json_fields; + return json_fields; } std::unique_ptr parser::func_in() { - std::unique_ptr left = primary(); - if (match({tt::IN})) { - /*if(!match({tt::LEFT_PAREN})){ - throw ComponentException("Missing open parenthesis for function call."); - }*/ + std::unique_ptr left = primary(); + if (match({tt::IN})) { + /*if(!match({tt::LEFT_PAREN})){ + throw ComponentException("Missing open parenthesis for function + call."); + }*/ - std::unique_ptr right = primary(); + std::unique_ptr right = primary(); - /*if (!match({tt::RIGHT_PAREN})) { - throw ComponentException("Missing closing parenthesis for function - call."); - }*/ + /*if (!match({tt::RIGHT_PAREN})) { + throw ComponentException("Missing closing parenthesis for function + call."); + }*/ - return std::make_unique(std::move(left), std::move(right)); - } - return left; + return std::make_unique(std::move(left), std::move(right)); + } + return left; } std::unique_ptr parser::unar() { - if (match({tt::NOT, tt::MINUS, tt::LEN, tt::SPLIT, tt::UPPER, tt::LOWER, - tt::REDUCE})) { - token oper = previous(); - std::unique_ptr right = unar(); - return std::make_unique(std::move(right), oper); - } - return func_in(); + if (match({tt::NOT, + tt::MINUS, + tt::LEN, + tt::SPLIT, + tt::UPPER, + tt::LOWER, + tt::REDUCE, + tt::NUM})) { + token oper = previous(); + std::unique_ptr right = unar(); + return std::make_unique(std::move(right), oper); + } + return func_in(); } std::unique_ptr parser::multiplication() { - std::unique_ptr left = unar(); - while (match({tt::SLASH, tt::STAR})) { - token oper = previous(); - std::unique_ptr right = unar(); - left = std::make_unique(std::move(left), oper, std::move(right)); - } - return left; + std::unique_ptr left = unar(); + while (match({tt::SLASH, tt::STAR})) { + token oper = previous(); + std::unique_ptr right = unar(); + left = + std::make_unique(std::move(left), oper, std::move(right)); + } + return left; } std::unique_ptr parser::addition() { - std::unique_ptr left = multiplication(); - while (match({tt::MINUS, tt::PLUS})) { - token oper = previous(); - std::unique_ptr right = multiplication(); - left = std::make_unique(std::move(left), oper, std::move(right)); - } - return left; + std::unique_ptr left = multiplication(); + while (match({tt::MINUS, tt::PLUS})) { + token oper = previous(); + std::unique_ptr right = multiplication(); + left = + std::make_unique(std::move(left), oper, std::move(right)); + } + return left; } std::unique_ptr parser::comparison() { - std::unique_ptr left = addition(); - while (match({tt::LESS, tt::LESS_EQUAL, tt::GREATER, tt::GREATER_EQUAL})) { - token oper = previous(); - std::unique_ptr right = addition(); - left = std::make_unique(std::move(left), oper, std::move(right)); - } - return left; + std::unique_ptr left = addition(); + while (match({tt::LESS, tt::LESS_EQUAL, tt::GREATER, tt::GREATER_EQUAL})) { + token oper = previous(); + std::unique_ptr right = addition(); + left = + std::make_unique(std::move(left), oper, std::move(right)); + } + return left; } std::unique_ptr parser::equality() { - std::unique_ptr left = comparison(); - while (match({tt::BANG_EQUAL, tt::EQUAL_EQUAL})) { - token oper = previous(); - std::unique_ptr right = comparison(); - left = std::make_unique(std::move(left), oper, std::move(right)); - } - return left; + std::unique_ptr left = comparison(); + while (match({tt::BANG_EQUAL, tt::EQUAL_EQUAL})) { + token oper = previous(); + std::unique_ptr right = comparison(); + left = + std::make_unique(std::move(left), oper, std::move(right)); + } + return left; } std::unique_ptr parser::and_expr() { - std::unique_ptr left = equality(); + std::unique_ptr left = equality(); - while (match({tt::AND})) { - token oper = previous(); - std::unique_ptr right = equality(); - left = - std::make_unique(std::move(left), oper, std::move(right)); - } - return left; + while (match({tt::AND})) { + token oper = previous(); + std::unique_ptr right = equality(); + left = std::make_unique( + std::move(left), oper, std::move(right)); + } + return left; } std::unique_ptr parser::or_expr() { - std::unique_ptr left = and_expr(); + std::unique_ptr left = and_expr(); - while (match({tt::OR})) { - token oper = previous(); - std::unique_ptr right = and_expr(); - left = - std::make_unique(std::move(left), oper, std::move(right)); - } - return left; + while (match({tt::OR})) { + token oper = previous(); + std::unique_ptr right = and_expr(); + left = std::make_unique( + std::move(left), oper, std::move(right)); + } + return left; } -std::unique_ptr parser::expression() { return or_expr(); } +std::unique_ptr parser::expression() { + return or_expr(); +} -std::unique_ptr parser::parse() { return expression(); } +std::unique_ptr parser::parse() { + return expression(); +} diff --git a/server/lib/query_language/src/scaner.cpp b/server/lib/query_language/src/scaner.cpp index b57272c..53677fb 100644 --- a/server/lib/query_language/src/scaner.cpp +++ b/server/lib/query_language/src/scaner.cpp @@ -1,209 +1,223 @@ #include "scaner.hpp" -token::token() : type(token_type::NUL), lexeme(""), literal("") {} +token::token() : type(token_type::NUL) { +} -token::token(token_type type) : type(type), lexeme(""), literal("") {} +token::token(token_type type) : type(type) { +} token::token(token_type type, const std::string &lexeme) - : type(type), lexeme(lexeme), literal("") {} + : type(type), lexeme(lexeme) { +} -token::token(token_type type, const std::string &lexeme, +token::token(token_type type, + const std::string &lexeme, const std::string &literal) - : type(type), lexeme(lexeme), literal(literal) {} + : type(type), lexeme(lexeme), literal(literal) { +} void scanner::init_keywords() { - keywords["in"] = tt::IN; - keywords["len"] = tt::LEN; - keywords["split"] = tt::SPLIT; - keywords["lower"] = tt::LOWER; - keywords["upper"] = tt::UPPER; - keywords["all"] = tt::ALL; - keywords["any"] = tt::ANY; - keywords["and"] = tt::AND; - keywords["or"] = tt::OR; - keywords["not"] = tt::NOT; - keywords["reduce"] = tt::REDUCE; + keywords["in"] = tt::IN; + keywords["len"] = tt::LEN; + keywords["split"] = tt::SPLIT; + keywords["lower"] = tt::LOWER; + keywords["upper"] = tt::UPPER; + keywords["all"] = tt::ALL; + keywords["any"] = tt::ANY; + keywords["and"] = tt::AND; + keywords["or"] = tt::OR; + keywords["not"] = tt::NOT; + keywords["reduce"] = tt::REDUCE; + keywords["num"] = tt::NUM; } -bool scanner::has_next(size_t i) { return current + i < source.size(); } +bool scanner::has_next(size_t i) { + return current + i < source.size(); +} -bool scanner::is_digit(char ch) { return std::isdigit(ch); } +bool scanner::is_digit(char ch) { + return std::isdigit(ch); +} -void scanner::add_token(token_type type) { add_token(type, ""); } +void scanner::add_token(token_type type) { + add_token(type, ""); +} void scanner::add_token(token_type type, const std::string &literal) { - std::string text = source.substr(start, current - start); - tokens.emplace_back(type, text, literal); + std::string text = source.substr(start, current - start); + tokens.emplace_back(type, text, literal); } char scanner::advance() { - current++; - return source[current - 1]; + current++; + return source[current - 1]; } bool scanner::match(const std::string &expected) { - if (!has_next(expected.size())) - return false; - if (source.substr(current, expected.size()) != expected) - return false; - current += expected.size(); - return true; + if (!has_next(expected.size())) + return false; + if (source.substr(current, expected.size()) != expected) + return false; + current += expected.size(); + return true; } char scanner::peek() { - if (!has_next()) { - return '\0'; - } - return source[current]; + if (!has_next()) { + return '\0'; + } + return source[current]; } char scanner::peek_next() { - if (current + 1 >= source.size()) { - return '\0'; - } - return source[current + 1]; + if (current + 1 >= source.size()) { + return '\0'; + } + return source[current + 1]; } void scanner::number() { - while (is_digit(peek())) { - advance(); - } - - if (peek() == '.' && is_digit(peek_next())) { - advance(); while (is_digit(peek())) { - advance(); + advance(); } - } - add_token(tt::NUMBER, source.substr(start, current - start)); + if (peek() == '.' && is_digit(peek_next())) { + advance(); + while (is_digit(peek())) { + advance(); + } + } + + add_token(tt::NUMBER, source.substr(start, current - start)); } void scanner::read_json_keyword() { - advance(); // считали $ - while (isalnum(peek()) || peek() == '_') { - advance(); - } - std::string text = source.substr(start, current - start); - if (text == "$ANY" || text == "$SELF") { - add_token(tt::IDENTIFIER); - } - // + advance(); // считали $ + while (isalnum(peek()) || peek() == '_') { + advance(); + } + std::string text = source.substr(start, current - start); + if (text == "$ANY" || text == "$SELF") { + add_token(tt::IDENTIFIER); + } + // } void scanner::read_json_level() { - while (isalnum(peek()) || peek() == '_') { - advance(); - } - std::string text = source.substr(start, current - start); - auto type = keywords.find(text); - type == keywords.end() ? add_token(tt::IDENTIFIER) : add_token(type->second); + while (isalnum(peek()) || peek() == '_') { + advance(); + } + std::string text = source.substr(start, current - start); + auto type = keywords.find(text); + type == keywords.end() ? add_token(tt::IDENTIFIER) + : add_token(type->second); } void scanner::string() { - while (peek() != '"' && has_next()) { - advance(); - } + while (peek() != '"' && has_next()) { + advance(); + } - // нет вторых кавычек - if (!has_next()) { + // нет вторых кавычек + if (!has_next()) { - throw ComponentException("Missing closing quotation mark for string."); - } + throw ComponentException("Missing closing quotation mark for string."); + } - advance(); // пропуск для кавычки - // добавляем слово без кавычек - std::string value = source.substr(start + 1, current - start - 2); - add_token(tt::STRING, value); + advance(); // пропуск для кавычки + // добавляем слово без кавычек + std::string value = source.substr(start + 1, current - start - 2); + add_token(tt::STRING, value); } void scanner::scan_token() { - const char token = advance(); - switch (token) { - case '(': - add_token(tt::LEFT_PAREN); - break; - case ')': - add_token(tt::RIGHT_PAREN); - break; - case '[': - add_token(tt::LEFT_BRACKET); - break; - case ']': - add_token(tt::RIGHT_BRACKET); - break; - case ',': - add_token(tt::COMMA); - break; - case '.': - add_token(tt::DOT); - break; - case '-': - add_token(tt::MINUS); - break; - case '+': - add_token(tt::PLUS); - break; - case ';': - add_token(tt::SEMICOLON); - break; - case '*': - add_token(tt::STAR); - break; - case '/': - add_token(SLASH); - break; - case '?': - add_token(tt::QMARK); - break; - case ':': - add_token(tt::COLON); - break; - case '!': - add_token(match(std::string(1, '=')) ? tt::BANG_EQUAL : tt::BANG); - break; - case '=': - add_token(match(std::string("=")) ? tt::EQUAL_EQUAL : tt::EQUAL); - break; - case '<': - add_token(match(std::string("=")) ? tt::LESS_EQUAL : tt::LESS); - break; - case '>': - add_token(match(std::string("=")) ? tt::GREATER_EQUAL : tt::GREATER); - break; - case ' ': - case '\r': - case '\n': - case '\t': - break; - case '"': - string(); - break; - - default: - if (is_digit(token)) - number(); - else if (token == '$') - read_json_keyword(); - else if (isalpha(token)) - read_json_level(); - else - throw ComponentException("Unexpected character encountered."); - break; - } + const char token = advance(); + switch (token) { + case '(': + add_token(tt::LEFT_PAREN); + break; + case ')': + add_token(tt::RIGHT_PAREN); + break; + case '[': + add_token(tt::LEFT_BRACKET); + break; + case ']': + add_token(tt::RIGHT_BRACKET); + break; + case ',': + add_token(tt::COMMA); + break; + case '.': + add_token(tt::DOT); + break; + case '-': + add_token(tt::MINUS); + break; + case '+': + add_token(tt::PLUS); + break; + case ';': + add_token(tt::SEMICOLON); + break; + case '*': + add_token(tt::STAR); + break; + case '/': + add_token(SLASH); + break; + case '?': + add_token(tt::QMARK); + break; + case ':': + add_token(tt::COLON); + break; + case '!': + add_token(match(std::string(1, '=')) ? tt::BANG_EQUAL : tt::BANG); + break; + case '=': + add_token(match(std::string("=")) ? tt::EQUAL_EQUAL : tt::EQUAL); + break; + case '<': + add_token(match(std::string("=")) ? tt::LESS_EQUAL : tt::LESS); + break; + case '>': + add_token(match(std::string("=")) ? tt::GREATER_EQUAL + : tt::GREATER); + break; + case ' ': + case '\r': + case '\n': + case '\t': + break; + case '"': + string(); + break; + + default: + if (is_digit(token)) { + number(); + } else if (token == '$') { + read_json_keyword(); + } else if (isalpha(token)) { + read_json_level(); + } else + throw ComponentException("Unexpected character encountered."); + break; + } } scanner::scanner(const std::string &source_) : source(source_) { - init_keywords(); + init_keywords(); } std::vector scanner::scan_tokens() { - while (has_next()) { - start = current; - scan_token(); - } - tokens.emplace_back(EOTF, "", ""); - return tokens; + while (has_next()) { + start = current; + scan_token(); + } + tokens.emplace_back(EOTF, "", ""); + return tokens; } -- GitLab