-
Notifications
You must be signed in to change notification settings - Fork 2
/
rune.go
58 lines (48 loc) · 1.4 KB
/
rune.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
package parse
import (
"strings"
"unicode"
)
// Rune matches a single rune.
func Rune(r rune) Parser[string] {
return stringParser{
Match: string(r),
}
}
type runeWhereParser struct {
F func(r rune) bool
}
func (p runeWhereParser) Parse(in *Input) (match string, ok bool, err error) {
match, ok = in.Peek(1)
if !ok {
return
}
ok = p.F(rune(match[0]))
if !ok {
return
}
in.Take(1)
return
}
// RuneWhere matches a single rune using the given predicate function.
func RuneWhere(predicate func(r rune) bool) Parser[string] {
return runeWhereParser{
F: predicate,
}
}
// RuneIn matches a single rune when the rune is in the string s.
func RuneIn(s string) Parser[string] {
return RuneWhere(func(r rune) bool { return strings.Contains(s, string(r)) })
}
// RuneNotIn matches a single rune when the rune is not in the string s.
func RuneNotIn(s string) Parser[string] {
return RuneWhere(func(r rune) bool { return !strings.Contains(s, string(r)) })
}
// RuneInRanges matches a single rune when the rune is withig one of the given Unicode ranges.
func RuneInRanges(ranges ...*unicode.RangeTable) Parser[string] {
return RuneWhere(func(r rune) bool { return unicode.IsOneOf(ranges, r) })
}
// AnyRune matches any single rune.
var AnyRune = RuneWhere(func(r rune) bool { return true })
// Letter returns a parser which accepts a rune within the Letter Unicode range.
var Letter = RuneInRanges(unicode.Letter)