xiiregexbuilder
FPGA-Accelerated Regular Expression Matching Enginesrc/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}