Previously, find and findall would return void if no matches were found.
This commit changes this behavior, so an empty slice is returned
instead.
Signed-off-by: Sebastian <sebastian@sebsite.pw>
---
Since v1: dropped free_{captures,matches} -> {captures,matches}_free
patch, since it's still unclear how these functions should be named.
Either the style guide needs to be updated and these functions changed,
or other stdlib functions should be changed.
regex/+test.ha | 106 +++++++++++++++++++++++--------------------------regex/README | 30 ++++++--------regex/regex.ha | 14 ++++---
3 files changed, 69 insertions(+), 81 deletions(-)
diff --git a/regex/+test.ha b/regex/+test.ha
index 48549d70..181cf0ec 100644
--- a/regex/+test.ha+++ b/regex/+test.ha
@@ -36,31 +36,30 @@ fn run_find_case(
};
defer finish(&re);
- match (find(&re, string)) {- case void =>+ const captures = find(&re, string);+ defer free_captures(captures);+ if (len(captures) == 0) { if (expected == matchres::MATCH) {
fmt::errorfln("Expected expression /{}/ to match string \"{}\", but it did not",
expr, string)!;
abort();
};
+ return;+ } else if (expected == matchres::NOMATCH) {+ fmt::errorfln("Expected expression /{}/ to not match string \"{}\", but it did",+ expr, string)!;+ abort();+ };- case let captures: []capture =>- defer free_captures(captures);- if (expected == matchres::NOMATCH) {- fmt::errorfln("Expected expression /{}/ to not match string \"{}\", but it did",- expr, string)!;- abort();- };- if (start: size != captures[0].start) {- fmt::errorfln("Expected start of main capture to be {} but it was {}",- start, captures[0].start)!;- abort();- };- if (end: size != captures[0].end) {- fmt::errorfln("Expected end of main capture to be {} but it was {}",- end, captures[0].end)!;- abort();- };+ if (start: size != captures[0].start) {+ fmt::errorfln("Expected start of main capture to be {} but it was {}",+ start, captures[0].start)!;+ abort();+ };+ if (end: size != captures[0].end) {+ fmt::errorfln("Expected end of main capture to be {} but it was {}",+ end, captures[0].end)!;+ abort(); };
};
@@ -68,15 +67,14 @@ fn run_submatch_case(
expr: str,
string: str,
expected: matchres,
- count: size, targets: []str
) void = {
const re = compile(expr)!;
defer finish(&re);
- const captures = find(&re, string) as []capture;+ const captures = find(&re, string); defer free_captures(captures);
- assert(len(captures) == count, "Invalid number of captures");+ assert(len(captures) == len(targets), "Invalid number of captures"); for (let i = 0z; i < len(targets); i += 1) {
assert(targets[i] == captures[i].content, "Invalid capture");
};
@@ -86,7 +84,6 @@ fn run_findall_case(
expr: str,
string: str,
expected: matchres,
- count: size, targets: []str
) void = {
const re = match (compile(expr)) {
@@ -108,33 +105,30 @@ fn run_findall_case(
abort();
};
- match (findall(&re, string)) {- case void =>- if (expected == matchres::MATCH) {- fmt::errorfln("Expected expression /{}/ to match string \"{}\", but it did not",- expr, string)!;- abort();- };+ const matches = findall(&re, string);+ if (len(matches) == 0 && expected == matchres::MATCH) {+ fmt::errorfln("Expected expression /{}/ to match string \"{}\", but it did not",+ expr, string)!;+ abort();+ };+ defer free_matches(matches);- case let matches: [][]capture =>- defer free_matches(matches);- if (expected == matchres::NOMATCH) {- fmt::errorfln("Expected expression /{}/ to not match string \"{}\", but it did",- expr, string)!;- abort();- };- if (count != len(matches)) {- fmt::errorfln("Expected to find {} matches but found {}",- count, len(matches))!;+ if (expected == matchres::NOMATCH) {+ fmt::errorfln("Expected expression /{}/ to not match string \"{}\", but it did",+ expr, string)!;+ abort();+ };+ if (len(targets) != len(matches)) {+ fmt::errorfln("Expected expression /{}/ to find {} matches but found {}",+ expr, len(targets), len(matches))!;+ abort();+ };+ for (let i = 0z; i < len(matches); i += 1) {+ if (matches[i][0].content != targets[i]) {+ fmt::errorfln("Expected submatch of expression /{}/ to be {} but it was {}",+ expr, targets[i], matches[i][0].content)!; abort();
};
- for (let i = 0z; i < len(matches); i += 1) {- if (matches[i][0].content != targets[i]) {- fmt::errorfln("Expected submatch to be {} but it was {}",- targets[i], matches[i][0].content)!;- abort();- };- }; };
};
@@ -553,32 +547,30 @@ fn run_findall_case(
const submatch_cases = [
// literals
- (`aaa ([^ ]*) (...)`, "aaa bbb ccc", matchres::MATCH, 3z,- ["aaa bbb ccc", "bbb", "ccc"]),+ (`aaa ([^ ]*) (...)`, "aaa bbb ccc", matchres::MATCH,+ ["aaa bbb ccc", "bbb", "ccc"]: []str), ];
for (let i = 0z; i < len(submatch_cases); i += 1) {
const expr = submatch_cases[i].0;
const string = submatch_cases[i].1;
const should_match = submatch_cases[i].2;
- const count = submatch_cases[i].3;- const targets = submatch_cases[i].4;- run_submatch_case(expr, string, should_match, count, targets);+ const targets = submatch_cases[i].3;+ run_submatch_case(expr, string, should_match, targets); };
};
@test fn findall() void = {
const cases = [
- (`ab.`, "hello abc and abあ test abq thanks", matchres::MATCH, 3z,- ["abc", "abあ", "abq"]),+ (`ab.`, "hello abc and abあ test abq thanks", matchres::MATCH,+ ["abc", "abあ", "abq"]: []str), ];
for (let i = 0z; i < len(cases); i += 1) {
const expr = cases[i].0;
const string = cases[i].1;
const should_match = cases[i].2;
- const count = cases[i].3;- const targets = cases[i].4;- run_findall_case(expr, string, should_match, count, targets);+ const targets = cases[i].3;+ run_findall_case(expr, string, should_match, targets); };
};
diff --git a/regex/README b/regex/README
index ea0a3513..a32197b7 100644
--- a/regex/README+++ b/regex/README
@@ -23,10 +23,8 @@ the longest match among the leftmost matches.
const does_match = regex::test(&re, "Hello Hare, hello Hare.");
fmt::printfln("matched? {}", does_match)!;
- const first_match = regex::find(&re, "Hello Hare, hello Hare.");- match (first_match) {- case void => void;- case let captures: []regex::capture =>+ const captures = regex::find(&re, "Hello Hare, hello Hare.");+ if (len(captures) != 0) { defer regex::free_captures(captures);
// captures[0]: The full matching string.
// captures[1...]: A capture for every capture group.
@@ -35,20 +33,16 @@ the longest match among the leftmost matches.
captures[0].end)!;
};
- const all_matches = regex::findall(&re, "Hello Hare, hello Hare.");- match (all_matches) {- case void => void;- case let matches: [][]regex::capture =>- defer regex::free_matches(matches);- // matches[0]: All captures for the first match.- // matches[0][0]: The full matching string for the first match.- // matches[0][1...]: A capture for every capture group in the- // first match.- for (let i = 0z; i < len(matches); i += 1) {- fmt::printfln("{} ({}, {})", matches[i][0].content,- matches[i][0].start,- matches[i][0].end)!;- };+ const matches = regex::findall(&re, "Hello Hare, hello Hare.");+ defer regex::free_matches(matches);+ // matches[0]: All captures for the first match.+ // matches[0][0]: The full matching string for the first match.+ // matches[0][1...]: A capture for every capture group in the+ // first match.+ for (let i = 0z; i < len(matches); i += 1) {+ fmt::printfln("{} ({}, {})", matches[i][0].content,+ matches[i][0].start,+ matches[i][0].end)!; };
[0]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_04
diff --git a/regex/regex.ha b/regex/regex.ha
index eb29e1ad..71308136 100644
--- a/regex/regex.ha+++ b/regex/regex.ha
@@ -773,16 +773,21 @@ export fn test(re: *regex, string: str) bool = {
// Attempts to match a regular expression against a string and returns the
// longest leftmost match, or void if there is no match.
-export fn find(re: *regex, string: str) (void | []capture) = {+export fn find(re: *regex, string: str) []capture = { let str_idx = -1;
let str_iter = strings::iter(string);
let str_bytesize = 0z;
- return search(re, string, &str_iter, &str_idx, &str_bytesize, true);+ match (search(re, string, &str_iter, &str_idx, &str_bytesize, true)) {+ case let m: []capture =>+ return m;+ case void =>+ return [];+ };};
// Attempts to match a regular expression against a string and returns all
// non-overlapping matches, or void if there are no matches.
-export fn findall(re: *regex, string: str) (void | [][]capture) = {+export fn findall(re: *regex, string: str) [][]capture = { let res: [][]capture = alloc([]);
let str_idx = -1;
let str_iter = strings::iter(string);
@@ -804,9 +809,6 @@ export fn findall(re: *regex, string: str) (void | [][]capture) = {
case void => break;
};
};
- if (len(res) == 0) {- return void;- }; return res;
};
--
2.36.1
[PATCH hare v2 3/3] regex: add replace and rawreplace