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);
}