-
Notifications
You must be signed in to change notification settings - Fork 0
/
chain.go
44 lines (38 loc) · 1.38 KB
/
chain.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
package repeat
import (
"github.com/flier/gocombine/pkg/pair"
"github.com/flier/gocombine/pkg/parser"
"github.com/flier/gocombine/pkg/parser/combinator"
"github.com/flier/gocombine/pkg/stream"
)
// ChainL1 parses `parser` one or more times separated by `op`.
// The value returned is the one produced
// by the left associative application of the function returned by the parser `op`.
func ChainL1[T stream.Token, O any](parser parser.Func[T, O], op parser.Func[T, func(l, h O) O]) parser.Func[T, O] {
return combinator.Map(
combinator.Pair(parser, Many1(combinator.Pair(op, parser))),
func(p pair.Pair[O, []pair.Pair[func(l, h O) O, O]]) (acc O) {
acc = p.First
for _, v := range p.Second {
acc = v.First(acc, v.Second)
}
return
},
).Expected("chain left1")
}
// ChainR1 parses `p` one or more times separated by `op`.
// The value returned is the one produced
// by the right associative application of the function returned by `op`.
func ChainR1[T stream.Token, O any](parser parser.Func[T, O], op parser.Func[T, func(l, h O) O]) parser.Func[T, O] {
return combinator.Map(
combinator.Pair(Many1(combinator.Pair(parser, op)), parser),
func(p pair.Pair[[]pair.Pair[O, func(l, h O) O], O]) (acc O) {
acc = p.Second
n := len(p.First)
for i := 0; i < n; i++ {
acc = p.First[n-1-i].Second(p.First[n-1-i].First, acc)
}
return
},
).Expected("chain right1")
}