-
Notifications
You must be signed in to change notification settings - Fork 5
/
reference_scanner.go
84 lines (68 loc) · 1.46 KB
/
reference_scanner.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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package reference
import (
"bufio"
"io"
"unicode"
)
var zeroRune = rune(0)
// scanner represents a lexical scanner.
type scanner struct {
r *bufio.Reader
}
// newScanner returns a new instance of scanner.
func newScanner(r io.Reader) *scanner {
return &scanner{r: bufio.NewReader(r)}
}
// read reads the next rune from the bufferred reader.
// Returns the rune(0) if an error occurs (or io.EOF is returned).
func (s *scanner) read() rune {
ch, _, err := s.r.ReadRune()
if err != nil {
return zeroRune
}
return ch
}
// unread places the previously read rune back on the reader.
func (s *scanner) unread() { _ = s.r.UnreadRune() }
// Scan extract token from characters
func (s *scanner) scan() (token, string) {
ch := s.read()
switch ch {
case zeroRune:
return eof, ""
case ':':
return colon, string(ch)
case '~':
return tilde, string(ch)
case '^':
return caret, string(ch)
case '.':
return dot, string(ch)
case '/':
return slash, string(ch)
}
if unicode.IsSpace(ch) {
return space, string(ch)
}
if unicode.IsControl(ch) {
return control, string(ch)
}
if unicode.IsNumber(ch) {
s.unread()
return s.scanNumber()
}
return char, string(ch)
}
// scanNumber return token according to string type
func (s *scanner) scanNumber() (token, string) {
var data string
for c := s.read(); c != zeroRune; c = s.read() {
if unicode.IsNumber(c) {
data += string(c)
} else {
s.unread()
return number, data
}
}
return number, data
}