-
Notifications
You must be signed in to change notification settings - Fork 35
/
Copy pathregx.go
106 lines (92 loc) · 2.17 KB
/
regx.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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package main
import (
"fmt"
"regexp"
)
// An interface to regexp for acme.
type AcmeRegexp struct {
re *regexp.Regexp
}
func rxcompile(r string) (*AcmeRegexp, error) {
re, err := regexp.Compile("(?m)" + string(r))
if err != nil {
return nil, err
}
return &AcmeRegexp{re}, nil
}
type FRuneReader struct {
buf Texter
q int
eof int
}
type BRuneReader FRuneReader
func NewFRuneReader(b Texter, offset int, eof int) *FRuneReader {
if eof > b.Nc() {
eof = b.Nc()
}
if eof < 0 {
eof = b.Nc()
}
return &FRuneReader{b, offset, eof}
}
func NewBRuneReader(b Texter, offset int) *BRuneReader {
frr := NewFRuneReader(b, offset, 0)
frr.q = offset - 1
return (*BRuneReader)(frr)
}
func (frr *FRuneReader) ReadRune() (r rune, size int, err error) {
if frr.q >= frr.eof {
return 0, 0, fmt.Errorf("end of buffer")
}
rr := frr.buf.ReadC(frr.q)
frr.q++
return rr, 1, nil
}
func (brr *BRuneReader) ReadRune() (r rune, size int, err error) {
if brr.q < 0 {
return 0, 0, fmt.Errorf("end of buffer")
}
rr := brr.buf.ReadC(brr.q)
brr.q--
return rr, 1, nil
}
// works on Text if present, rune otherwise
func (re *AcmeRegexp) rxexecute(t Texter, r []rune, startp int, eof int, nmatch int) (rp RangeSet) {
var source Texter
if t != nil {
source = t
} else {
source = &TextBuffer{0, 0, r}
}
rngs := RangeSet([]Range{})
for len(rngs) < nmatch {
reader := NewFRuneReader(source, int(startp), int(eof))
locs := re.re.FindReaderSubmatchIndex(reader)
if locs == nil {
return rngs
}
for i := 0; i < len(locs); i += 2 {
rng := Range{locs[i] + startp, locs[i+1] + startp}
rngs = append(rngs, rng)
}
startp += locs[1]
}
return rngs
}
func (re *AcmeRegexp) rxbexecute(t Texter, startp int, nmatch int) (rp RangeSet) {
source := t
rngs := RangeSet([]Range{})
for startp >= 0 && len(rngs) < nmatch {
reader := NewBRuneReader(source, int(startp))
locs := re.re.FindReaderSubmatchIndex(reader)
if locs == nil {
return rngs
}
for i := 0; i < len(locs); i += 2 {
rng := Range{startp - locs[i+1], startp - locs[i]}
rngs = append(rngs, rng)
}
startp = startp - locs[1] //TODO(flux): Does this follow "end" semantics, or do I need loc[0]-1
}
return rngs
}