Newer
Older
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package gqlex
import (
"strings"
"unicode"
)
const (
leftCurl = "{"
rightCurl = "}"
)
// stateFn represents the state of the scanner as a function that
// returns the next state.
type stateFn func(*lexer) stateFn
func lexText(l *lexer) stateFn {
for {
if strings.HasPrefix(l.input[l.pos:], leftCurl) {
if l.pos > l.start {
l.emit(itemText)
}
return lexLeftCurl
}
if strings.HasPrefix(l.input[l.pos:], rightCurl) {
return l.errorf("Too many right brackets")
}
if l.next() == EOF {
break
}
}
// Correctly reached EOF.
if l.pos > l.start {
l.emit(itemText)
}
l.emit(itemEOF)
return nil // Stop the run loop.
}
func lexLeftCurl(l *lexer) stateFn {
l.pos += len(leftCurl)
l.depth += 1
l.emit(itemLeftCurl)
return lexInside(l)
}
func lexRightCurl(l *lexer) stateFn {
l.pos += len(rightCurl)
l.depth -= 1
l.emit(itemRightCurl)
if l.depth == 0 {
return lexText
} else {
return lexInside
}
}
func lexInside(l *lexer) stateFn {
for {
if strings.HasPrefix(l.input[l.pos:], rightCurl) {
return lexRightCurl
}
if strings.HasPrefix(l.input[l.pos:], leftCurl) {
return lexLeftCurl
}
switch r := l.next(); {
case r == EOF:
return l.errorf("unclosed action")
case isSpace(r) || isEndOfLine(r):
l.ignore()
case isAlphaNumeric(r):
l.backup()
return lexIdentifier
}
}
}
func lexIdentifier(l *lexer) stateFn {
Loop:
for {
switch r := l.next(); {
case isAlphaNumeric(r):
// absorb.
default:
l.backup()
l.emit(itemIdentifier)
break Loop
}
}
return lexInside
}
func isSpace(r rune) bool {
return r == ' ' || r == '\t'
}
func isEndOfLine(r rune) bool {
return r == '\r' || r == '\n'
}
func isAlphaNumeric(r rune) bool {
return r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r)
}