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
tests/parser_compiler_edge_cases.zigmodified+35-35
Changes to tests/parser_compiler_edge_cases.zig
@@ -10,13 +10,13 @@ const RegexError = @import("regex").RegexError;
1010
1111test "parser: quantifier ? at start is rejected" {
1212 const allocator = std.testing.allocator;
13 const result = Regex.compile(allocator, "?abc");
13 const result = Regex.compile(allocator, std.testing.io, "?abc");
1414 try std.testing.expectError(RegexError.UnexpectedCharacter, result);
1515}
1616
1717test "parser: nested empty groups" {
1818 const allocator = std.testing.allocator;
19 var regex = try Regex.compile(allocator, "(())");
19 var regex = try Regex.compile(allocator, std.testing.io, "(())");
2020 defer regex.deinit();
2121 // Should compile without error
2222 try std.testing.expect(try regex.isMatch(""));
@@ -25,7 +25,7 @@ test "parser: nested empty groups" {
2525test "parser: deeply nested groups" {
2626 const allocator = std.testing.allocator;
2727 // 20 levels of nesting - should be within limits
28 var regex = try Regex.compile(allocator, "((((((((((((((((((((a))))))))))))))))))))");
28 var regex = try Regex.compile(allocator, std.testing.io, "((((((((((((((((((((a))))))))))))))))))))");
2929 defer regex.deinit();
3030 try std.testing.expect(try regex.isMatch("a"));
3131}
@@ -33,20 +33,20 @@ test "parser: deeply nested groups" {
3333test "parser: consecutive quantifiers rejected by analyzer" {
3434 const allocator = std.testing.allocator;
3535 // a** parses as (a*)* which is rejected as nested quantifiers
36 const result = Regex.compile(allocator, "a**");
36 const result = Regex.compile(allocator, std.testing.io, "a**");
3737 try std.testing.expectError(RegexError.PatternTooComplex, result);
3838}
3939
4040test "parser: quantifier on quantifier rejected by analyzer" {
4141 const allocator = std.testing.allocator;
4242 // a+* parses as (a+)* which is rejected as nested quantifiers
43 const result = Regex.compile(allocator, "a+*");
43 const result = Regex.compile(allocator, std.testing.io, "a+*");
4444 try std.testing.expectError(RegexError.PatternTooComplex, result);
4545}
4646
4747test "parser: empty alternation branch is valid" {
4848 const allocator = std.testing.allocator;
49 var regex = try Regex.compile(allocator, "a|");
49 var regex = try Regex.compile(allocator, std.testing.io, "a|");
5050 defer regex.deinit();
5151 // "a|" means "a or empty string" - should match empty
5252 try std.testing.expect(try regex.isMatch("a"));
@@ -55,7 +55,7 @@ test "parser: empty alternation branch is valid" {
5555
5656test "parser: leading pipe alternation" {
5757 const allocator = std.testing.allocator;
58 var regex = try Regex.compile(allocator, "|a");
58 var regex = try Regex.compile(allocator, std.testing.io, "|a");
5959 defer regex.deinit();
6060 // "|a" means "empty string or a"
6161 try std.testing.expect(try regex.isMatch(""));
@@ -66,7 +66,7 @@ test "parser: leading pipe alternation" {
6666
6767test "parser: {0} means zero occurrences" {
6868 const allocator = std.testing.allocator;
69 var regex = try Regex.compile(allocator, "^a{0}b$");
69 var regex = try Regex.compile(allocator, std.testing.io, "^a{0}b$");
7070 defer regex.deinit();
7171
7272 try std.testing.expect(try regex.isMatch("b"));
@@ -75,7 +75,7 @@ test "parser: {0} means zero occurrences" {
7575
7676test "parser: {1} means exactly once" {
7777 const allocator = std.testing.allocator;
78 var regex = try Regex.compile(allocator, "^a{1}$");
78 var regex = try Regex.compile(allocator, std.testing.io, "^a{1}$");
7979 defer regex.deinit();
8080
8181 try std.testing.expect(try regex.isMatch("a"));
@@ -86,7 +86,7 @@ test "parser: {1} means exactly once" {
8686test "parser: large but valid quantifier" {
8787 const allocator = std.testing.allocator;
8888 // {0,100} should be valid
89 var regex = try Regex.compile(allocator, "a{0,100}");
89 var regex = try Regex.compile(allocator, std.testing.io, "a{0,100}");
9090 defer regex.deinit();
9191 try std.testing.expect(try regex.isMatch(""));
9292}
@@ -95,7 +95,7 @@ test "parser: large but valid quantifier" {
9595
9696test "parser: character class with escaped ]" {
9797 const allocator = std.testing.allocator;
98 var regex = try Regex.compile(allocator, "[\\]]");
98 var regex = try Regex.compile(allocator, std.testing.io, "[\\]]");
9999 defer regex.deinit();
100100
101101 try std.testing.expect(try regex.isMatch("]"));
@@ -105,7 +105,7 @@ test "parser: character class with escaped ]" {
105105test "parser: character class with hyphen between ranges" {
106106 const allocator = std.testing.allocator;
107107 // Hyphen at start is literal, not range
108 var regex = try Regex.compile(allocator, "[-az]");
108 var regex = try Regex.compile(allocator, std.testing.io, "[-az]");
109109 defer regex.deinit();
110110
111111 try std.testing.expect(try regex.isMatch("-"));
@@ -116,7 +116,7 @@ test "parser: character class with hyphen between ranges" {
116116
117117test "parser: negated class with range" {
118118 const allocator = std.testing.allocator;
119 var regex = try Regex.compile(allocator, "^[^0-9]+$");
119 var regex = try Regex.compile(allocator, std.testing.io, "^[^0-9]+$");
120120 defer regex.deinit();
121121
122122 try std.testing.expect(try regex.isMatch("abc"));
@@ -128,7 +128,7 @@ test "parser: negated class with range" {
128128
129129test "parser: tab and newline escapes" {
130130 const allocator = std.testing.allocator;
131 var regex = try Regex.compile(allocator, "\\t");
131 var regex = try Regex.compile(allocator, std.testing.io, "\\t");
132132 defer regex.deinit();
133133
134134 try std.testing.expect(try regex.isMatch("\t"));
@@ -137,7 +137,7 @@ test "parser: tab and newline escapes" {
137137
138138test "parser: carriage return escape" {
139139 const allocator = std.testing.allocator;
140 var regex = try Regex.compile(allocator, "\\r\\n");
140 var regex = try Regex.compile(allocator, std.testing.io, "\\r\\n");
141141 defer regex.deinit();
142142
143143 try std.testing.expect(try regex.isMatch("\r\n"));
@@ -145,7 +145,7 @@ test "parser: carriage return escape" {
145145
146146test "parser: escaped caret and dollar" {
147147 const allocator = std.testing.allocator;
148 var regex = try Regex.compile(allocator, "\\^\\$");
148 var regex = try Regex.compile(allocator, std.testing.io, "\\^\\$");
149149 defer regex.deinit();
150150
151151 try std.testing.expect(try regex.isMatch("^$"));
@@ -156,7 +156,7 @@ test "parser: escaped caret and dollar" {
156156
157157test "compiler: alternation with quantifiers" {
158158 const allocator = std.testing.allocator;
159 var regex = try Regex.compile(allocator, "^(ab+|cd*)e$");
159 var regex = try Regex.compile(allocator, std.testing.io, "^(ab+|cd*)e$");
160160 defer regex.deinit();
161161
162162 try std.testing.expect(try regex.isMatch("abe"));
@@ -169,7 +169,7 @@ test "compiler: alternation with quantifiers" {
169169
170170test "compiler: character class in alternation" {
171171 const allocator = std.testing.allocator;
172 var regex = try Regex.compile(allocator, "^([0-9]+|[a-z]+)$");
172 var regex = try Regex.compile(allocator, std.testing.io, "^([0-9]+|[a-z]+)$");
173173 defer regex.deinit();
174174
175175 try std.testing.expect(try regex.isMatch("123"));
@@ -180,7 +180,7 @@ test "compiler: character class in alternation" {
180180
181181test "compiler: optional group" {
182182 const allocator = std.testing.allocator;
183 var regex = try Regex.compile(allocator, "^colou?r$");
183 var regex = try Regex.compile(allocator, std.testing.io, "^colou?r$");
184184 defer regex.deinit();
185185
186186 try std.testing.expect(try regex.isMatch("color"));
@@ -190,7 +190,7 @@ test "compiler: optional group" {
190190
191191test "compiler: optional group with parentheses" {
192192 const allocator = std.testing.allocator;
193 var regex = try Regex.compile(allocator, "^(un)?happy$");
193 var regex = try Regex.compile(allocator, std.testing.io, "^(un)?happy$");
194194 defer regex.deinit();
195195
196196 try std.testing.expect(try regex.isMatch("happy"));
@@ -200,7 +200,7 @@ test "compiler: optional group with parentheses" {
200200
201201test "compiler: multiple capture groups" {
202202 const allocator = std.testing.allocator;
203 var regex = try Regex.compile(allocator, "(\\d{4})-(\\d{2})-(\\d{2})");
203 var regex = try Regex.compile(allocator, std.testing.io, "(\\d{4})-(\\d{2})-(\\d{2})");
204204 defer regex.deinit();
205205
206206 if (try regex.find("Today is 2024-01-15!")) |match| {
@@ -220,7 +220,7 @@ test "compiler: multiple capture groups" {
220220
221221test "compiler: anchored pattern only tries position 0" {
222222 const allocator = std.testing.allocator;
223 var regex = try Regex.compile(allocator, "^abc");
223 var regex = try Regex.compile(allocator, std.testing.io, "^abc");
224224 defer regex.deinit();
225225
226226 try std.testing.expect(try regex.isMatch("abcdef"));
@@ -230,7 +230,7 @@ test "compiler: anchored pattern only tries position 0" {
230230
231231test "compiler: end-anchored pattern" {
232232 const allocator = std.testing.allocator;
233 var regex = try Regex.compile(allocator, "abc$");
233 var regex = try Regex.compile(allocator, std.testing.io, "abc$");
234234 defer regex.deinit();
235235
236236 if (try regex.find("xyzabc")) |match| {
@@ -244,7 +244,7 @@ test "compiler: end-anchored pattern" {
244244
245245test "compiler: both anchors" {
246246 const allocator = std.testing.allocator;
247 var regex = try Regex.compile(allocator, "^exact$");
247 var regex = try Regex.compile(allocator, std.testing.io, "^exact$");
248248 defer regex.deinit();
249249
250250 try std.testing.expect(try regex.isMatch("exact"));
@@ -257,13 +257,13 @@ test "compiler: both anchors" {
257257
258258test "compiler: password strength check" {
259259 const allocator = std.testing.allocator;
260 var has_digit = try Regex.compile(allocator, "\\d");
260 var has_digit = try Regex.compile(allocator, std.testing.io, "\\d");
261261 defer has_digit.deinit();
262 var has_lower = try Regex.compile(allocator, "[a-z]");
262 var has_lower = try Regex.compile(allocator, std.testing.io, "[a-z]");
263263 defer has_lower.deinit();
264 var has_upper = try Regex.compile(allocator, "[A-Z]");
264 var has_upper = try Regex.compile(allocator, std.testing.io, "[A-Z]");
265265 defer has_upper.deinit();
266 var min_length = try Regex.compile(allocator, ".{8,}");
266 var min_length = try Regex.compile(allocator, std.testing.io, ".{8,}");
267267 defer min_length.deinit();
268268
269269 const password = "MyP4ssword";
@@ -280,7 +280,7 @@ test "compiler: password strength check" {
280280
281281test "compiler: CSV field extraction" {
282282 const allocator = std.testing.allocator;
283 var regex = try Regex.compile(allocator, "[^,]+");
283 var regex = try Regex.compile(allocator, std.testing.io, "[^,]+");
284284 defer regex.deinit();
285285
286286 const matches = try regex.findAll(allocator, "foo,bar,baz");
@@ -300,7 +300,7 @@ test "compiler: CSV field extraction" {
300300
301301test "compiler: whitespace normalization via replaceAll" {
302302 const allocator = std.testing.allocator;
303 var regex = try Regex.compile(allocator, "\\s+");
303 var regex = try Regex.compile(allocator, std.testing.io, "\\s+");
304304 defer regex.deinit();
305305
306306 const result = try regex.replaceAll(allocator, " hello world ", " ");
@@ -312,7 +312,7 @@ test "compiler: whitespace normalization via replaceAll" {
312312
313313test "compiler: pattern with only ^ anchor" {
314314 const allocator = std.testing.allocator;
315 var regex = try Regex.compile(allocator, "^");
315 var regex = try Regex.compile(allocator, std.testing.io, "^");
316316 defer regex.deinit();
317317
318318 // ^ matches at position 0 of any string (matches zero-width)
@@ -322,7 +322,7 @@ test "compiler: pattern with only ^ anchor" {
322322
323323test "compiler: pattern with only $ anchor" {
324324 const allocator = std.testing.allocator;
325 var regex = try Regex.compile(allocator, "$");
325 var regex = try Regex.compile(allocator, std.testing.io, "$");
326326 defer regex.deinit();
327327
328328 // $ matches at end of any string (zero-width)
@@ -334,7 +334,7 @@ test "compiler: pattern with only $ anchor" {
334334
335335test "compiler: dot plus" {
336336 const allocator = std.testing.allocator;
337 var regex = try Regex.compile(allocator, "^.+$");
337 var regex = try Regex.compile(allocator, std.testing.io, "^.+$");
338338 defer regex.deinit();
339339
340340 try std.testing.expect(try regex.isMatch("a"));
@@ -344,7 +344,7 @@ test "compiler: dot plus" {
344344
345345test "compiler: dot question" {
346346 const allocator = std.testing.allocator;
347 var regex = try Regex.compile(allocator, "^.?$");
347 var regex = try Regex.compile(allocator, std.testing.io, "^.?$");
348348 defer regex.deinit();
349349
350350 try std.testing.expect(try regex.isMatch(""));
@@ -354,7 +354,7 @@ test "compiler: dot question" {
354354
355355test "compiler: dot repeat" {
356356 const allocator = std.testing.allocator;
357 var regex = try Regex.compile(allocator, "^.{3}$");
357 var regex = try Regex.compile(allocator, std.testing.io, "^.{3}$");
358358 defer regex.deinit();
359359
360360 try std.testing.expect(try regex.isMatch("abc"));