forked from cloudflare/circl
-
Notifications
You must be signed in to change notification settings - Fork 1
/
lexer.go
88 lines (81 loc) · 1.35 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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package dsl
import (
"fmt"
"strings"
)
var keywords = map[string]string{
"and": And,
"or": Or,
"not": Not,
}
type Lexer struct {
source string
tokens []Token
start int
curr int
line int
hadError bool
}
func newLexer(source string) Lexer {
return Lexer{
source: source,
tokens: nil,
start: 0,
curr: 0,
line: 1,
hadError: false,
}
}
func (l *Lexer) scanTokens() error {
errMsg := "unexpected character(s): "
for l.curr < len(l.source) {
l.start = l.curr
c := l.source[l.curr]
l.curr++
switch c {
case '(':
l.addToken(LeftParen)
case ')':
l.addToken(RightParen)
case ':':
l.addToken(Colon)
case ' ', '\r', '\t':
case '\n':
l.line++
default:
if isAlphaNumeric(c) {
l.identifier()
} else {
errMsg += fmt.Sprintf("'%s' ", string(c))
l.hadError = true
}
}
}
l.addToken(EOF)
if l.hadError {
return fmt.Errorf(strings.TrimSpace(errMsg))
}
return nil
}
func (l *Lexer) addToken(tokenType string) {
token := Token{
tokenType,
l.source[l.start:l.curr],
l.line,
}
l.tokens = append(l.tokens, token)
}
func (l *Lexer) identifier() {
for l.curr < len(l.source) {
if isAlphaNumeric(l.source[l.curr]) {
l.curr++
} else {
break
}
}
tokenType, ok := keywords[l.source[l.start:l.curr]]
if !ok {
tokenType = Identifier
}
l.addToken(tokenType)
}