context_free_grammar_generator::context_free_grammar_generator(const std::string& source) { const char* reading = source.c_str(); nonterminal* current = nullptr; std::vector<std::string>* filled = nullptr; std::string buf; while (*reading != 0) { if (*reading == '=') { // Leading and trailing whitespace is not significant, but internal whitespace is std::string key = boost::trim_copy(buf); if(key == "!" || key =="(" || key == ")") { throw name_generator_invalid_exception("[context_free_grammar_generator] Parsing error: nonterminals (, ! and ) may not be overridden"); } current = &nonterminals_[key]; current->possibilities_.push_back(std::vector<std::string>()); filled = ¤t->possibilities_.back(); buf.clear(); } else if (*reading == '\n') { // All whitespace is significant after the = if (filled) filled->push_back(buf); filled = nullptr; current = nullptr; buf.clear(); } else if (*reading == '|') { if (!filled || !current) { throw name_generator_invalid_exception("[context_free_grammar_generator] Parsing error: misplaced | symbol"); } filled->push_back(buf); current->possibilities_.push_back(std::vector<std::string>()); filled = ¤t->possibilities_.back(); buf.clear(); } else if (*reading == '\\' && reading[1] == 'n') { reading++; buf.push_back('\n'); } else if (*reading == '\\' && reading[1] == 't') { reading++; buf.push_back('\t'); } else { if (*reading == '{') { if (!filled) { throw name_generator_invalid_exception("[context_free_grammar_generator] Parsing error: misplaced { symbol"); } filled->push_back(buf); buf.clear(); } else if (*reading == '}') { if (!filled) { throw name_generator_invalid_exception("[context_free_grammar_generator] Parsing error: misplaced } symbol"); } filled->push_back('{' + boost::trim_copy(buf)); buf.clear(); } else buf.push_back(*reading); } reading++; } if (filled) filled->push_back(buf); }
context_free_grammar_generator::context_free_grammar_generator(const std::map<std::string, std::vector<std::string>>& source) { for(auto rule : source) { std::string key = rule.first; // Need to do this because utils::strip is mutating key = utils::strip(key); if(key == "!" || key =="(" || key == ")") { throw name_generator_invalid_exception("[context_free_grammar_generator] Parsing error: nonterminals (, ! and ) may not be overridden"); } std::string buf; for(std::string str : rule.second) { nonterminals_[key].possibilities_.emplace_back(); std::vector<std::string>* filled = &nonterminals_[key].possibilities_.back(); std::string buf; // A little code duplication here... for(char c : str) { if (c == '{') { if (!filled) { throw name_generator_invalid_exception("[context_free_grammar_generator] Parsing error: misplaced { symbol"); } filled->push_back(buf); buf.clear(); } else if (c == '}') { if (!filled) { throw name_generator_invalid_exception("[context_free_grammar_generator] Parsing error: misplaced } symbol"); } filled->push_back('{' + utils::strip(buf)); buf.clear(); } else buf.push_back(c); } if(!buf.empty()) { filled->push_back(buf); } } } }