xiiregexbuilder

FPGA-Accelerated Regular Expression Matching Engine
commit 1fcbf19350c8294cd19982d8b50360baf64633f2
parent 907199802749d357c7f9a12bdb596fee78e5f6a7
Author: Pranav Prabhu Kumble <kumblepranavprabhu@gmail.com>
Date:   Sun, 29 Mar 2026 21:04:36 +0530

Week 2: Implement AST Parser (Part 2: Core logic)

Diffstat:
Msrc/parser.cpp | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/parser.h | 47+++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 105 insertions(+), 0 deletions(-)

diff --git a/src/parser.cpp b/src/parser.cpp @@ -40,3 +40,61 @@ std::unique_ptr<ASTNode> Parser::parseExpression() { } return left; +} + +// Term -> Factor+ +std::unique_ptr<ASTNode> Parser::parseTerm() { + auto node = parseFactor(); + + while (!isAtEnd() && + peek().type != TokenType::PIPE && + peek().type != TokenType::RPAREN && + peek().type != TokenType::END_OF_INPUT) { + auto next = parseFactor(); + node = std::make_unique<ConcatenationNode>(std::move(node), std::move(next)); + } + + return node; +} + +// Factor -> Atom ( '*' | '+' | '?' )? +std::unique_ptr<ASTNode> Parser::parseFactor() { + auto node = parseAtom(); + + if (match(TokenType::STAR)) { + node = std::make_unique<StarNode>(std::move(node)); + } else if (match(TokenType::PLUS)) { + node = std::make_unique<PlusNode>(std::move(node)); + } else if (match(TokenType::QUESTION)) { + node = std::make_unique<OptionalNode>(std::move(node)); + } + + return node; +} + +// Atom -> LITERAL | DOT | '(' Expression ')' +std::unique_ptr<ASTNode> Parser::parseAtom() { + if (match(TokenType::LITERAL)) { + return std::make_unique<LiteralNode>(tokens[pos - 1].value); + } + + if (match(TokenType::DOT)) { + return std::make_unique<DotNode>(); + } + + if (match(TokenType::LPAREN)) { + auto node = parseExpression(); + if (!match(TokenType::RPAREN)) { + error("Unmatched parenthesis: expected ')'"); + } + return node; + } + + if (peek().type == TokenType::STAR || peek().type == TokenType::PLUS || peek().type == TokenType::QUESTION) { + error("Quantifier '" + tokenTypeToString(peek().type) + "' applied to nothing"); + } + + error("Unexpected token: " + tokenTypeToString(peek().type)); + return nullptr; // Should not reach here +} + diff --git a/src/parser.h b/src/parser.h @@ -33,3 +33,50 @@ std::string nodeTypeToString(ASTNodeType type); class LiteralNode : public ASTNode { public: + char value; + int position; // Used for Glushkov's construction + explicit LiteralNode(char v) : ASTNode(ASTNodeType::LITERAL), value(v), position(-1) {} +}; + +class DotNode : public ASTNode { +public: + int position; // Used for Glushkov's construction + DotNode() : ASTNode(ASTNodeType::DOT), position(-1) {} +}; + +class ConcatenationNode : public ASTNode { +public: + std::unique_ptr<ASTNode> left; + std::unique_ptr<ASTNode> right; + ConcatenationNode(std::unique_ptr<ASTNode> l, std::unique_ptr<ASTNode> r) + : ASTNode(ASTNodeType::CONCATENATION), left(std::move(l)), right(std::move(r)) {} +}; + +class UnionNode : public ASTNode { +public: + std::unique_ptr<ASTNode> left; + std::unique_ptr<ASTNode> right; + UnionNode(std::unique_ptr<ASTNode> l, std::unique_ptr<ASTNode> r) + : ASTNode(ASTNodeType::UNION), left(std::move(l)), right(std::move(r)) {} +}; + +class StarNode : public ASTNode { +public: + std::unique_ptr<ASTNode> inner; + explicit StarNode(std::unique_ptr<ASTNode> i) + : ASTNode(ASTNodeType::STAR), inner(std::move(i)) {} +}; + +class PlusNode : public ASTNode { +public: + std::unique_ptr<ASTNode> inner; + explicit PlusNode(std::unique_ptr<ASTNode> i) + : ASTNode(ASTNodeType::PLUS), inner(std::move(i)) {} +}; + +class OptionalNode : public ASTNode { +public: + std::unique_ptr<ASTNode> inner; + explicit OptionalNode(std::unique_ptr<ASTNode> i) + : ASTNode(ASTNodeType::OPTIONAL), inner(std::move(i)) {} +};