commit f49928c22a00c08d06453648856f90d4d2abf537
parent 6f7343019c63029335be0494abf485190a017509
Author: Achuthan TM <achuthantm05@gmail.com>
Date: Sun, 29 Mar 2026 07:13:50 +0530
Week 2: Implement Glushkov NFA Builder (Part 3: Finalizing)
Diffstat:
| M | src/nfa.cpp | | | 61 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | src/nfa.h | | | 11 | +++++++++++ |
2 files changed, 72 insertions(+), 0 deletions(-)
diff --git a/src/nfa.cpp b/src/nfa.cpp
@@ -204,3 +204,64 @@ void NFABuilder::computeNullableFirstLast(ASTNode* node) {
n->lastpos = n->inner->lastpos;
break;
}
+ case ASTNodeType::PLUS: {
+ auto n = static_cast<PlusNode*>(node);
+ computeNullableFirstLast(n->inner.get());
+ n->nullable = n->inner->nullable;
+ n->firstpos = n->inner->firstpos;
+ n->lastpos = n->inner->lastpos;
+ break;
+ }
+ case ASTNodeType::OPTIONAL: {
+ auto n = static_cast<OptionalNode*>(node);
+ computeNullableFirstLast(n->inner.get());
+ n->nullable = true;
+ n->firstpos = n->inner->firstpos;
+ n->lastpos = n->inner->lastpos;
+ break;
+ }
+ }
+}
+
+void NFABuilder::computeFollowpos(ASTNode* node, std::map<int, std::set<int>>& followpos) {
+ if (!node) return;
+ switch (node->type) {
+ case ASTNodeType::CONCATENATION: {
+ auto n = static_cast<ConcatenationNode*>(node);
+ computeFollowpos(n->left.get(), followpos);
+ computeFollowpos(n->right.get(), followpos);
+ for (int p : n->left->lastpos) {
+ followpos[p].insert(n->right->firstpos.begin(), n->right->firstpos.end());
+ }
+ break;
+ }
+ case ASTNodeType::STAR: {
+ auto n = static_cast<StarNode*>(node);
+ computeFollowpos(n->inner.get(), followpos);
+ for (int p : n->inner->lastpos) {
+ followpos[p].insert(n->inner->firstpos.begin(), n->inner->firstpos.end());
+ }
+ break;
+ }
+ case ASTNodeType::PLUS: {
+ auto n = static_cast<PlusNode*>(node);
+ computeFollowpos(n->inner.get(), followpos);
+ for (int p : n->inner->lastpos) {
+ followpos[p].insert(n->inner->firstpos.begin(), n->inner->firstpos.end());
+ }
+ break;
+ }
+ case ASTNodeType::UNION: {
+ auto n = static_cast<UnionNode*>(node);
+ computeFollowpos(n->left.get(), followpos);
+ computeFollowpos(n->right.get(), followpos);
+ break;
+ }
+ case ASTNodeType::OPTIONAL: {
+ auto n = static_cast<OptionalNode*>(node);
+ computeFollowpos(n->inner.get(), followpos);
+ break;
+ }
+ default: break;
+ }
+}
diff --git a/src/nfa.h b/src/nfa.h
@@ -31,3 +31,14 @@ public:
class NFABuilder {
public:
// Global state counter to ensure unique IDs across all NFAs
+ static int globalStateCounter;
+
+ static std::unique_ptr<NFA> build(ASTNode* root, int regexIdx);
+
+private:
+ static void linearize(ASTNode* node, int& posCounter, std::map<int, unsigned char>& posToChar, std::set<int>& dotPositions);
+ static void computeNullableFirstLast(ASTNode* node);
+ static void computeFollowpos(ASTNode* node, std::map<int, std::set<int>>& followpos);
+};
+
+#endif // NFA_H