main.cpp (4354B)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | #include <iostream> #include <fstream> #include <string> #include <vector> #include <memory> #include <regex> #include <algorithm> #include "lexer.h" #include "parser.h" #include "nfa.h" #include "emitter.h" std::string trim(const std::string& str) { size_t first = str.find_first_not_of(" \t\r\n"); if (first == std::string::npos) return ""; size_t last = str.find_last_not_of(" \t\r\n"); return str.substr(first, (last - first + 1)); } int main(int argc, char* argv[]) { bool isPII = false; int argOffset = 1; if (argc > 1 && std::string(argv[1]) == "--pii") { isPII = true; argOffset = 2; } if (argc < argOffset + 1) { std::cerr << "Usage: " << argv[0] << " [--pii] <regex_file> [test_strings_file] [output_dir]" << std::endl; return 1; } std::string regexFilename = argv[argOffset]; std::string testFilename = (argc > argOffset + 1) ? argv[argOffset + 1] : ""; std::string outputDir = (argc > argOffset + 2) ? argv[argOffset + 2] : "output"; if (testFilename == "-" || testFilename == "none") { testFilename = ""; } std::ifstream regexFile(regexFilename); if (!regexFile.is_open()) { std::cerr << "Failed to open regex file: " << regexFilename << std::endl; return 1; } std::string line; int lineNum = 0; int regexIdx = 0; std::vector<std::unique_ptr<NFA>> nfas; std::vector<std::string> rawRegexes; std::cout << "Starting XIIRegexBuilder pipeline..." << std::endl; while (std::getline(regexFile, line)) { lineNum++; std::string trimmedLine = trim(line); if (trimmedLine.empty() || trimmedLine[0] == '#') continue; std::cout << "Processing Regex [" << regexIdx << "]: " << trimmedLine << std::endl; Lexer lexer(trimmedLine, lineNum); try { std::vector<Token> tokens = lexer.tokenize(); Parser parser(tokens); auto ast = parser.parse(); auto nfa = NFABuilder::build(ast.get(), regexIdx); if (nfa) { nfas.push_back(std::move(nfa)); rawRegexes.push_back(trimmedLine); regexIdx++; // Increment only on success } } catch (const std::exception& e) { std::cerr << "Error parsing regex: " << e.what() << std::endl; } } if (nfas.empty()) { std::cerr << "No valid regexes found. Exiting." << std::endl; return 1; } std::vector<std::string> testStrings; std::vector<std::string> expectedMatches; if (!testFilename.empty()) { std::ifstream testFile(testFilename); if (testFile.is_open()) { std::string tline; while (std::getline(testFile, tline)) { size_t last = tline.find_last_not_of("\r\n"); std::string s = (last != std::string::npos) ? tline.substr(0, last + 1) : (tline.empty() ? "" : tline); // Skip comments and truly blank lines if (!s.empty() && s[0] == '#') continue; if (s.empty() && trim(tline).empty()) continue; testStrings.push_back(s); // Generate expected matches using std::regex std::string mask = ""; for (const auto& re_str : rawRegexes) { bool match = false; try { std::regex re(re_str); match = std::regex_match(s, re); } catch (...) {} mask += (match ? "1" : "0"); } std::reverse(mask.begin(), mask.end()); expectedMatches.push_back(mask); } std::cout << "Loaded " << testStrings.size() << " test strings and generated golden matches." << std::endl; } } std::cout << "Generated " << nfas.size() << " NFAs. Emitting Verilog..." << std::endl; try { Emitter::emit(nfas, outputDir, testStrings, expectedMatches, isPII); std::cout << "Pipeline complete. Verilog files emitted to '" << outputDir << "/'" << std::endl; } catch (const std::exception& e) { std::cerr << "Error during Verilog emission: " << e.what() << std::endl; return 1; } return 0; } |