in match/optimize.go [135:223]
func concatRepetition(r *syntax.Regexp) (bool, *syntax.Regexp) {
if r.Op != syntax.OpConcat {
// don't iterate sub-expressions if top-level is no OpConcat
return false, r
}
// check if concatenated op is already a repetition
if isConcatRepetition(r) {
return false, r
}
// concatenate repetitions in sub-expressions first
subs := make([]*syntax.Regexp, len(r.Sub))
changed := false
for i, sub := range r.Sub {
changedSub, tmp := concatRepetition(sub)
changed = changed || changedSub
subs[i] = tmp
}
var concat []*syntax.Regexp
lastMerged := -1
for i, j := 0, 1; j < len(subs); i, j = j, j+1 {
if subs[i].Op == syntax.OpRepeat && eqRegex(subs[i].Sub[0], subs[j]) {
r := subs[i]
concat = append(concat,
&syntax.Regexp{
Op: syntax.OpRepeat,
Sub: r.Sub,
Min: r.Min + 1,
Max: r.Max + 1,
Flags: r.Flags,
},
)
lastMerged = j
changed = true
j++
continue
}
if isConcatRepetition(subs[i]) && eqRegex(subs[i].Sub[0], subs[j]) {
r := subs[i]
concat = append(concat,
&syntax.Regexp{
Op: syntax.OpConcat,
Sub: append(r.Sub, r.Sub[0]),
Flags: r.Flags,
},
)
lastMerged = j
changed = true
j++
continue
}
if eqRegex(subs[i], subs[j]) {
r := subs[i]
concat = append(concat,
&syntax.Regexp{
Op: syntax.OpRepeat,
Sub: []*syntax.Regexp{r},
Min: 2,
Max: 2,
Flags: r.Flags,
},
)
lastMerged = j
changed = true
j++
continue
}
concat = append(concat, subs[i])
}
if lastMerged+1 != len(subs) {
concat = append(concat, subs[len(subs)-1])
}
r = &syntax.Regexp{
Op: syntax.OpConcat,
Sub: concat,
Flags: r.Flags,
}
return changed, r
}