diff --git a/building/main.cpp b/building/main.cpp index 10466ff..5eb43fa 100644 --- a/building/main.cpp +++ b/building/main.cpp @@ -116,7 +116,6 @@ struct CAWebChat { }; T.units = { "alotalot.cpp", - "execute_expression.cpp", "html_case.cpp", "parser.cpp", "rendering.cpp", diff --git a/src/http_server/new_york_transit_line/core.h b/src/http_server/new_york_transit_line/core.h index c598fe4..b1a250c 100644 --- a/src/http_server/new_york_transit_line/core.h +++ b/src/http_server/new_york_transit_line/core.h @@ -17,17 +17,6 @@ namespace nytl { global_elem_set_t& result, TemplaterSettings& syntax); /* =================== For rendering ====================*/ - struct LocalVarValue { - bool is_json = false; - std::string EL_name; - const json::JSON* JSON_subval = NULL; - }; - - /* No new JSON object will ever be created, I have one root json argument, - * all the other json variables are subtrees of it */ - LocalVarValue rendering_core_execute_expression(const global_elem_set_t& global_elems, - const std::vector& local_vars, const json::JSON& expr); - std::string rendering_core(const std::string& entry_func, const std::vector& entry_arguments, const global_elem_set_t& elem_ns, const std::function& escape); } diff --git a/src/http_server/new_york_transit_line/execute_expression.cpp b/src/http_server/new_york_transit_line/execute_expression.cpp deleted file mode 100644 index 03b8f16..0000000 --- a/src/http_server/new_york_transit_line/execute_expression.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include "core.h" -#include "alotalot.h" -#include - -namespace nytl { - /* Expression Execution Frame */ - struct EEFrame { - const json::JSON& expr; - LocalVarValue& result; - LocalVarValue temp_ret; - size_t chain_el = 0; - - EEFrame(const json::JSON &expr, LocalVarValue &result) - : expr(expr), - result(result) { - } - - // todo: remove this debug function - // void print_result() { - // if (result.is_json) { - // printf("print_result %%p: %p\n", result.JSON_subval); - // printf("%s\n", json::generate_str(*result.JSON_subval, json::print_compact).c_str()); - // } else - // printf("element %s\n", result.EL_name.c_str()); - // } - - void descend(const json::JSON& what) { - if (result.is_json) { - const json::JSON& P = *result.JSON_subval; - if (P.isArray() && what.isInteger()) { - const std::vector arr_p = P.asArray(); - int64_t ind_w = what.asInteger().get_int(); - ASSERT(ind_w > 0 && ind_w < arr_p.size(), "Expression \"array[integer]\" caused out-of-bound situation"); - result = LocalVarValue{true, "", &arr_p[ind_w]}; - } else if (P.isDictionary() && what.isString()) { - const std::map& dict_p = P.asDictionary(); - const std::string& key_w = what.asString(); - ASSERT(dict_p.count(key_w) == 1, "No such key exception"); - result = LocalVarValue{true, "", &dict_p.at(key_w)}; - } else - THROW("Incorrect type of \"json[json]\" expression. Unallowed signature of [] operator"); - } else { - ASSERT(what.isString(), "Expression \"element[X]\" allowed only if X is string (json object)"); - if (what.asString().empty()) - return; - if (!is_uname_dotted_sequence(what.asString())) - THROW("Incorrect X in \"element[X]\""); - result.EL_name += ("." + what.asString()); - } - } - - uptr toMe(bool returned, const global_elem_set_t& global_elems, - const std::vector& local_vars) { - if (returned) { - ASSERT(temp_ret.is_json, "Expression \"X[ element ]\" is not allowed"); - assert(temp_ret.JSON_subval); - descend(*(temp_ret.JSON_subval)); - } else { - assert(expr.isDictionary()); - const json::JSON& val = expr["V"].g(); - if (val.isInteger()) { - size_t lv_ind = val.asInteger().get_int(); - assert(lv_ind < local_vars.size()); - result = local_vars[lv_ind]; - } else if (val.isString()) { - std::string cur_el_name_str = expr["V"].g().asString(); - result = LocalVarValue{false, cur_el_name_str, NULL}; - } else - assert(false); - } - const std::vector& chain = expr["C"].g().asArray(); - while (true) { - if (chain_el >= chain.size()) - return NULL; - const json::JSON& t = chain[chain_el++]; - if (t.isDictionary()) - return std::make_unique(t, temp_ret); - descend(t); - } - } - }; - - LocalVarValue rendering_core_execute_expression(const global_elem_set_t& global_elems, - const std::vector& local_vars, const json::JSON& expr) { - bool returned = false; - std::vector> stack; - LocalVarValue result; - stack.push_back(std::make_unique(expr, result)); - while (!stack.empty()) { - EEFrame& cur = *stack.back(); - uptr todo = cur.toMe(returned, global_elems, local_vars); - returned = !(bool)todo; - if (todo) - stack.push_back(mv(todo)); - else - stack.pop_back(); - } - return result; - } -} diff --git a/src/http_server/new_york_transit_line/rendering.cpp b/src/http_server/new_york_transit_line/rendering.cpp index b6cc23e..3bcb089 100644 --- a/src/http_server/new_york_transit_line/rendering.cpp +++ b/src/http_server/new_york_transit_line/rendering.cpp @@ -5,6 +5,101 @@ #include namespace nytl { + struct LocalVarValue { + bool is_json = false; + std::string EL_name; + const json::JSON* JSON_subval = NULL; + }; + + /* Expression Execution Frame */ + struct EEFrame { + const json::JSON& expr; + LocalVarValue& result; + LocalVarValue temp_ret; + size_t chain_el = 0; + + EEFrame(const json::JSON &expr, LocalVarValue &result) + : expr(expr), + result(result) { + } + + void descend(const json::JSON& what) { + if (result.is_json) { + const json::JSON& P = *result.JSON_subval; + if (P.isArray() && what.isInteger()) { + const std::vector arr_p = P.asArray(); + int64_t ind_w = what.asInteger().get_int(); + ASSERT(ind_w > 0 && ind_w < arr_p.size(), "Expression \"array[integer]\" caused out-of-bound situation"); + result = LocalVarValue{true, "", &arr_p[ind_w]}; + } else if (P.isDictionary() && what.isString()) { + const std::map& dict_p = P.asDictionary(); + const std::string& key_w = what.asString(); + ASSERT(dict_p.count(key_w) == 1, "No such key exception"); + result = LocalVarValue{true, "", &dict_p.at(key_w)}; + } else + THROW("Incorrect type of \"json[json]\" expression. Unallowed signature of [] operator"); + } else { + ASSERT(what.isString(), "Expression \"element[X]\" allowed only if X is string (json object)"); + if (what.asString().empty()) + return; + if (!is_uname_dotted_sequence(what.asString())) + THROW("Incorrect X in \"element[X]\""); + result.EL_name += ("." + what.asString()); + } + } + + uptr toMe(bool returned, const global_elem_set_t& global_elems, + const std::vector& local_vars) { + if (returned) { + ASSERT(temp_ret.is_json, "Expression \"X[ element ]\" is not allowed"); + assert(temp_ret.JSON_subval); + descend(*(temp_ret.JSON_subval)); + } else { + assert(expr.isDictionary()); + const json::JSON& val = expr["V"].g(); + if (val.isInteger()) { + size_t lv_ind = val.asInteger().get_int(); + assert(lv_ind < local_vars.size()); + result = local_vars[lv_ind]; + } else if (val.isString()) { + std::string cur_el_name_str = expr["V"].g().asString(); + result = LocalVarValue{false, cur_el_name_str, NULL}; + } else + assert(false); + } + const std::vector& chain = expr["C"].g().asArray(); + while (true) { + if (chain_el >= chain.size()) + return NULL; + const json::JSON& t = chain[chain_el++]; + if (t.isDictionary()) + return std::make_unique(t, temp_ret); + descend(t); + } + } + }; + + /* No new JSON object will ever be created, I have N root json arguments, + * all the other json variables are subtrees of them. With one exception: Key iterators for arrays + * and dictionaries. They are stored in json in rendering stack */ + LocalVarValue rendering_core_execute_expression(const global_elem_set_t& global_elems, + const std::vector& local_vars, const json::JSON& expr) { + bool returned = false; + std::vector> stack; + LocalVarValue result; + stack.push_back(std::make_unique(expr, result)); + while (!stack.empty()) { + EEFrame& cur = *stack.back(); + uptr todo = cur.toMe(returned, global_elems, local_vars); + returned = !(bool)todo; + if (todo) + stack.push_back(mv(todo)); + else + stack.pop_back(); + } + return result; + } + struct Ditch { std::string result; size_t cur_line_width = 0; @@ -33,6 +128,7 @@ namespace nytl { }; #define RFrame_passed const global_elem_set_t& elem_ns, Ditch& result, const std::function& escape + /* Rendering Frame */ struct RFrame { size_t wsp_before_newlines = 0; bool newlined_somewhere = false;