bool Preprocessor::HandleToken(size_t line_no, const std::string & line){ Tokenizer tok; tok.set_input(line); if (tok.next_token() != "#"){ return false; } if (!tok.next_token()){ return false; } if (tok == "section"){ return HandleSection(line_no, tok); } if (limitSection == "" || currentSection == limitSection){ if (tok == "version"){ return HandleVersion(line_no, tok); } if (tok == "pragma"){ return HandlePragma(line_no, tok); } if (tok == "include"){ return HandleInclude(line_no, tok); } } return false; }
bool Preprocessor::HandleSection(size_t line_no, Tokenizer & tok){ if (tok.next_token().get_type() != Tokenizer::Type::String){ throw Exception::Error("Section name must be a quoted string; got `" + tok.get_string() + "`."); } size_t file_number = push_file(filenames, filedata.name()); std::string version; std::string prefix; if (Defined(currentSection, "__INTERNAL VERSION", version) && defines.size() == 1){ prefix += "#version " + version + "\n"; } if (currentSection == ""){ prefix += "#line 1 " + std::to_string(file_number) + "\n"; } sections[currentSection].data = prefix + currentData; currentData = ""; currentData += "#line " + std::to_string(line_no) + " " + std::to_string(file_number) + "\n"; std::string section = tok; section.pop_back(); section.erase(section.begin(), section.begin() + 1); currentSection = section; if (currentSection == "__END"){ return true; } return true; }
bool Preprocessor::HandleVersion(size_t line_no, Tokenizer & tok){ if (!tok.next_token()){ throw Exception::Error("Bad version"); } Define("__INTERNAL VERSION", tok.get_remaining()); currentData += '\n'; return true; }
bool Preprocessor::HandlePragma(size_t line_no, Tokenizer & tok){ if (!tok.next_token()){ throw Exception::Error("Bad Pragma"); } if (tok == "once"){ std::string name = "___ONCE_INCLUDE " + currentSection + "?" + filedata.name(); if (currentSection == limitSection){ Define(name, ""); currentData += '\n'; } return true; } return false; }
bool Preprocessor::HandleInclude(size_t line_no, Tokenizer & tok){ bool issection = false; if (tok.next_token() == "section"){ issection = true; tok.next_token(); } if (tok.get_type() != Tokenizer::Type::String){ throw Exception::Error("Include name must be quoted string; got `" + tok.get_string() + "`."); } MappedFile mfile; std::string section = ""; if (issection){ section = tok.get_string(); trim_ends(section); mfile = filedata; } else{ std::string file = tok; trim_ends(file); size_t pos = file.find_first_of("?"); if (pos != std::string::npos){ section = file.substr(pos + 1); file.erase(file.begin() + pos, file.end()); } else{ if (tok.next_token()){ if (tok == "section"){ if (tok.next_token().get_type() == Tokenizer::Type::String){ section = tok.get_string(); trim_ends(section); } else{ throw Exception::Error("String expected after `section`; got `" + tok.get_string() + "`."); } } else{ throw Exception::Error("Unknown include specifier `" + tok.get_string() + "`. Did you mean to use `section`?"); } } } mfile = MappedFile(file, include_paths); } size_t file_number;// = push_file(filenames, mfile.name()); std::string test_name = "___ONCE_INCLUDE " + section + "?" + mfile.name(); if (Defined(section, test_name)){ currentData.push_back('\n'); return true; } //currentData += "#line 1 " + std::to_string(file_number) + "\n"; defines.push_back(§ions[currentSection].defines); Preprocessor p = Preprocessor(mfile, include_paths, defines, filenames, section); auto newSections = p.Preprocess(); auto& back = *defines.back(); defines.pop_back(); for (auto & def : back){ Define(def.first, def.second); } file_number = push_file(filenames, filedata.name()); currentData += newSections.at(section).data; currentData.push_back('\n'); currentData += "#line " + std::to_string(line_no) + " " + std::to_string(file_number) + "\n"; return true; }