From b8adc5bd55a9886f7474b9cab1dbb3c491c61ed6 Mon Sep 17 00:00:00 2001 From: Andreev Gregory Date: Wed, 14 Aug 2024 01:15:13 +0300 Subject: [PATCH] Mhm, I wrote something, for some reason nothing works --- assets/HypertextPages/test.nytl.html | 13 +- src/http_server/new_york_transit_line/core.h | 34 +---- .../new_york_transit_line/parser.cpp | 128 ++++++++++++++---- .../new_york_transit_line/templater.cpp | 2 +- 4 files changed, 108 insertions(+), 69 deletions(-) diff --git a/assets/HypertextPages/test.nytl.html b/assets/HypertextPages/test.nytl.html index 2c78ec3..ff78735 100644 --- a/assets/HypertextPages/test.nytl.html +++ b/assets/HypertextPages/test.nytl.html @@ -1,10 +1,3 @@ - - - - - {% WRITE arg1 %} - - -

{% WRITE arg1 %}

- - \ No newline at end of file +{% ELDEF main %} +AAAAAAAA +{% ENDELDEF %} \ No newline at end of file diff --git a/src/http_server/new_york_transit_line/core.h b/src/http_server/new_york_transit_line/core.h index b567ac5..49b4273 100644 --- a/src/http_server/new_york_transit_line/core.h +++ b/src/http_server/new_york_transit_line/core.h @@ -6,39 +6,11 @@ namespace nytl { /* ============== For parsing =============================*/ - struct ParsingContext { - std::string text; - size_t pos = 0; - size_t column = 0; - size_t line = 0; - }; - - constexpr int EOFVAL = -999; - - int peep(ParsingContext& ctx); - - char skip(ParsingContext& ctx); - void skip(ParsingContext& ctx, char ch); - - void skipWhitespace(ParsingContext& ctx); - - void skipString(ParsingContext& ctx, const std::string& str); - - /* Returns empty if what is ahead of us is not name */ - std::string readName(ParsingContext& ctx); - - /* Returns empty if what is ahead of us is not uint */ - std::string readUint(ParsingContext& ctx); - - std::vector splitIntoLines(const std::string& str); - std::string concatenateLines(const std::vector& lines); - void one_part_update_min_start_wsp_non_empty(const std::string& str, bool is_first, size_t& min); - std::string one_part_cut_excess_tab(const std::string& str, bool is_first, size_t cut); - void parse_bare_file(const std::string& filename, const std::string& content, - global_elem_set_t& result); + global_elem_set_t& result); + void parse_special_file(const std::string& filename, const std::string& content, - global_elem_set_t& result); + global_elem_set_t& result, TemplaterSettings& syntax); /* =================== For rendering ====================*/ struct LocalVarValue { diff --git a/src/http_server/new_york_transit_line/parser.cpp b/src/http_server/new_york_transit_line/parser.cpp index db43dd7..dbc69da 100644 --- a/src/http_server/new_york_transit_line/parser.cpp +++ b/src/http_server/new_york_transit_line/parser.cpp @@ -34,6 +34,15 @@ namespace nytl { return ""; } + struct ParsingContext { + std::string text; + size_t pos = 0; + size_t column = 0; + size_t line = 0; + }; + + constexpr int EOFVAL = -999; + int peep(ParsingContext &ctx) { if (ctx.text.size() <= ctx.pos) return EOFVAL; @@ -159,7 +168,7 @@ namespace nytl { uptr toMe(bool returned, ParsingContext& ctx) { if (!returned) { std::string nm = readName(ctx); - ASSERT(!nm.empty, "Type specification expected"); + ASSERT(!nm.empty(), "Type specification expected"); nm = make_uppercase(nm); if (nm == "JSON") { result = json::JSON(true); @@ -183,7 +192,7 @@ namespace nytl { std::vector> stack; stack.push_back(mv(std::make_unique(result))); bool returned = false; - while (!stack.empty) { + while (!stack.empty()) { uptr ret = stack.back()->toMe(returned, ctx); returned = !(bool)ret; if (ret) @@ -252,7 +261,7 @@ namespace nytl { std::vector> stack; stack.push_back(mv(std::make_unique(result))); bool returned = false; - while (!stack.empty) { + while (!stack.empty()) { uptr ret = stack.back()->toMe(returned, ctx, local_var_names); returned = !(bool)ret; if (ret) @@ -283,7 +292,7 @@ namespace nytl { } bool isIt_magic_block_end(ParsingContext& ctx, const TemplaterSettings& syntax) { - return peep(ctx) == syntax.magic_block_start[0]; + return peep(ctx) == syntax.magic_block_end[0]; } struct ECPFrame { @@ -320,27 +329,10 @@ namespace nytl { result.parts.back().when_for_put.line_feed = true; else assert(false); - } - // skip_magic_block_start(ctx, syntax); - // std::string ender = make_uppercase(readName(ctx)); - // if (gone_for == gone_for_for) { - // ASSERT(ender == "ENDFOR", "Expected ENDFOR"); - // skipWhitespace(ctx); - // std::string lf_arg = make_uppercase(readName(ctx)); - // if (lf_arg == "LF") { - // result.back().when_for_put.line_feed = true; - // } else if (lf_arg == "NOLF") { - // result.back().when_for_put.line_feed = false; - // } else - // ASSERT(lf_arg == "", "Expected nothing, LF or NOLF"); - // skip_magic_block_end(ctx, syntax); - // } else if (gone_for == gone_for_ref) { - // skip_magic_block_start(ctx, syntax); - // ASSERT(ender == "ENDREF", "Expected ENDREF"); - // } else - // assert(false); - // skip_magic_block_end(ctx, syntax); + } else + assert(ret_data_int == 0); } + ret_data_int = 0; ya_e_ya_h_i_ya_g_d_o: result.parts.emplace_back(); result.parts.back().when_code.lines = read_code_up_to_mag_block_start(ctx, syntax); @@ -440,8 +432,61 @@ namespace nytl { P.called_element["V"] = json::JSON(base_el); P.called_element["C"] = json::JSON(json::array); skipWhitespace(ctx); + P.passed_arguments = {parse_expression(ctx, local_var_names)}; }; - // todo REF, PUT, WRITE, ROUGHINSERT todo enders todo else (error) + if (op == "WRITE") { + mediocre_operator("str2text"); + goto ya_e_ya_h_i_ya_g_d_o;; + } + if (op == "ROUGHINSERT") { + mediocre_operator("str2code"); + goto ya_e_ya_h_i_ya_g_d_o;; + } + if (op == "ENDELDEF") { + ASSERT(myself == gone_for_nothing, "Unexpected end of element"); + skip_magic_block_end(ctx, syntax); + if (!result.parts.empty()) { + if (result.parts[0].type == element_part_type_t::code) + result.parts[0].when_code.lines = clement_lstrip(result.parts[0].when_code.lines); + if (result.parts.back().type == element_part_type_t::code) + rstrip(result.parts.back().when_code.lines); + size_t cut = 999999999999; + size_t N = result.parts.size(); + for (size_t i = 0; i < N; i++) { + if (result.parts[i].type == element_part_type_t::code) { + one_part_update_min_start_wsp_non_empty(result.parts[i].when_code.lines, i == 0, cut); + } + } + for (size_t i = 0; i < N; i++) { + if (result.parts[i].type == element_part_type_t::code) { + result.parts[i].when_code.lines = one_part_cut_excess_tab(result.parts[i].when_code.lines, i == 0, cut); + } + } + } + return NULL; + } + if (op == "ENDFOR") { + ASSERT(myself == gone_for_for, "Unexpected end of for cycle"); + skipWhitespace(ctx); + /* Here I am using ret_data_int to return info about NOLF(1)/LF(2) decision */ + ret_data_int = 2; // Default is to do LF + if (!isIt_magic_block_end(ctx, syntax)) { + op = make_uppercase(readName(ctx)); + if (op == "LF") { + ret_data_int = 2; + } else if (op == "NOLF") { + ret_data_int = 1; + } else + THROW("Expected LF, NOLF or end of magic block"); + } + skip_magic_block_end(ctx, syntax); + return NULL; + } + if (op == "ENDREF") { + skip_magic_block_end(ctx, syntax); + return NULL; + } + THROW("Unknown operator. Expected FOR, REF, PUT, WRITE, ROUGHINSERT, ENDELDEF, ENDFOR, ENDREF"); } }; @@ -462,8 +507,37 @@ namespace nytl { } void parse_special_file(const std::string& filename, const std::string& content, - std::map& result) + global_elem_set_t& result, TemplaterSettings& syntax) { - // THROW("Don't know how to parse it yet"); + ParsingContext ctx{content}; + while(true) { + skipWhitespace(ctx); + if (peep(ctx) == EOFVAL) + break; + skip_magic_block_start(ctx, syntax); + ASSERT(make_uppercase(readName(ctx)) == "ELDEF", "Expected ELDEF"); + skipWhitespace(ctx); + std::string elname_postfix = readName(ctx); + ASSERT(elname_postfix != "_", "please don't"); + std::string fullname = elname_postfix == "main" ? filename : filename + "." + elname_postfix; + ASSERT(result.count(fullname) == 0, "Element " + fullname + " has been already defined"); + Element& newborn = result[fullname]; + arg_name_list_t arglist; + while (true) { + skipWhitespace(ctx); + if (isIt_magic_block_end(ctx, syntax)) + break; + newborn.arguments.push_back(parse_type(ctx)); + skipWhitespace(ctx); + std::string argname = readName(ctx); + ASSERT(!argname.empty(), "Expected argument name"); + if (argname != "_") { + size_t k = arglist.size(); + arglist[argname] = k; + } + } + skip_magic_block_end(ctx, syntax); + parse_element_content(fullname, ctx, syntax, arglist, newborn, result); + } } } diff --git a/src/http_server/new_york_transit_line/templater.cpp b/src/http_server/new_york_transit_line/templater.cpp index e129063..f66a0bd 100644 --- a/src/http_server/new_york_transit_line/templater.cpp +++ b/src/http_server/new_york_transit_line/templater.cpp @@ -119,7 +119,7 @@ namespace nytl { for (const InterestingFile& file: intersting_files) { std::string content = readFile(file.path); if (file.special_syntax_applied) { - parse_special_file(file.dot_name, content, elements); + parse_special_file(file.dot_name, content, elements, settings); } else { parse_bare_file(file.dot_name, content, elements); }