forked from si3nloong/go-rsql
-
Notifications
You must be signed in to change notification settings - Fork 0
/
lexer.go
105 lines (95 loc) · 2.2 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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package rsql
import (
"bytes"
"strings"
"github.com/timtadh/lexmachine"
"github.com/timtadh/lexmachine/machines"
)
// types :
const (
Expression = iota
String
Or
And
Numeric
Text
Group
Whitespace
)
type Token struct {
Type int
Value string
Lexeme []byte
TC int
StartLine int
StartColumn int
EndLine int
EndColumn int
}
type defaultTokenLexer struct {
ids map[string]int
lexer *lexmachine.Lexer
}
func newDefaultTokenLexer() *defaultTokenLexer {
return &defaultTokenLexer{
ids: map[string]int{
"whitespace": Whitespace,
"grouping": Group,
"string": String,
"text": Text,
"numeric": Numeric,
"and": And,
"or": Or,
"operator": Expression,
},
}
}
func (l *defaultTokenLexer) addActions(lexer *lexmachine.Lexer) {
b := new(bytes.Buffer)
b.WriteByte('(')
for k := range operators {
b.WriteString(escapeStr(k))
b.WriteByte('|')
}
b.Truncate(b.Len() - 1)
b.WriteByte(')')
lexer.Add([]byte(`\s`), l.token("whitespace"))
lexer.Add([]byte(`\(|\)`), l.token("grouping"))
lexer.Add([]byte(`\"(\\.|[^\"])*\"`), l.token("string"))
lexer.Add([]byte(`\'(\\.|[^\'])*\'`), l.token("string"))
lexer.Add([]byte(`(\,|or)`), l.token("or"))
lexer.Add([]byte(`(\;|and)`), l.token("and"))
lexer.Add([]byte(`(\-)?([0-9]*\.[0-9]+|[0-9]+)`), l.token("numeric"))
lexer.Add([]byte(`[a-zA-Z0-9\_\.\%]+`), l.token("text"))
lexer.Add(b.Bytes(), l.token("operator"))
l.lexer = lexer
}
func (l *defaultTokenLexer) token(name string) lexmachine.Action {
return func(s *lexmachine.Scanner, m *machines.Match) (interface{}, error) {
return &Token{
Type: l.ids[name],
Value: string(m.Bytes),
Lexeme: m.Bytes,
TC: m.TC,
StartLine: m.StartLine,
StartColumn: m.StartColumn,
EndLine: m.EndLine,
EndColumn: m.EndColumn,
}, nil
}
}
func escapeStr(str string) string {
length := len(str)
blr := new(strings.Builder)
for i := 0; i < length; i++ {
if (str[i] >= 'a' && str[i] <= 'z') ||
(str[i] >= 'A' && str[i] <= 'Z') ||
(str[i] >= '0' && str[i] <= '9') {
blr.WriteByte(str[i])
} else {
blr.WriteByte('\\')
blr.WriteByte(str[i])
}
}
return blr.String()
}