-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlexer.go
147 lines (127 loc) · 3 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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*************************************************************************
* Copyright 2022 Gravwell, Inc. All rights reserved.
* Contact: <[email protected]>
*
* This software may be modified and distributed under the terms of the
* BSD 2-clause license. See the LICENSE file for details.
**************************************************************************/
package main
import (
"fmt"
"strconv"
"strings"
"unicode"
)
func (p *pbpgData) lexcomment(input string) (int, string, error) {
// eat until the end of the line
offset := 0
for r, s := getRune(input, offset); s > 0; r, s = getRune(input, offset) {
offset += s
if r == '\n' {
break
}
}
var token string
if offset > 0 {
token = input[:offset-1]
}
return offset, token, nil
}
func (p *pbpgData) lexcode(input string) (int, string, error) {
// lexCode has to track bracket depth, escaped values, and quoted states
offset := 0
bdepth := 0
quote := false
escape := false
for r, s := getRune(input, offset); s > 0; r, s = getRune(input, offset) {
offset += s
if escape {
escape = false
continue
}
if r == '\\' {
escape = true
continue
}
if quote && r != '"' {
continue
}
switch r {
case '}':
if bdepth == 0 {
offset--
return offset, input[:offset], nil
}
bdepth--
case '{':
bdepth++
case '"':
quote = !quote
}
}
return 0, "", fmt.Errorf("could not extract token")
}
func (p *pbpgData) lexname(input string) (int, string, error) {
offset := countLeadingWhitespace(input)
val := ""
for r, s := getRune(input, offset); s > 0; r, s = getRune(input, offset) {
if unicode.IsLetter(r) {
val += string(r)
offset += s
continue
}
if len(val) == 0 {
return 0, "", fmt.Errorf("could not extract name, got %v", string(r))
}
return offset, val, nil
}
return 0, "", fmt.Errorf("could not extract token")
}
func (p *pbpgData) lexfunctionname(input string) (int, string, error) {
return p.lexname(input)
}
func (p *pbpgData) lexquotedstring(input string) (int, string, error) {
// everything up to the closing quote but no leading or trailing
// whitespace -- interior whitespace is okay
offset := 0
escape := false
for r, s := getRune(input, offset); s > 0; r, s = getRune(input, offset) {
offset += s
if escape {
escape = false
continue
}
if r == '\\' {
escape = true
continue
}
if r == '"' {
offset--
val := input[:offset]
// unescape
val, err := strconv.Unquote(`"` + val + `"`)
if err != nil {
return 0, "", err
}
if strings.TrimSpace(val) != val {
return 0, "", fmt.Errorf("string cannot contain leading or trailing whitespace")
}
return offset, val, nil
}
}
return 0, "", fmt.Errorf("could not extract token")
}
func (p *pbpgData) lextype(input string) (int, string, error) {
offset := 0
for r, s := getRune(input, offset); s > 0; r, s = getRune(input, offset) {
offset += s
if r == '\n' {
break
}
}
var token string
if offset > 0 {
token = input[:offset-1]
}
return offset, token, nil
}