-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathoperators.go
269 lines (237 loc) · 5.84 KB
/
operators.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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
package abnf
import (
"bytes"
"sort"
"unicode/utf8"
)
// Operator represents an ABNF operator.
type Operator func(s []byte, ns Nodes) Nodes
func literal(key string, val []byte, ci bool) Operator {
return func(s []byte, ns Nodes) Nodes {
if len(s) < len(val) {
return ns
}
if !bytes.Equal(val, s[:len(val)]) {
if !ci || !bytes.Equal(toLower(val), toLower(s[:len(val)])) {
return ns
}
}
return append(ns, &Node{
Key: key,
Value: s[:len(val)],
})
}
}
// Literal defines a case-insensitive characters sequence.
func Literal(key string, val []byte) Operator {
return literal(key, val, true)
}
// LiteralCS defines a case-sensitive characters sequence.
func LiteralCS(key string, val []byte) Operator {
return literal(key, val, false)
}
// Range defines a range of alternative numeric values.
func Range(key string, low, high []byte) Operator {
return func(s []byte, ns Nodes) Nodes {
if len(s) < len(low) || bytes.Compare(s[:len(low)], low) < 0 {
return ns
}
var l int
_, size := utf8.DecodeRune(s)
for i := len(high); 0 < i; i-- {
if len(high)-i < size && s[len(high)-i] <= high[i-1] {
l++
} else {
break
}
}
if l == 0 {
return nil
}
return append(ns, &Node{
Key: key,
Value: s[:l],
})
}
}
func alt(key string, fm bool, oprts ...Operator) Operator {
return func(s []byte, ns Nodes) Nodes {
subns := newNodes()
for _, op := range oprts {
subns.clear()
subns = op(s, subns)
for _, sn := range subns {
ns = append(ns, &Node{
Key: key,
Value: s[:len(sn.Value)],
Children: append(newNodes(), sn),
})
}
if len(subns) > 0 && fm {
break
}
}
subns.free()
if len(ns) > 1 {
sort.Sort(nodeSorter(ns))
}
return ns
}
}
// Alt defines a sequence of alternative elements that are separated by a forward slash ("/").
// Created operator will return all matched alternatives.
func Alt(key string, oprts ...Operator) Operator {
return alt(key, false, oprts...)
}
// AltFirst defines a sequence of alternative elements that are separated by a forward slash ("/").
// Created operator will return first matched alternative.
func AltFirst(key string, oprts ...Operator) Operator {
return alt(key, true, oprts...)
}
func concat(key string, all bool, oprts ...Operator) Operator {
return func(s []byte, ns Nodes) Nodes {
if len(oprts) == 0 {
return ns
}
ns = append(ns, &Node{Key: key, Value: s[:0]})
newns := newNodes()
subns := newNodes()
for _, op := range oprts {
newns.clear()
for _, n := range ns {
subns.clear()
subns = op(s[len(n.Value):], subns)
for _, sn := range subns {
var nn *Node
if len(subns) == 1 {
nn = n
nn.Value = s[:len(n.Value)+len(sn.Value)]
nn.Children = append(n.Children, sn)
} else {
nn = &Node{
Key: n.Key,
Value: s[:len(n.Value)+len(sn.Value)],
Children: append(append(newNodes(), n.Children...), sn),
}
}
newns = append(newns, nn)
}
}
if len(newns) > 0 {
ns.clear()
ns = append(ns, newns...)
} else {
ns.clear()
break
}
}
newns.free()
subns.free()
if len(ns) > 1 && !all {
ns[0] = ns.Best()
ns1 := ns[1:]
ns1.clear()
ns = ns[:1]
}
return ns
}
}
// Concat defines a simple, ordered string of values.
// Created operator will return the longest alternative.
func Concat(key string, oprts ...Operator) Operator {
return concat(key, false, oprts...)
}
// ConcatAll defines a simple, ordered string of values.
// Created operator will return all alternatives.
func ConcatAll(key string, oprts ...Operator) Operator {
return concat(key, true, oprts...)
}
// Repeat defines a variable repetition.
func Repeat(key string, min, max uint, op Operator) Operator {
var minp Operator
if min > 0 {
ps := make([]Operator, min)
for i := uint(0); i < min; i++ {
ps[i] = op
}
minp = concat(key, true, ps...)
}
return func(s []byte, ns Nodes) Nodes {
if 0 < max && max < min {
return ns
}
if min == 0 {
ns = append(ns, &Node{Key: key, Value: s[:0]})
} else {
ns = minp(s, ns)
if len(ns) == 0 {
return ns
}
}
if len(s) == 0 {
return ns
}
curns := append(newNodes(), ns...)
newns := newNodes()
subns := newNodes()
var i uint
for i = min; i < max || max == 0; i++ {
newns.clear()
for _, n := range curns {
subns.clear()
subns = op(s[len(n.Value):], subns)
for _, sn := range subns {
var chns Nodes
if len(subns) == 1 {
chns = append(n.Children, sn)
} else {
chns = append(append(newNodes(), n.Children...), sn)
}
newns = append(newns, &Node{
Key: n.Key,
Value: s[:len(n.Value)+len(sn.Value)],
Children: chns,
})
}
}
if len(newns) > 0 && newns.Compare(curns) == 1 {
curns.clear()
curns = append(curns, newns...)
ns = append(ns, newns...)
} else {
break
}
}
curns.free()
newns.free()
subns.free()
if len(ns) > 1 {
sort.Sort(nodeSorter(ns))
}
return ns
}
}
// RepeatN defines a specific repetition.
func RepeatN(key string, n uint, op Operator) Operator {
return Repeat(key, n, n, op)
}
// Repeat0Inf defines a specific repetition from 0 to infinity.
func Repeat0Inf(key string, op Operator) Operator {
return Repeat(key, 0, 0, op)
}
// Repeat1Inf defines a specific repetition from 1 to infinity.
func Repeat1Inf(key string, op Operator) Operator {
return Repeat(key, 1, 0, op)
}
// Optional defines an optional element sequence.
// It is equivalent to repeat 0-1.
func Optional(key string, op Operator) Operator {
return Repeat(key, 0, 1, op)
}
type nodeSorter Nodes
func (ns nodeSorter) Len() int { return len(ns) }
func (ns nodeSorter) Less(i, j int) bool {
return len(ns[i].Value) > len(ns[j].Value) ||
len(ns[i].Children) > len(ns[j].Children)
}
func (ns nodeSorter) Swap(i, j int) { ns[i], ns[j] = ns[j], ns[i] }