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 = &current->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 = &current->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);
            }
        }
    }
}