ReviewOS

also looking at this

zig-utils/zig-regex

Port to latest zig-master

#2
Closed armagidon-exception wants to merge main into main
53 files +1149 -1017
src/regex.zigmodified+25-27
Changes to src/regex.zig
@@ -41,6 +41,7 @@ pub const EngineType = enum {
4141/// Main regex type - represents a compiled regular expression pattern
4242pub const Regex = struct {
4343 allocator: std.mem.Allocator,
44 io: std.Io,
4445 pattern: []const u8,
4546 nfa: compiler.NFA,
4647 backtrack_engine: ?backtrack.BacktrackEngine,
@@ -52,12 +53,12 @@ pub const Regex = struct {
5253 named_captures: std.StringHashMap(usize), // name -> capture_index mapping
5354
5455 /// Compile a regex pattern with default flags
55 pub fn compile(allocator: std.mem.Allocator, pattern: []const u8) !Regex {
56 return compileWithFlags(allocator, pattern, .{});
56 pub fn compile(allocator: std.mem.Allocator, io: std.Io, pattern: []const u8) !Regex {
57 return compileWithFlags(allocator, io, pattern, .{});
5758 }
5859
5960 /// Compile a regex pattern with custom flags
60 pub fn compileWithFlags(allocator: std.mem.Allocator, pattern: []const u8, flags: common.CompileFlags) !Regex {
61 pub fn compileWithFlags(allocator: std.mem.Allocator, io: std.Io, pattern: []const u8, flags: common.CompileFlags) !Regex {
6162 if (pattern.len == 0) {
6263 return RegexError.EmptyPattern;
6364 }
@@ -92,12 +93,7 @@ pub const Regex = struct {
9293
9394 if (needs_backtracking) {
9495 // Use backtracking engine
95 var backtrack_engine = try backtrack.BacktrackEngine.init(
96 allocator,
97 tree.root,
98 tree.capture_count,
99 flags
100 );
96 var backtrack_engine = try backtrack.BacktrackEngine.init(allocator, tree.root, tree.capture_count, flags);
10197 errdefer backtrack_engine.deinit();
10298
10399 // Create a dummy NFA (not used)
@@ -106,6 +102,7 @@ pub const Regex = struct {
106102 _ = try dummy_nfa.addState();
107103
108104 return Regex{
105 .io = io,
109106 .allocator = allocator,
110107 .pattern = owned_pattern,
111108 .nfa = dummy_nfa,
@@ -126,6 +123,7 @@ pub const Regex = struct {
126123 _ = try comp.compile(&tree);
127124
128125 return Regex{
126 .io = io,
129127 .allocator = allocator,
130128 .pattern = owned_pattern,
131129 .nfa = comp.nfa,
formatting only · 13 hidden lines
Changes to src/regex.zig
@@ -676,11 +674,11 @@ fn requiresBacktracking(node: *ast.Node) bool { formatting only
676674 // Recursively check compound nodes
677675 .concat => {
678676 return requiresBacktracking(node.data.concat.left) or
679 requiresBacktracking(node.data.concat.right);
677 requiresBacktracking(node.data.concat.right);
680678 },
681679 .alternation => {
682680 return requiresBacktracking(node.data.alternation.left) or
683 requiresBacktracking(node.data.alternation.right);
681 requiresBacktracking(node.data.alternation.right);
684682 },
685683 .group => return requiresBacktracking(node.data.group.child),
686684
Changes to src/regex.zig
@@ -727,20 +725,20 @@ fn collectNamedCaptures(node: *ast.Node, map: *std.StringHashMap(usize)) !void {
727725
728726test "compile empty pattern" {
729727 const allocator = std.testing.allocator;
730 const result = Regex.compile(allocator, "");
728 const result = Regex.compile(allocator, std.testing.io, "");
731729 try std.testing.expectError(RegexError.EmptyPattern, result);
732730}
733731
734732test "compile basic pattern" {
735733 const allocator = std.testing.allocator;
736 var regex = try Regex.compile(allocator, "test");
734 var regex = try Regex.compile(allocator, std.testing.io, "test");
737735 defer regex.deinit();
738736 try std.testing.expectEqualStrings("test", regex.pattern);
739737}
740738
741739test "match literal" {
742740 const allocator = std.testing.allocator;
743 var regex = try Regex.compile(allocator, "hello");
741 var regex = try Regex.compile(allocator, std.testing.io, "hello");
744742 defer regex.deinit();
745743
746744 try std.testing.expect(try regex.isMatch("hello"));
@@ -749,7 +747,7 @@ test "match literal" {
749747
750748test "find literal" {
751749 const allocator = std.testing.allocator;
752 var regex = try Regex.compile(allocator, "world");
750 var regex = try Regex.compile(allocator, std.testing.io, "world");
753751 defer regex.deinit();
754752
755753 if (try regex.find("hello world")) |match_result| {
@@ -765,7 +763,7 @@ test "find literal" {
765763
766764test "alternation" {
767765 const allocator = std.testing.allocator;
768 var regex = try Regex.compile(allocator, "cat|dog");
766 var regex = try Regex.compile(allocator, std.testing.io, "cat|dog");
769767 defer regex.deinit();
770768
771769 try std.testing.expect(try regex.isMatch("cat"));
@@ -775,7 +773,7 @@ test "alternation" {
775773
776774test "star quantifier" {
777775 const allocator = std.testing.allocator;
778 var regex = try Regex.compile(allocator, "a*");
776 var regex = try Regex.compile(allocator, std.testing.io, "a*");
779777 defer regex.deinit();
780778
781779 try std.testing.expect(try regex.isMatch(""));
@@ -785,7 +783,7 @@ test "star quantifier" {
785783
786784test "plus quantifier" {
787785 const allocator = std.testing.allocator;
788 var regex = try Regex.compile(allocator, "a+");
786 var regex = try Regex.compile(allocator, std.testing.io, "a+");
789787 defer regex.deinit();
790788
791789 try std.testing.expect(!try regex.isMatch(""));
@@ -795,7 +793,7 @@ test "plus quantifier" {
795793
796794test "optional quantifier" {
797795 const allocator = std.testing.allocator;
798 var regex = try Regex.compile(allocator, "a?");
796 var regex = try Regex.compile(allocator, std.testing.io, "a?");
799797 defer regex.deinit();
800798
801799 try std.testing.expect(try regex.isMatch(""));
@@ -804,7 +802,7 @@ test "optional quantifier" {
804802
805803test "dot wildcard" {
806804 const allocator = std.testing.allocator;
807 var regex = try Regex.compile(allocator, "a.c");
805 var regex = try Regex.compile(allocator, std.testing.io, "a.c");
808806 defer regex.deinit();
809807
810808 try std.testing.expect(try regex.isMatch("abc"));
@@ -814,7 +812,7 @@ test "dot wildcard" {
814812
815813test "character class \\d" {
816814 const allocator = std.testing.allocator;
817 var regex = try Regex.compile(allocator, "\\d+");
815 var regex = try Regex.compile(allocator, std.testing.io, "\\d+");
818816 defer regex.deinit();
819817
820818 if (try regex.find("abc123def")) |match_result| {
@@ -828,7 +826,7 @@ test "character class \\d" {
828826
829827test "replace" {
830828 const allocator = std.testing.allocator;
831 var regex = try Regex.compile(allocator, "world");
829 var regex = try Regex.compile(allocator, std.testing.io, "world");
832830 defer regex.deinit();
833831
834832 const result = try regex.replace(allocator, "hello world", "Zig");
@@ -839,7 +837,7 @@ test "replace" {
839837
840838test "replace all" {
841839 const allocator = std.testing.allocator;
842 var regex = try Regex.compile(allocator, "a");
840 var regex = try Regex.compile(allocator, std.testing.io, "a");
843841 defer regex.deinit();
844842
845843 const result = try regex.replaceAll(allocator, "banana", "o");
@@ -850,7 +848,7 @@ test "replace all" {
850848
851849test "split" {
852850 const allocator = std.testing.allocator;
853 var regex = try Regex.compile(allocator, ",");
851 var regex = try Regex.compile(allocator, std.testing.io, ",");
854852 defer regex.deinit();
855853
856854 const parts = try regex.split(allocator, "a,b,c");
@@ -866,7 +864,7 @@ test "compile rejects dangerous nested quantifiers" {
866864 const allocator = std.testing.allocator;
867865
868866 // This pattern should be rejected as critical risk
869 const result = Regex.compile(allocator, "(a+)+");
867 const result = Regex.compile(allocator, std.testing.io, "(a+)+");
870868 try std.testing.expectError(RegexError.PatternTooComplex, result);
871869}
872870
@@ -874,7 +872,7 @@ test "compile rejects nested stars" {
874872 const allocator = std.testing.allocator;
875873
876874 // This pattern should be rejected
877 const result = Regex.compile(allocator, "(a*)*");
875 const result = Regex.compile(allocator, std.testing.io, "(a*)*");
878876 try std.testing.expectError(RegexError.PatternTooComplex, result);
879877}
880878
@@ -882,6 +880,6 @@ test "compile accepts safe complex patterns" {
882880 const allocator = std.testing.allocator;
883881
884882 // This pattern should be accepted (medium risk is OK)
885 var regex = try Regex.compile(allocator, "a+b*c?d{2,5}");
883 var regex = try Regex.compile(allocator, std.testing.io, "a+b*c?d{2,5}");
886884 defer regex.deinit();
887885}