From 84428c144e54170ec629b379e1daf86857da2be8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Gassmann?= Date: Thu, 17 Mar 2022 16:14:17 +0100 Subject: [~] Refactoring of the FileAssembler, Extraction of methods in PParser --- src/PParser.cpp | 236 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 236 insertions(+) create mode 100644 src/PParser.cpp (limited to 'src/PParser.cpp') diff --git a/src/PParser.cpp b/src/PParser.cpp new file mode 100644 index 0000000..b4f478c --- /dev/null +++ b/src/PParser.cpp @@ -0,0 +1,236 @@ +#include "../inc/PParser.h" + +PParser::PParser( + map *variables, + map *templates, + map *pages, + map *posts + ): variables(variables), + templates(templates), + pages(pages), + posts(posts) +{ + ordered_posts_indexes = get_ordered_posts_indexes(); // Only used when a listing of posts in a page is necessary +} + +map* PParser::parse(){ + map* website = new map[2]; + + map::iterator it = pages->begin(); + while (it != pages->end()){ + if(it->first.substr(0, 5) != "link_"){ // Ignoring link pages + website[0][it->first] = parse_text(it->first, (*templates)["header.html"] + it->second + (*templates)["footer.html"], false); + } + it ++; + } + + it = posts->begin(); + while (it != posts->end()){ + website[1][it->first] = parse_text(it->first, (*templates)["header.html"] + it->second + (*templates)["footer.html"], true); + it ++; + } + return website; +} + +string* PParser::parse_function(string to_parse){ + static std::regex rgx("(\\w+)\\(([^\\)\\$]*)\\)"); + std::smatch match; + if (std::regex_search(to_parse, match, rgx)){ + string* r = new string[2]; + r[0] = match[1].str(); + r[1] = match[2].str(); + return r; + } + return NULL; +} + +string* PParser::parse_separator(string to_parse, string separator){ + static std::regex rgx("(\\w+)" + separator + "(\\w+)"); + std::smatch match; + if (std::regex_search(to_parse, match, rgx)){ + string* r = new string[2]; + r[0] = match[1].str(); + r[1] = match[2].str(); + return r; + } + return NULL; +} + +bool PParser::cmp_posts(pair& a, pair& b){ + string a_date = parse_function(a.second)[1]; + string b_date = parse_function(b.second)[1]; + if(a_date == ""){ + cerr << "Error: swg: Variable 'date' of post '" << a.first << "' is not defined." << endl; + exit(5); + }else if (b_date == ""){ + cerr << "Error: swg: Variable 'date' of post '" << b.first << "' is not defined." << endl; + exit(5); + } + static std::regex rgx("(\\d{1,2})\\.(\\d{1,2})\\.(\\d{4})"); + std::smatch a_match; + std::smatch b_match; + if (std::regex_search(a_date, a_match, rgx)){ // For now only european swiss format handled + if (std::regex_search(b_date, b_match, rgx)){ // For now only european swiss format handled + if(a_match[3] != b_match[3]) // Trying to differentiate by year + return stoi(a_match[3]) > stoi(b_match[3]); + if(a_match[2] != b_match[2]) // Trying to differentiate by month + return stoi(a_match[2]) > stoi(b_match[2]); + if(a_match[1] != b_match[1]) // Trying to differentiate by day + return stoi(a_match[1]) > stoi(b_match[1]); + return false; // or if equal return false + }else{ + cerr << "Error: swg: Variable 'date' of post '" << b.first << "' is not following the format dd.mm.yyyy." << endl; + exit(5); + } + }else{ + cerr << "Error: swg: Variable 'date' of post '" << a.first << "' is not following the format dd.mm.yyyy." << endl; + exit(5); + } +} + +vector PParser::get_ordered_posts_indexes(){ + vector> ordered_posts; + for (auto& it : *posts) { + ordered_posts.push_back(it); + } + sort(ordered_posts.begin(), ordered_posts.end(), cmp_posts); + + vector titles; + transform(ordered_posts.begin(), ordered_posts.end(), std::back_inserter(titles), + [](const std::pair& p) { return p.first; }); + return titles; +} + + + +string PParser::parse_text(string title, string to_parse, bool is_post){ + string parsed = to_parse; + string url = (*variables)["website"]; + + if(is_post) + (*variables)["link"] = url + "posts/" + lowercase(title) + ".html"; + else{ + if(title == (*variables)["index"]){ + (*variables)["link"] = url + "index.html"; + }else if(title.substr(0, 5) == "link_"){ // Link + (*variables)["link"] = (*pages)[title]; + }else{ + (*variables)["link"] = url + lowercase(title) + ".html"; + } + (*variables).erase("date"); // we are not doing it if it's a post, because it could be a listing + } + // Parsing variables and functions + size_t pos_first = 0; + size_t pos_second = 0; + static std::regex swg_expression("\\$([^\\$]*)\\$"); + std::smatch m_swg_expression; + while (regex_search(parsed, m_swg_expression, swg_expression)){ + string input = m_swg_expression[1]; //Group 1 ie. without the dollars + string output = ""; + + if(string *separator = parse_separator(input, "_")) // LISTINGS + { // Can have 0 or 1 argument + if(separator[0] == "list") + { + cout << "Type: " << separator[0] << ", Variation: " << separator[1] << endl; + + int arg = -1; + string *function = parse_function(input); + if (function != NULL) + arg = stoi(function[1]); + + string list_template = separator[1]+ "_listing.html"; + + if((*templates).find(list_template) == (*templates).end()) + { + cerr << "Error: swg: Listing template '" << list_template << "' does not exist." << endl; + exit(2); + } + + if(separator[1] == "menu") + { + string current_link = (*variables)["link"]; + map::iterator it = (*pages).begin(); + while (it != (*pages).end()) + { + output += parse_text(it->first,(*templates)[list_template], false); + it ++; + } + (*variables)["link"] = current_link; + } + else if(separator[1] == "post") + { + string current_date = ""; + string current_link = (*variables)["link"]; + if((*variables).find("date") != (*templates).end()) + current_date = (*variables)["date"]; + + int i = 0; + vector::iterator it = ordered_posts_indexes.begin(); + while (it != ordered_posts_indexes.end() && + (arg == -1 || i < arg)) // Limiting the number of posts shown if arg is set + { + string date = parse_function((*posts)[*it])[1]; + if(date != "") + (*variables)["date"] = date; + else + { + cerr << "Error: swg: Variable 'date' of post '" << *it << "' is not defined." << endl; + exit(5); + } + output += parse_text(*it,(*templates)[list_template], true); + it ++; + i ++; + } + if(current_date != "") + (*variables)["date"] = current_date; + else + (*variables).erase("date"); + (*variables)["link"] = current_link; + } + } + } + else if(string *function = parse_function(input)) // FUNCTIONS + { // *always* have *ONE* argument + cout << "Function: " << function[0] << ", Arg: " << function[1] << endl; + + if(function[0] == "date") // date + { + (*variables)["date"] = function[1]; + output = function[1]; + } + else if(function[0] == "res") // resources + { + string full_path = function[1]; + output = url + full_path; + } + } + else // KEYWORDS + { + cout << "Input: " << input << endl; + + if(input == "title") // Title + { + string* s = parse_separator(title, "_"); + if(s != NULL && s[0] == "link") // Link + output = s[1]; + else + output = title; + } + else if((*variables).find(input) != (*variables).end()) //Variables + output = (*variables)[input]; + + } + + if(output.length() == 0){ + cerr << "Error: swg: Invalid swg text section: \"" << input << "\"." << endl; + exit(4); + } + //cout << "BEFORE:" << endl << parsed << endl << endl; + parsed = regex_replace(parsed, swg_expression, output, regex_constants::format_first_only); + //cout << "AFTER:" << endl << parsed << endl ; + //cout << endl << "----------------------------------------------------" << endl << endl; + } + return parsed; +} + -- cgit v1.2.3