-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparse.go
423 lines (360 loc) · 11 KB
/
parse.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
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
package parser
import (
"fmt"
"slices"
"strings"
"unicode"
"github.com/lyrise/sprache-go/internal"
)
// TryParse a single character matching 'predicate'
func RuneFunc(predicate func(rune) bool, description string) Parser[rune] {
return func(input ParserInput) ParserResult[rune] {
if input.IsEnd() {
return NewFailureResult[rune](input, "unexpected end of input", []string{description})
}
if predicate(input.Current()) {
return NewSuccessResult[rune](input.Current(), input.Advance())
}
return NewFailureResult[rune](input, fmt.Sprintf("unexpected %v", input.Current()), []string{description})
}
}
// Parse a single character except those matching 'predicate'
func RuneExceptFunc(predicate func(rune) bool, description string) Parser[rune] {
return RuneFunc(func(c rune) bool {
return !predicate(c)
}, fmt.Sprintf("any character expect %v", description))
}
// Parse a single character c.
func Rune(c rune) Parser[rune] {
return RuneFunc(func(r rune) bool {
return r == c
}, string(c))
}
// Parse a single character except c.
func RuneExcept(c rune) Parser[rune] {
return RuneExceptFunc(func(r rune) bool {
return r == c
}, string(c))
}
// Parse a single character of any in rs
func Runes(rs ...rune) Parser[rune] {
description := strings.Join(internal.Map(rs, internal.RuneToString), "|")
return RuneFunc(func(r rune) bool {
return slices.Contains(rs, r)
}, description)
}
// Parse a single character of any in s
func RunesString(s string) Parser[rune] {
rs := []rune(s)
description := strings.Join(internal.Map(rs, internal.RuneToString), "|")
return RuneFunc(func(r rune) bool {
return slices.Contains(rs, r)
}, description)
}
// Parses a single character except for those in rs
func RunesExcept(rs ...rune) Parser[rune] {
description := strings.Join(internal.Map(rs, internal.RuneToString), "|")
return RuneExceptFunc(func(r rune) bool {
return slices.Contains(rs, r)
}, description)
}
// Parses a single character except for those in s
func RunesStringExcept(s string) Parser[rune] {
rs := []rune(s)
description := strings.Join(internal.Map(rs, internal.RuneToString), "|")
return RuneExceptFunc(func(r rune) bool {
return slices.Contains([]rune(s), r)
}, description)
}
// Parse a single character in a case-insensitive fashion.
func IgnoreCase(c rune) Parser[rune] {
return RuneFunc(func(r rune) bool {
return unicode.ToLower(r) == unicode.ToLower(c)
}, string(c))
}
// Parse a string in a case-insensitive fashion.
func IgnoreCaseString(s string) Parser[[]rune] {
res := Return([]rune{})
for _, r := range s {
res = Concat(res, Once(IgnoreCase(r)))
}
return SetExpectationIfError(res, s)
}
// Parse a string of characters.
func String(s string) Parser[[]rune] {
res := Return([]rune{})
for _, r := range s {
res = Concat(res, Once(Rune(r)))
}
return SetExpectationIfError(res, s)
}
// Parse any character.
func AnyRune() Parser[rune] {
return RuneFunc(func(r rune) bool {
return true
}, "any character")
}
// Parse a whitespace.
func WhiteSpace() Parser[rune] {
return RuneFunc(func(r rune) bool {
return unicode.IsSpace(r)
}, "whitespace")
}
// Parse a digit.
func Digit() Parser[rune] {
return RuneFunc(func(r rune) bool {
return unicode.IsDigit(r)
}, "digit")
}
// Parse a letter.
func Letter() Parser[rune] {
return RuneFunc(func(r rune) bool {
return unicode.IsLetter(r)
}, "letter")
}
// Parse a letter or digit.
func LetterOrDigit() Parser[rune] {
return RuneFunc(func(r rune) bool {
return unicode.IsLetter(r) || unicode.IsDigit(r)
}, "letter or digit")
}
// Parse a lowercase letter.
func Lower() Parser[rune] {
return RuneFunc(func(r rune) bool {
return unicode.IsLower(r)
}, "lowercase letter")
}
// Parse an uppercase letter.
func Upper() Parser[rune] {
return RuneFunc(func(r rune) bool {
return unicode.IsUpper(r)
}, "uppercase letter")
}
// Parse a numeric character.
func Numeric() Parser[rune] {
return RuneFunc(func(r rune) bool {
return unicode.IsNumber(r)
}, "numeric character")
}
// Constructs a parser that will fail if the given parser succeeds,
// and will succeed if the given parser fails. In any case, it won't
// consume any input. It's like a negative look-ahead in regex.
func Not[T any](parser Parser[T]) Parser[T] {
return func(input ParserInput) ParserResult[T] {
r := parser(input)
if !r.Succeeded {
msg := fmt.Sprintf("unexpected %v", strings.Join(r.Expectations, ", "))
return NewFailureResult[T](input, msg, []string{})
}
return NewSuccessResult[T](r.Value, r.Remainder)
}
}
// Parse first, and if successful, then parse second.
func Then[T, U any](first Parser[T], second func(T) Parser[U]) Parser[U] {
return func(input ParserInput) ParserResult[U] {
r := first(input)
return IfSuccess(r, func(r ParserResult[T]) ParserResult[U] {
return second(r.Value)(r.Remainder)
})
}
}
// Parse a stream of elements.
func Many[T any](parser Parser[T]) Parser[[]T] {
return func(input ParserInput) ParserResult[[]T] {
var results []T
remainder := input
for {
r := parser(remainder)
if !r.Succeeded {
break
}
results = append(results, r.Value)
remainder = r.Remainder
}
return NewSuccessResult[[]T](results, remainder)
}
}
// Parse a stream of elements, failing if any element is only partially parsed.
func XMany[T any](parser Parser[T]) Parser[[]T] {
return Then(Many(parser), func(m []T) Parser[[]T] {
return XOr(Once(parser), Return(m))
})
}
// TryParse a stream of elements with at least one item.
func AtLeastOnce[T any](parser Parser[T]) Parser[[]T] {
return Then(Once(parser), func(t1 []T) Parser[[]T] {
return Select(Many(parser), func(ts []T) []T {
return internal.Union(t1, ts)
})
})
}
// TryParse a stream of elements with at least one item. Except the first
func XAtLeastOnce[T any](parser Parser[T]) Parser[[]T] {
return Then(Once(parser), func(t1 []T) Parser[[]T] {
return Select(XMany(parser), func(ts []T) []T {
return internal.Union(t1, ts)
})
})
}
// Parse end-of-input.
func End[T any](parser Parser[T]) Parser[T] {
return func(input ParserInput) ParserResult[T] {
r := parser(input)
return IfSuccess[T](r, func(r ParserResult[T]) ParserResult[T] {
if r.Remainder.IsEnd() {
return r
}
return NewFailureResult[T](input, fmt.Sprintf("unexpected %v", r.Remainder.Current()), []string{"end of input"})
})
}
}
// Take the result of parsing, and project it onto a different domain.
func Select[T any, U any](parser Parser[T], convert func(T) U) Parser[U] {
return Then(parser, func(v T) Parser[U] {
return Return[U](convert(v))
})
}
// Parse the token, embedded in any amount of whitespace characters.
func Token[T any](parser Parser[T]) Parser[T] {
return Then(Many(WhiteSpace()), func(_ []rune) Parser[T] {
return Then(parser, func(v T) Parser[T] {
return Then(Many(WhiteSpace()), func(_ []rune) Parser[T] {
return Return[T](v)
})
})
})
}
// Succeed immediately and return value.
func Return[T any](value T) Parser[T] {
return func(input ParserInput) ParserResult[T] {
return NewSuccessResult[T](value, input)
}
}
// Version of Return with simpler inline syntax.
func ReturnValue[T, U any](parser Parser[T], value U) Parser[U] {
return Select(parser, func(T) U {
return value
})
}
// Convert a stream of characters to a string.
func Text(parser Parser[[]rune]) Parser[string] {
return Select(parser, func(rs []rune) string {
return string(rs)
})
}
// Parse first, if it succeeds, return first, otherwise try second.
func Or[T any](first Parser[T], second Parser[T]) Parser[T] {
return func(input ParserInput) ParserResult[T] {
var fr = first(input)
if !fr.Succeeded {
return IfFailure(second(input), func(sf ParserResult[T]) ParserResult[T] {
return determineBestError(fr, sf)
})
}
if fr.Remainder.Equal(input) {
return IfFailure(second(input), func(sf ParserResult[T]) ParserResult[T] {
return fr
})
}
return fr
}
}
// Parse first, if it succeeds, return first, otherwise try second.
func XOr[T any](first Parser[T], second Parser[T]) Parser[T] {
return func(input ParserInput) ParserResult[T] {
var fr = first(input)
if !fr.Succeeded {
// The 'X' part
if !fr.Remainder.Equal(input) {
return fr
}
return IfFailure(second(input), func(sf ParserResult[T]) ParserResult[T] {
return determineBestError(fr, sf)
})
}
if fr.Remainder.Equal(input) {
return IfFailure(second(input), func(sf ParserResult[T]) ParserResult[T] {
return fr
})
}
return fr
}
}
func determineBestError[T any](firstFailure ParserResult[T], secondFailure ParserResult[T]) ParserResult[T] {
if secondFailure.Remainder.Position() > firstFailure.Remainder.Position() {
return secondFailure
}
if secondFailure.Remainder.Position() == firstFailure.Remainder.Position() {
unionFailure := NewFailureResult[T](
firstFailure.Remainder,
firstFailure.Message,
internal.Union(firstFailure.Expectations, secondFailure.Expectations))
return unionFailure
}
return firstFailure
}
// Names part of the grammar for help with error messages.
func SetExpectationIfError[T any](parser Parser[T], expectation string) Parser[T] {
return func(input ParserInput) ParserResult[T] {
return IfFailure(parser(input), func(f ParserResult[T]) ParserResult[T] {
if f.Remainder.Equal(input) {
return NewFailureResult[T](f.Remainder, f.Message, []string{expectation})
}
return f
})
}
}
// Parse a stream of elements containing only one item.
func Once[T any](parser Parser[T]) Parser[[]T] {
return Select(parser, func(r T) []T {
return []T{r}
})
}
// Concatenate two streams of elements.
func Concat[T any](first, second Parser[[]T]) Parser[[]T] {
return Then(first, func(fr []T) Parser[[]T] {
return Select(second, func(sr []T) []T {
return internal.Union(fr, sr)
})
})
}
// Attempt parsing only if the except parser fails.
func Except[T, U any](parser Parser[T], except Parser[U]) Parser[T] {
return func(input ParserInput) ParserResult[T] {
r := except(input)
if r.Succeeded {
return NewFailureResult[T](input, "Excepted parser succeeded.", []string{"other than the excepted input"})
}
return parser(input)
}
}
// Parse a sequence of items until a terminator is reached.
// Returns the sequence, discarding the terminator.
func Until[T, U any](parser Parser[T], until Parser[U]) Parser[[]T] {
return Then(Many(Except(parser, until)), func(v []T) Parser[[]T] {
return ReturnValue(until, v)
})
}
// Succeed if the parsed value matches predicate.
func Where[T any](parser Parser[T], predicate func(T) bool) Parser[T] {
return func(input ParserInput) ParserResult[T] {
return IfSuccess(parser(input), func(s ParserResult[T]) ParserResult[T] {
if predicate(s.Value) {
return s
}
return NewFailureResult[T](input, fmt.Sprintf("Unexpected %v", s.Value), []string{})
})
}
}
// Monadic combinator Then, adapted for Linq comprehension syntax.
func SelectMany[T, U, V any](parser Parser[T], selector func(T) Parser[U], projector func(T, U) V) Parser[V] {
return Then(parser, func(t T) Parser[V] {
return Select(selector(t), func(u U) V {
return projector(t, u)
})
})
}
// Parse a number.
func Number() Parser[string] {
return Text(AtLeastOnce(Numeric()))
}