-
Notifications
You must be signed in to change notification settings - Fork 0
/
charmRequire.go
69 lines (62 loc) · 1.28 KB
/
charmRequire.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
package charm
import (
"fmt"
"strconv"
)
// implements error
type InvalidRune rune
func (e InvalidRune) Error() string {
var name string
switch q := rune(e); q {
case ' ':
name = "<space>"
case '\n':
name = "<newline>"
case '\t':
name = "<tab>"
case Eof:
name = "<end of file>"
default:
if strconv.IsPrint(q) {
name = strconv.QuoteRune(q)
} else {
name = "0x" + strconv.FormatInt(int64(q), 16)
}
}
return fmt.Sprintf("invalid rune: %s", name)
}
// the next rune will return unhandled
func UnhandledNext() State {
return Statement("unhandled next", func(r rune) (_ State) {
return
})
}
// zero or more of the runes must pass the filter
func Optional(filter func(r rune) bool) State {
return Self("optional", func(self State, r rune) (ret State) {
if filter(r) {
ret = self
}
return
})
}
// ensure the next rune passes the filter
func Require(filter func(r rune) bool) State {
return Statement("require", func(r rune) (ret State) {
if !filter(r) {
ret = Error(InvalidRune(r))
}
return
})
}
// one or more of the runes must pass the filter
func AtleastOne(filter func(r rune) bool) State {
return Statement("several", func(r rune) (ret State) {
if filter(r) {
ret = Optional(filter)
} else {
ret = Error(InvalidRune(r))
}
return
})
}