Advertisement
Vultraz

Untitled

Apr 1st, 2018
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.32 KB | None | 0 0
  1. std::string convert_to_wml(const std::string& element_name, const std::string& contents)
  2. {
  3.     std::stringstream ss;
  4.  
  5.     bool in_quotes = false;
  6.     bool last_char_escape = false;
  7.  
  8.     const char escape_char = '\\';
  9.  
  10.     std::vector<std::string> attributes;
  11.  
  12.     // Find the different attributes.
  13.     // No checks are made for the equal sign or something like that.
  14.     // Attributes are just separated by spaces or newlines.
  15.     // Attributes that contain spaces must be in single quotes.
  16.     for(std::size_t pos = 0; pos < contents.size(); ++pos) {
  17.         const char c = contents[pos];
  18.  
  19.         if(c == escape_char && !last_char_escape) {
  20.             last_char_escape = true;
  21.         } else {
  22.             if(c == '\'' && !last_char_escape) {
  23.                 ss << '"';
  24.                 in_quotes = !in_quotes;
  25.             } else if((c == ' ' || c == '\n') && !last_char_escape && !in_quotes) {
  26.                 // Space or newline, end of attribute.
  27.                 attributes.push_back(ss.str());
  28.                 ss.str("");
  29.             } else {
  30.                 ss << c;
  31.             }
  32.  
  33.             last_char_escape = false;
  34.         }
  35.     }
  36.  
  37.     if(in_quotes) {
  38.         throw parse_error(formatter() << "Unterminated single quote after: '" << ss.str() << "'");
  39.     }
  40.  
  41.     if(!ss.str().empty()) {
  42.         attributes.push_back(ss.str());
  43.     }
  44.  
  45.     ss.str("");
  46.  
  47.     // Create the WML.
  48.     ss << "[" << element_name << "]\n";
  49.  
  50.     for(const std::string& attr : attributes) {
  51.         ss << attr << "\n";
  52.     }
  53.  
  54.     ss << "[/" << element_name << "]\n";
  55.  
  56.     return ss.str();
  57. }
  58.  
  59. config parse_text(const std::string& text)
  60. {
  61.     config res;
  62.  
  63.     bool last_char_escape = false;
  64.     const char escape_char = '\\';
  65.  
  66.     std::stringstream ss;
  67.     std::size_t pos;
  68.  
  69.     enum { ELEMENT_NAME, OTHER } state = OTHER;
  70.  
  71.     for(pos = 0; pos < text.size(); ++pos) {
  72.         const char c = text[pos];
  73.  
  74.         if(c == escape_char && !last_char_escape) {
  75.             last_char_escape = true;
  76.         } else {
  77.             if(state == OTHER) {
  78.                 if(c == '<') {
  79.                     if(last_char_escape) {
  80.                         ss << c;
  81.                     } else {
  82.                         res.add_child("text", config{"text", ss.str()});
  83.                         ss.str("");
  84.                         state = ELEMENT_NAME;
  85.                     }
  86.                 } else {
  87.                     ss << c;
  88.                 }
  89.             } else if(state == ELEMENT_NAME) {
  90.                 if(c == '/') {
  91.                     throw parse_error("Erroneous / in element name.");
  92.                 } else if(c == '>') {
  93.                     const std::string element_name = ss.str();
  94.                     ss.str("");
  95.  
  96.                     // End of this name.
  97.                     std::stringstream s;
  98.                     s << "</" << element_name << ">";
  99.  
  100.                     const std::string end_element_name = s.str();
  101.                     std::size_t end_pos = text.find(end_element_name, pos);
  102.  
  103.                     if(end_pos == std::string::npos) {
  104.                         throw parse_error(formatter() << "Unterminated element: " << element_name);
  105.                     }
  106.  
  107.                     const std::string contents = text.substr(pos + 1, end_pos - pos - 1);
  108.  
  109.                     s.str(convert_to_wml(element_name, contents));
  110.                     s.seekg(0);
  111.  
  112.                     try {
  113.                         config cfg;
  114.                         read(cfg, s);
  115.  
  116.                         res.append_children(cfg);
  117.                     } catch(config::error& e) {
  118.                         throw parse_error(formatter() << "Error when parsing help markup as WML: " << e.message);
  119.                     }
  120.  
  121.                     pos = end_pos + end_element_name.size() - 1;
  122.                     state = OTHER;
  123.                 } else {
  124.                     ss << c;
  125.                 }
  126.             }
  127.  
  128.             last_char_escape = false;
  129.         }
  130.     }
  131.  
  132.     if(state == ELEMENT_NAME) {
  133.         throw parse_error(formatter() << "Element '" << ss.str() << "' continues through end of string.");
  134.     }
  135.  
  136.     // Add the last string.
  137.     if(!ss.str().empty()) {
  138.         res.add_child("text", config{"text", ss.str()});
  139.     }
  140.  
  141.     return res;
  142. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement