Skip to content

Commit 14bdeb0

Browse files
committed
Keep adjacent replace_all matches reachable
1 parent 56d29b5 commit 14bdeb0

2 files changed

Lines changed: 41 additions & 16 deletions

File tree

vibes/builtins.go

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -552,25 +552,46 @@ func regexReplaceAllWithLimit(re *regexp.Regexp, text string, replacement string
552552
}
553553

554554
func nextRegexReplaceAllSubmatchIndex(re *regexp.Regexp, text string, start int) ([]int, bool) {
555-
windowStart := start
556-
if windowStart > 0 {
557-
windowStart--
555+
loc := re.FindStringSubmatchIndex(text[start:])
556+
if loc == nil {
557+
return nil, false
558+
}
559+
direct := offsetRegexSubmatchIndex(loc, start)
560+
if start == 0 || direct[0] > start {
561+
return direct, true
558562
}
563+
564+
windowStart := start - 1
559565
locs := re.FindAllStringSubmatchIndex(text[windowStart:], 2)
560-
for _, loc := range locs {
561-
absStart := loc[0] + windowStart
562-
if absStart < start {
566+
if len(locs) == 0 {
567+
return nil, false
568+
}
569+
570+
first := offsetRegexSubmatchIndex(locs[0], windowStart)
571+
if first[0] >= start {
572+
return first, true
573+
}
574+
if first[1] > start {
575+
return direct, true
576+
}
577+
if len(locs) < 2 {
578+
return nil, false
579+
}
580+
second := offsetRegexSubmatchIndex(locs[1], windowStart)
581+
if second[0] >= start {
582+
return second, true
583+
}
584+
return nil, false
585+
}
586+
587+
func offsetRegexSubmatchIndex(loc []int, offset int) []int {
588+
abs := make([]int, len(loc))
589+
for i, index := range loc {
590+
if index < 0 {
591+
abs[i] = -1
563592
continue
564593
}
565-
abs := make([]int, len(loc))
566-
for i, index := range loc {
567-
if index < 0 {
568-
abs[i] = -1
569-
continue
570-
}
571-
abs[i] = index + windowStart
572-
}
573-
return abs, true
594+
abs[i] = index + offset
574595
}
575-
return nil, false
596+
return abs
576597
}

vibes/runtime_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1954,6 +1954,7 @@ func TestRegexBuiltins(t *testing.T) {
19541954
match_empty: Regex.match("^", "ID-12"),
19551955
replace_one: Regex.replace("ID-12 ID-34", "ID-[0-9]+", "X"),
19561956
replace_all: Regex.replace_all("ID-12 ID-34", "ID-[0-9]+", "X"),
1957+
replace_all_adjacent: Regex.replace_all("aaaa", "aa", "X"),
19571958
replace_all_anchor: Regex.replace_all("abc", "^", "X"),
19581959
replace_all_boundary: Regex.replace_all("ab", "\\b", "X"),
19591960
replace_all_abutting_empty: Regex.replace_all("aa", "aa|", "X"),
@@ -1987,6 +1988,9 @@ func TestRegexBuiltins(t *testing.T) {
19871988
if !out["replace_all"].Equal(NewString("X X")) {
19881989
t.Fatalf("replace_all mismatch: %v", out["replace_all"])
19891990
}
1991+
if !out["replace_all_adjacent"].Equal(NewString("XX")) {
1992+
t.Fatalf("replace_all_adjacent mismatch: %v", out["replace_all_adjacent"])
1993+
}
19901994
if !out["replace_all_anchor"].Equal(NewString("Xabc")) {
19911995
t.Fatalf("replace_all_anchor mismatch: %v", out["replace_all_anchor"])
19921996
}

0 commit comments

Comments
 (0)