-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsequence.go
118 lines (100 loc) · 3.98 KB
/
sequence.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
package gomme
// Delimited parses and discards the result from the prefix parser, then
// parses the result of the main parser, and finally parses and discards
// the result of the suffix parser.
func Delimited[I Bytes, OP, O, OS any](prefix Parser[I, OP], parser Parser[I, O], suffix Parser[I, OS]) Parser[I, O] {
return func(input I) Result[O, I] {
return Terminated(Preceded(prefix, parser), suffix)(input)
}
}
// Pair applies two parsers and returns a Result containing a pair container holding
// the resulting values.
func Pair[I Bytes, LO, RO any, LP Parser[I, LO], RP Parser[I, RO]](
leftParser LP, rightParser RP,
) Parser[I, PairContainer[LO, RO]] {
return func(input I) Result[PairContainer[LO, RO], I] {
leftResult := leftParser(input)
if leftResult.Err != nil {
return Failure[I, PairContainer[LO, RO]](NewError(input, "Pair"), input)
}
rightResult := rightParser(leftResult.Remaining)
if rightResult.Err != nil {
return Failure[I, PairContainer[LO, RO]](NewError(input, "Pair"), input)
}
return Success(PairContainer[LO, RO]{leftResult.Output, rightResult.Output}, rightResult.Remaining)
}
}
// Preceded parses and discards a result from the prefix parser. It
// then parses a result from the main parser and returns its result.
//
// Preceded is effectively equivalent to applying DiscardAll(prefix),
// and then applying the main parser.
func Preceded[I Bytes, OP, O any](prefix Parser[I, OP], parser Parser[I, O]) Parser[I, O] {
return func(input I) Result[O, I] {
prefixResult := prefix(input)
if prefixResult.Err != nil {
return Failure[I, O](prefixResult.Err, input)
}
result := parser(prefixResult.Remaining)
if result.Err != nil {
return Failure[I, O](result.Err, input)
}
return Success(result.Output, result.Remaining)
}
}
// SeparatedPair applies two separated parsers and returns a Result containing a slice of
// size 2 as its output. The first element of the slice is the result of the left parser,
// and the second element is the result of the right parser. The result of the separator parser
// is discarded.
func SeparatedPair[I Bytes, LO, RO any, S Separator, LP Parser[I, LO], SP Parser[I, S], RP Parser[I, RO]](
leftParser LP, separator SP, rightParser RP,
) Parser[I, PairContainer[LO, RO]] {
return func(input I) Result[PairContainer[LO, RO], I] {
leftResult := leftParser(input)
if leftResult.Err != nil {
return Failure[I, PairContainer[LO, RO]](NewError(input, "SeparatedPair"), input)
}
sepResult := separator(leftResult.Remaining)
if sepResult.Err != nil {
return Failure[I, PairContainer[LO, RO]](NewError(input, "SeparatedPair"), input)
}
rightResult := rightParser(sepResult.Remaining)
if rightResult.Err != nil {
return Failure[I, PairContainer[LO, RO]](NewError(input, "SeparatedPair"), input)
}
return Success(PairContainer[LO, RO]{leftResult.Output, rightResult.Output}, rightResult.Remaining)
}
}
// Sequence applies a sequence of parsers and returns either a
// slice of results or an error if any parser fails.
func Sequence[I Bytes, O any](parsers ...Parser[I, O]) Parser[I, []O] {
return func(input I) Result[[]O, I] {
remaining := input
outputs := make([]O, 0, len(parsers))
for _, parser := range parsers {
res := parser(remaining)
if res.Err != nil {
return Failure[I, []O](res.Err, input)
}
outputs = append(outputs, res.Output)
remaining = res.Remaining
}
return Success(outputs, remaining)
}
}
// Terminated parses a result from the main parser, it then
// parses the result from the suffix parser and discards it; only
// returning the result of the main parser.
func Terminated[I Bytes, O, OS any](parser Parser[I, O], suffix Parser[I, OS]) Parser[I, O] {
return func(input I) Result[O, I] {
result := parser(input)
if result.Err != nil {
return Failure[I, O](result.Err, input)
}
suffixResult := suffix(result.Remaining)
if suffixResult.Err != nil {
return Failure[I, O](suffixResult.Err, input)
}
return Success(result.Output, suffixResult.Remaining)
}
}