-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathcompiledmatch.go
53 lines (47 loc) · 1.31 KB
/
compiledmatch.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package yarex
import "sync"
// IntStackPool is accessed by compiled matchers to reuse int stacks.
// Do not use this for any other purposes.
var IntStackPool = sync.Pool{
New: func() interface{} {
b := make([]int, 256)
return &b
},
}
var compiledRegexps = map[string]*Regexp{}
func RegisterCompiledRegexp(s string, h bool, m int, f func(int, MatchContext, int, func(MatchContext)) bool) bool {
compiledRegexps[s] = &Regexp{s, &compiledExecer{f, h, m}}
return true
}
type compiledExecer struct {
fun func(int, MatchContext, int, func(MatchContext)) bool
headOnly bool
minReq int
}
func (exe *compiledExecer) exec(str string, pos int, onSuccess func(MatchContext)) bool {
headOnly := exe.headOnly
minReq := exe.minReq
if headOnly && pos != 0 {
return false
}
if minReq > len(str)-pos {
return false
}
stack := *(opStackPool.Get().(*[]opStackFrame))
defer func() { opStackPool.Put(&stack) }()
getter := func() []opStackFrame { return stack }
setter := func(s []opStackFrame) { stack = s }
ctx0 := makeOpMatchContext(&str, &getter, &setter)
if exe.fun(0, ctx0.Push(ContextKey{'c', 0}, pos), pos, onSuccess) {
return true
}
if headOnly {
return false
}
for i := pos + 1; minReq <= len(str)-i; i++ {
if exe.fun(0, ctx0.Push(ContextKey{'c', 0}, i), i, onSuccess) {
return true
}
}
return false
}