KartonArmadon

Untitled

Aug 19th, 2023 (edited)
110
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.44 KB | Source Code | 0 0
  1. #include <cassert>
  2. #include <filesystem>
  3. #include <fstream>
  4. #include <iostream>
  5. #include <regex>
  6. #include <sstream>
  7. #include <string>
  8. #include <string_view>
  9. #include <vector>
  10.  
  11.  
  12. using namespace std;
  13. using filesystem::path;
  14. namespace fs = std::filesystem;
  15.  
  16. const static regex header_reg(R"/(\s*#\s*include\s*"([^"]*)"\s*)/");
  17. const static regex library_reg(R"/(\s*#\s*include\s*<([^>]*)>\s*)/");
  18. const static regex test_reg(R"/(include)/");
  19.  
  20. path operator""_p(const char*, std::size_t);
  21.  
  22. // напишите эту функцию
  23. bool Preprocess(const path&, const path&, const vector<path>&);
  24.  
  25. bool RecursivePreprocess(ifstream&, ofstream&, const path&, const vector<path>&);
  26.  
  27. bool findInclude(const string&, const vector<path>&, path& result);
  28.  
  29. string GetFileContents(string);
  30.  
  31. string ReadLine(istream&);
  32.  
  33. void Test() {
  34.     error_code err;
  35.     filesystem::remove_all("sources"_p, err);
  36.     filesystem::create_directories("sources"_p / "include2"_p / "lib"_p, err);
  37.     filesystem::create_directories("sources"_p / "include1"_p, err);
  38.     filesystem::create_directories("sources"_p / "dir1"_p / "subdir"_p, err);
  39.  
  40.     {
  41.         ofstream file("sources/a.cpp");
  42.         file << "// this comment before include\n"
  43.             "#include \"dir1/b.h\"\n"
  44.             "// text between b.h and c.h\n"
  45.             "#include \"dir1/d.h\"\n"
  46.             "\n"
  47.             "int SayHello() {\n"
  48.             "    cout << \"hello, world!\" << endl;\n"
  49.             "#   include<dummy.txt>\n"
  50.             "}\n"sv;
  51.     }
  52.     {
  53.         ofstream file("sources/dir1/b.h");
  54.         file << "// text from b.h before include\n"
  55.             "#include \"subdir/c.h\"\n"
  56.             "// text from b.h after include"sv;
  57.     }
  58.     {
  59.         ofstream file("sources/dir1/subdir/c.h");
  60.         file << "// text from c.h before include\n"
  61.             "#include <std1.h>\n"
  62.             "// text from c.h after include\n"sv;
  63.     }
  64.     {
  65.         ofstream file("sources/dir1/d.h");
  66.         file << "// text from d.h before include\n"
  67.             "#include \"lib/std2.h\"\n"
  68.             "// text from d.h after include\n"sv;
  69.     }
  70.     {
  71.         ofstream file("sources/include1/std1.h");
  72.         file << "// std1\n"sv;
  73.     }
  74.     {
  75.         ofstream file("sources/include2/lib/std2.h");
  76.         file << "// std2\n"sv;
  77.     }
  78.  
  79.     assert((!Preprocess("sources"_p / "a.cpp"_p, "sources"_p / "a.in"_p,
  80.         { "sources"_p / "include1"_p,"sources"_p / "include2"_p })));
  81.  
  82.     return;
  83.     ostringstream test_out;
  84.     test_out << "// this comment before include\n"
  85.         "// text from b.h before include\n"
  86.         "// text from c.h before include\n"
  87.         "// std1\n"
  88.         "// text from c.h after include\n"
  89.         "// text from b.h after include\n"
  90.         "// text between b.h and c.h\n"
  91.         "// text from d.h before include\n"
  92.         "// std2\n"
  93.         "// text from d.h after include\n"
  94.         "\n"
  95.         "int SayHello() {\n"
  96.         "    cout << \"hello, world!\" << endl;\n"sv;
  97.  
  98.     assert(GetFileContents("sources/a.in"s) == test_out.str());
  99. }
  100.  
  101. int main() {
  102.     Test();
  103. }
  104.  
  105. path operator""_p(const char* data, std::size_t sz) {
  106.     return path(data, data + sz);
  107. }
  108.  
  109. // напишите эту функцию
  110. bool Preprocess(const path& in_file, const path& out_file, const vector<path>& include_directories) {
  111.  
  112.     ifstream in_stream(in_file);
  113.     //Если файл не открылся
  114.     if (!in_stream)
  115.         return false;
  116.     //Если файл открылся
  117.     ofstream out_stream(out_file);
  118.     if (RecursivePreprocess(in_stream, out_stream, in_file, include_directories) == true) {
  119.         return true;
  120.     }
  121.     else {
  122.         return false;
  123.     }
  124. }
  125.  
  126. bool RecursivePreprocess(
  127.     ifstream& in,
  128.     ofstream& out,
  129.     const path& p,
  130.     const vector<path>& include_directories) {
  131.     if (!in.is_open()) {
  132.         return false;
  133.     }
  134.     string temp;
  135.     smatch m;
  136.     int i = 0;
  137.     while (!in.eof()) {
  138.         i++;
  139.         temp = ReadLine(in);
  140.         //if (temp.empty())
  141.         //  continue;
  142.         //cout << i++ << " line: "s << temp << endl;
  143.         if (bool regex_match_result = regex_match(temp, m, header_reg);
  144.             regex_match_result == true) {
  145.             //cout << "header_reg result: " << regex_match_result << endl;
  146.             //cout << "include: " << m[0] << endl;
  147.             //cout << "header_path: " << string(m[1]) << endl;
  148.             path include_path = p.parent_path() / string(m[1]);
  149.             if (!fs::exists(include_path)) {
  150.                 bool find_result = findInclude(string(m[1]), include_directories, include_path);
  151.                 if (find_result) {
  152.                     //cout << "full header_path: " << include_path << endl;
  153.                     //cout << "header file content: " << endl << GetFileContents(include_path.string()) << endl;
  154.                     //system("pause");
  155.                     //cout << endl;
  156.                     ifstream lib_file(include_path);
  157.                     RecursivePreprocess(lib_file, out, include_path, include_directories);
  158.                 }
  159.                 else {
  160.                     cout << "unknown include file "s << string(m[1]) << " at file "s << p.string() << " at line "s << i << endl;
  161.                     return false;
  162.                 }
  163.             }
  164.             else {
  165.                 //cout << "full header_path: " << include_path << endl;
  166.                 //cout << "header file content: " << endl << GetFileContents(include_path.string()) << endl;
  167.                 //system("pause");
  168.                 //cout << endl;
  169.                 ifstream h_file(include_path);
  170.                 RecursivePreprocess(h_file, out, include_path, include_directories);
  171.             }
  172.         }
  173.         else if (bool regex_match_result = regex_match(temp, m, library_reg);
  174.             regex_match_result == true) {
  175.             //cout << "library_reg result: " << regex_match_result << endl;
  176.             //cout << "include: " << m[0] << endl;
  177.             //cout << "library_name: " << string(m[1]) << endl;
  178.             path include_path;
  179.             bool find_result = findInclude(string(m[1]), include_directories, include_path);
  180.             //cout << "find_result: " << find_result << endl;
  181.             if (find_result) {
  182.                 //cout << "full library_path: " << include_path << endl;
  183.                 //cout << "library file content: " << endl << GetFileContents(include_path.string()) << endl;
  184.                 //system("pause");
  185.                 //cout << endl;
  186.                 ifstream lib_file(include_path);
  187.                 RecursivePreprocess(lib_file, out, include_path, include_directories);
  188.             }
  189.             else {
  190.                 cout << "unknown include file "s << string(m[1]) << " at file "s << p.string() << " at line "s << i << endl;
  191.                 return false;
  192.             }
  193.         }
  194.         else
  195.             out << temp << endl;
  196.     }
  197.     return true;
  198. }
  199.  
  200. bool findInclude(const string& file_to_find, const vector<path>& include_directories, path& result) {
  201.     for (const auto& item : include_directories) {
  202.         result = item / file_to_find;
  203.         if (fs::exists(result))
  204.             return true;
  205.     }
  206.     result.clear();
  207.     return false;
  208. }
  209.  
  210. string GetFileContents(string file) {
  211.     ifstream stream(file);
  212.  
  213.     // конструируем string по двум итераторам
  214.     return { (istreambuf_iterator<char>(stream)), istreambuf_iterator<char>() };
  215. }
  216.  
  217. string ReadLine(istream& stream) {
  218.     string s;
  219.     getline(stream, s);
  220.     return s;
  221. }
Advertisement
Add Comment
Please, Sign In to add comment