xiiregexbuilder

FPGA-Accelerated Regular Expression Matching Engine

src/parser_tester.cpp (3305B)


  1#include <iostream>
  2#include <fstream>
  3#include <string>
  4#include <vector>
  5#include <algorithm>
  6#include "lexer.h"
  7#include "parser.h"
  8#include "nfa.h"
  9
 10std::string trim(const std::string &str)
 11{
 12    size_t first = str.find_first_not_of(" \t\r\n");
 13    if (first == std::string::npos)
 14        return "";
 15    size_t last = str.find_last_not_of(" \t\r\n");
 16    return str.substr(first, (last - first + 1));
 17}
 18
 19int main(int argc, char *argv[])
 20{
 21    if (argc < 2)
 22    {
 23        std::cerr << "Usage: " << argv[0] << " <regex_file> [test_strings_file]" << std::endl;
 24        return 1;
 25    }
 26
 27    std::string regexFilename = argv[1];
 28    std::ifstream regexFile(regexFilename);
 29    if (!regexFile.is_open())
 30    {
 31        std::cerr << "Failed to open " << regexFilename << std::endl;
 32        return 1;
 33    }
 34
 35    // Optional: Test strings for validation
 36    std::string testFilename = (argc > 2) ? argv[2] : "";
 37    std::vector<std::string> testStrings;
 38    if (!testFilename.empty())
 39    {
 40        std::ifstream testFile(testFilename);
 41        if (testFile.is_open())
 42        {
 43            std::string testLine;
 44            while (std::getline(testFile, testLine))
 45            {
 46                std::string trimmed = trim(testLine);
 47                if (trimmed.empty() || trimmed[0] == '#')
 48                    continue;
 49                testStrings.push_back(trimmed);
 50            }
 51        }
 52    }
 53
 54    std::string line;
 55    int lineNum = 0;
 56    int regexIdx = 0;
 57    std::vector<std::unique_ptr<NFA>> nfas;
 58    std::vector<std::string> originalRegexes;
 59
 60    // Core Pipeline: Regex -> Tokens -> AST -> NFA
 61    while (std::getline(regexFile, line))
 62    {
 63        lineNum++;
 64        std::string trimmedLine = trim(line);
 65        if (trimmedLine.empty() || trimmedLine[0] == '#')
 66            continue;
 67
 68        originalRegexes.push_back(trimmedLine);
 69        Lexer lexer(trimmedLine, lineNum);
 70        try
 71        {
 72            std::vector<Token> tokens = lexer.tokenize();
 73            Parser parser(tokens);
 74            auto ast = parser.parse();
 75
 76            // Glushkov NFA construction
 77            auto nfa = NFABuilder::build(ast.get(), regexIdx++);
 78            if (nfa)
 79            {
 80                nfas.push_back(std::move(nfa));
 81            }
 82        }
 83        catch (const std::exception &e)
 84        {
 85            std::cerr << "Error processing regex '" << trimmedLine << "': " << e.what() << std::endl;
 86        }
 87    }
 88
 89    std::cout << "Successfully built " << nfas.size() << " NFAs." << std::endl;
 90
 91    // Optional Validation: NFA Simulation
 92    if (!testStrings.empty())
 93    {
 94        std::cout << "\n--- NFA Simulation Results ---" << std::endl;
 95        for (const auto &testStr : testStrings)
 96        {
 97            std::cout << "String: \"" << testStr << "\"" << std::endl;
 98            for (size_t i = 0; i < nfas.size(); ++i)
 99            {
100                bool matches = nfas[i]->simulate(testStr);
101                std::cout << "  Regex [" << i << "] (" << originalRegexes[i] << "): "
102                          << (matches ? "MATCH" : "NO MATCH") << std::endl;
103            }
104            std::cout << std::endl;
105        }
106    }
107
108    // Future: Stage 3 -  Verilog Emitter
109    // if (!nfas.empty()) {
110    //     Emitter emitter(nfas);
111    //     emitter.emit("output/");
112    // }
113
114    return 0;
115}