|
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
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
// Package parse provides a simple parser combinator library
package parse
// The N struct is a parser result node.
type N struct {
// Match indicates whether the parser succeeded.
Matched bool
// Content contains whatever was matched by the parser.
Content string
// Nodes contains any result nodes by nested parsers.
Nodes []N
}
// Parser function type
// Takes a string and returns a result and the remaining part of the string.
type P func(string) (N, string)
// A sequence of parsers. Matches when all of p match.
func Seq(p ...P) P {
return func(s string) (N, string) {
result := N{Matched: true, Nodes: make([]N, 0, len(p))}
for _, parser := range p {
n, r := parser(s)
result.Nodes = append(result.Nodes, n)
if !n.Matched {
result.Matched = false
break
}
result.Content = result.Content + n.Content
s = r
}
return result, s
}
}
// Matches and returns on the first match of p.
func Any(p ...P) P {
return func(s string) (N, string) {
result := N{Matched: false, Nodes: nil}
for _, parser := range p {
n, r := parser(s)
if n.Matched {
return n, r
}
result.Nodes, s = append(result.Nodes, n), r
}
return result, s
}
}
// Kleene star (zero or more). Always matches.
func K(p P) P {
return func(s string) (N, string) {
result := N{Matched: true, Nodes: nil}
for n, r := p(s); n.Matched; n, r = p(r) {
result.Content = result.Content + n.Content
result.Nodes = append(result.Nodes, n)
s = r
}
return result, s
}
}
// Returns a delegating parser whose delegate can be set on later.
// Useful for recursive definitions.
func Defer() (P, *P) {
var deferred P
return func(s string) (N, string) {
return deferred(s)
}, &deferred
}
// Returns a parser that accepts the specified number of bytes
func Accept(count int) P {
return func(s string) (N, string) {
if len(s) < count {
return N{Matched: false, Content: "", Nodes: nil}, s
}
return N{Matched: true, Content: s[:count], Nodes: nil}, s[count:]
}
}
|