struct Tag {
std::unordered_map<std::string, boost::variant<int, double, std::string, std::complex> contents;
};
boost::variant<int, double, std::string, std::complex> parse_tag_end(T& begin, end) {
boost::variant<int, double, std::string, std::complex> out;
if (*begin == TokenType::Integer) {
int i;
std::stringstream sstr(begin->contents);
begin++;
sstr >> i;
return out = i;
}
if (*begin == TokenType::Double) {
double i;
std::stringstream sstr(begin->contents);
begin++;
sstr >> i;
return out = i;
}
// and complex and filename
}
std::unordered_map<std::string, Tag> parse(std::vector<Token> tokens) {
std::unordered_map<std::string, Tag> result;
auto curr = tokens.begin();
auto end = tokens.end();
while(curr != end) {
if (*curr != TokenType::LessThan)
throw std::runtime_error("File must open with '<'");
curr++;
if (*curr != TokenType::Identifier)
throw std::runtime_error("Expected identifier after '<'");
auto curr_tag = curr->contents;
Tag& t = result[curr_tag];
cur++;
if (*curr != TokenType::GreaterThan)
throw std::runtime_error("Expected '>' after identifier");
curr++;
// now match tag_contents
while(curr != TokenType::LessThan) { // '<' introduces the close
if (*curr != TokenType::Identifier)
throw std::runtime_error("Expected identifier before '<'");
auto& out = t.contents[curr->contents];
curr++;
if (*curr != TokenType::Equals)
throw std::runtime_error("Expected '=' after identifier");
curr++;
out = parse_tag_end(curr, end);
}
// now match the end
curr++; // already know this is '<'
if (*curr != TokenType::Identifier)
throw std::runtime_error("Expected identifier after '<'");
if (curr->contents != curr_tag)
throw std::runtime_error("Expected closing tag to be equivalent to opening.");
curr++;
if (*curr != TokenType::GreaterThan)
throw std::runtime_error("Expected '>' after identifier");
}
return result;
}