xiiregexbuilder

FPGA-Accelerated Regular Expression Matching Engine

src/golden.cpp (3177B)


 1#include <iostream>
 2#include <fstream>
 3#include <string>
 4#include <vector>
 5#include <regex>
 6#include <iomanip>
 7#include <algorithm>
 8
 9std::string trim(const std::string& str) {
10    size_t first = str.find_first_not_of(" \t\r\n");
11    if (first == std::string::npos) return "";
12    size_t last = str.find_last_not_of(" \t\r\n");
13    return str.substr(first, (last - first + 1));
14}
15
16int main(int argc, char* argv[]) {
17    if (argc < 3) {
18        std::cerr << "Usage: " << argv[0] << " <regex_file> <test_strings_file> [output_file]" << std::endl;
19        return 1;
20    }
21
22    std::string regexFilename = argv[1];
23    std::string testFilename = argv[2];
24    std::string outputFilename = (argc > 3) ? argv[3] : "expected_matches.txt";
25
26    std::ifstream regexFile(regexFilename);
27    if (!regexFile.is_open()) {
28        std::cerr << "Failed to open " << regexFilename << std::endl;
29        return 1;
30    }
31
32    std::vector<std::string> regexes;
33    std::string line;
34    while (std::getline(regexFile, line)) {
35        std::string trimmed = trim(line);
36        if (trimmed.empty() || trimmed[0] == '#') continue;
37        regexes.push_back(trimmed);
38    }
39    regexFile.close();
40
41    std::ifstream testFile(testFilename);
42    if (!testFile.is_open()) {
43        std::cerr << "Failed to open " << testFilename << std::endl;
44        return 1;
45    }
46
47    std::vector<std::string> testStrings;
48    while (std::getline(testFile, line)) {
49        // Remove trailing \r\n
50        size_t last = line.find_last_not_of("\r\n");
51        std::string s = (last != std::string::npos) ? line.substr(0, last + 1) : (line.empty() ? "" : line);
52        
53        // Skip comments and blank lines if desired, but spec says "Each line is one test string"
54        // Let's at least skip the comment headers if they start with #
55        if (!s.empty() && s[0] == '#') continue;
56        if (s.empty()) {
57            // Check if it's truly a blank line (might be intentional empty string test)
58            // For safety, let's only skip if the raw line was empty or just whitespace
59            if (trim(line).empty()) continue;
60        }
61
62        testStrings.push_back(s);
63    }
64    testFile.close();
65
66    std::ofstream outFile(outputFilename);
67    if (!outFile.is_open()) {
68        std::cerr << "Failed to open " << outputFilename << " for writing." << std::endl;
69        return 1;
70    }
71
72    for (const auto& testStr : testStrings) {
73        std::string mask = "";
74        for (size_t i = 0; i < regexes.size(); ++i) {
75            bool matches = false;
76            try {
77                // std::regex_match does full match.
78                std::regex re(regexes[i]);
79                matches = std::regex_match(testStr, re);
80            } catch (const std::regex_error& e) {
81                // Ignore syntax mismatch
82            }
83            mask += (matches ? "1" : "0");
84        }
85        // Reverse mask so bit 0 is on the right (Verilog convention)
86        std::reverse(mask.begin(), mask.end());
87        outFile << mask << "\n";
88    }
89    outFile.close();
90
91    std::cout << "Golden reference generated: " << outputFilename << " (" << testStrings.size() << " test cases)" << std::endl;
92
93    return 0;
94}