-
Notifications
You must be signed in to change notification settings - Fork 271
/
lexer.go
70 lines (58 loc) · 1.06 KB
/
lexer.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
package cli53
import (
"fmt"
"strings"
"unicode/utf8"
)
type lexer struct {
input string
start int
pos int
width int
}
const eof = -1
func lex(input string) *lexer {
l := &lexer{input: input}
return l
}
func (l *lexer) emit() string {
ret := l.input[l.start:l.pos]
l.start = l.pos
return ret
}
func (l *lexer) accept(valid string) bool {
if strings.IndexRune(valid, l.next()) >= 0 {
l.emit()
return true
}
l.backup()
return false
}
func (l *lexer) acceptAny() string {
l.next()
return l.emit()
}
func (l *lexer) acceptRun(pred func(rune) bool) string {
for pred(l.next()) {
}
l.backup()
return l.emit()
}
func (l *lexer) next() (rune rune) {
if l.pos >= len(l.input) {
l.width = 0
return eof
}
rune, l.width = utf8.DecodeRuneInString(l.input[l.pos:])
l.pos += l.width
return rune
}
func (l *lexer) backup() {
l.pos -= l.width
}
func (l *lexer) eof() bool {
return l.pos >= len(l.input)
}
func (l *lexer) Error(msg string) error {
return fmt.Errorf("%s: %s[%s]%s", msg, l.input[0:l.start], l.input[l.start:l.pos], l.input[l.pos:])
}