forked from brg-liuwei/godnf
-
Notifications
You must be signed in to change notification settings - Fork 0
/
state.go
244 lines (213 loc) · 5.87 KB
/
state.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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
package godnf
import (
"errors"
)
var leftDelimOfConj, rightDelimOfConj byte = byte('('), byte(')')
var leftDelimOfSet, rightDelimOfSet byte = byte('{'), byte('}')
var separatorOfSet byte = byte(',')
// SetDelimOfConj set global conj delim to left and right
func SetDelimOfConj(left, right rune) {
leftDelimOfConj, rightDelimOfConj = byte(left), byte(right)
}
// GetDelimOfConj returns current global left and right delim of conjunction
// eg: if a right dnf is like (Country in {CN, RU, US}),
// this func will return rune('('), rune(')')
func GetDelimOfConj() (left, right rune) {
return rune(leftDelimOfConj), rune(rightDelimOfConj)
}
// SetDelimOfSet set global set delim to left and right
func SetDelimOfSet(left, right rune) {
leftDelimOfSet, rightDelimOfSet = byte(left), byte(right)
}
// GetDelimOfSet returns current global left and right delim of set
// eg: if a dnf is like (Country in {CN, RU, US}),
// this func will return rune('{'), rune('}')
func GetDelimOfSet() (left, right rune) {
return rune(leftDelimOfSet), rune(rightDelimOfSet)
}
// SetSeparatorOfSet set global separator of set
func SetSeparatorOfSet(sep rune) {
separatorOfSet = byte(sep)
}
// GetSeparatorOfSet returns current global separator of elems in set
// eg: the separator of set elems is rune(',') when a dnf is like (Country in {CN, RU, US})
func GetSeparatorOfSet() rune {
return rune(separatorOfSet)
}
var dnfFmtError error = errors.New("dnf format error")
func skipSpace(s *string, i int) int {
for i < len(*s) {
if (*s)[i] != ' ' {
break
}
i++
}
return i
}
func skipString(s *string, i int) (j int) {
if i >= len(*s) {
return len(*s)
}
for j = i + 1; j < len(*s); j++ {
switch (*s)[j] {
case ' ':
return
case separatorOfSet:
return
case leftDelimOfSet:
return
case rightDelimOfSet:
return
}
}
return
}
func getString(s *string, i int) (subStr string, endIndex int) {
j := skipString(s, i)
ASSERT(i < j)
return string((*s)[i:j]), j
}
func dnfIdxCheck(dnf *string, i int, errmsg string) bool {
if i >= len(*dnf) || i < 0 {
DEBUG(errmsg)
return false
}
return true
}
// DnfCheck check dnf syntax
func DnfCheck(dnf string) error {
return dnfStart(&dnf, skipSpace(&dnf, 0))
}
// start: get leftDelimOfConj, default is '('
func dnfStart(dnf *string, i int) error {
if !dnfIdxCheck(dnf, i, "start dnf idx error") {
return dnfFmtError
}
if (*dnf)[i] != leftDelimOfConj {
DEBUG("dnf start error, dnf[", i, "] =", string((*dnf)[i]))
return dnfFmtError
}
m := make(map[string]bool)
return dnfState1(dnf, skipSpace(dnf, i+1), m)
}
// state1: get key
func dnfState1(dnf *string, i int, m map[string]bool) error {
if !dnfIdxCheck(dnf, i, "dnfState1 check error") {
return dnfFmtError
}
j := skipString(dnf, i)
if j >= len(*dnf) {
DEBUG("state 1 internal error")
return dnfFmtError
}
key := string((*dnf)[i:j])
if _, ok := m[key]; ok {
return errors.New("conjunction key " + key + " duplicate")
}
m[key] = true
return dnfState2(dnf, skipSpace(dnf, j+1), m)
}
// state2: get 'not' or get 'in'
func dnfState2(dnf *string, i int, m map[string]bool) error {
if !dnfIdxCheck(dnf, i, "dnfState2 check error") {
return dnfFmtError
}
if i+3 <= len(*dnf) && string((*dnf)[i:i+3]) == "not" {
return dnfState3(dnf, skipSpace(dnf, i+3), m)
}
if i+2 <= len(*dnf) && string((*dnf)[i:i+2]) == "in" {
return dnfState4(dnf, skipSpace(dnf, i+2), m)
}
DEBUG("state2 internal error")
return dnfFmtError
}
// state3: get 'in'
func dnfState3(dnf *string, i int, m map[string]bool) error {
if !dnfIdxCheck(dnf, i, "dnfState3 check error") {
return dnfFmtError
}
if i+2 <= len(*dnf) && string((*dnf)[i:i+2]) == "in" {
return dnfState4(dnf, skipSpace(dnf, i+2), m)
}
DEBUG("state3 internal error")
return dnfFmtError
}
// state4: get leftDelimOfSet, default is '{'
func dnfState4(dnf *string, i int, m map[string]bool) error {
if !dnfIdxCheck(dnf, i, "dnfState4 check error") {
return dnfFmtError
}
if (*dnf)[i] != leftDelimOfSet {
DEBUG("state4 internal error")
return dnfFmtError
}
return dnfState5(dnf, skipSpace(dnf, i+1), m)
}
// state5: get elem of set
func dnfState5(dnf *string, i int, m map[string]bool) error {
if !dnfIdxCheck(dnf, i, "dnfState5 check error") {
return dnfFmtError
}
j := skipString(dnf, i)
if j >= len(*dnf) {
DEBUG("state5 internal error")
return dnfFmtError
}
// val := string((*dnf)[i:j])
// _ = val
return dnfState6(dnf, skipSpace(dnf, j), m)
}
// state6: get next val(',') or get end of set('}')
func dnfState6(dnf *string, i int, m map[string]bool) error {
if !dnfIdxCheck(dnf, i, "dnfState6 check error") {
return dnfFmtError
}
if (*dnf)[i] == separatorOfSet {
return dnfState7(dnf, skipSpace(dnf, i+1), m)
}
if (*dnf)[i] == rightDelimOfSet {
return dnfState8(dnf, skipSpace(dnf, i+1), m)
}
DEBUG("state6 internal error")
return dnfFmtError
}
// state7: get next val
func dnfState7(dnf *string, i int, m map[string]bool) error {
if !dnfIdxCheck(dnf, i, "dnfState7 check error") {
return dnfFmtError
}
j := skipString(dnf, i)
if j >= len(*dnf) {
DEBUG("state7 internal error")
return dnfFmtError
}
// val := string((*dnf)[i:j])
// _ = val
return dnfState6(dnf, skipSpace(dnf, j), m)
}
// state8: get 'and' or end of this conj(')')
func dnfState8(dnf *string, i int, m map[string]bool) error {
if !dnfIdxCheck(dnf, i, "dnfState8 check error") {
return dnfFmtError
}
if i+3 < len(*dnf) && string((*dnf)[i:i+3]) == "and" {
return dnfState1(dnf, skipSpace(dnf, i+3), m)
}
if (*dnf)[i] == rightDelimOfConj {
return dnfState9(dnf, skipSpace(dnf, i+1), m)
}
DEBUG("state8 internal error")
return dnfFmtError
}
// state9: end of dnf or next conj(get "or")
func dnfState9(dnf *string, i int, m map[string]bool) error {
if i == len(*dnf) {
// accept
return nil
}
if i+2 < len(*dnf) && string((*dnf)[i:i+2]) == "or" {
return dnfStart(dnf, skipSpace(dnf, i+2))
}
DEBUG("state9 internal error")
return dnfFmtError
}