rgviz 0.2 → 0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/rgviz/lexer.rb +605 -0
- data/lib/rgviz/nodes.rb +437 -0
- data/lib/rgviz/parser.rb +403 -0
- data/lib/rgviz/token.rb +83 -0
- data/lib/rgviz/visitor.rb +18 -0
- metadata +8 -3
data/lib/rgviz/lexer.rb
ADDED
@@ -0,0 +1,605 @@
|
|
1
|
+
module Rgviz
|
2
|
+
class Lexer
|
3
|
+
def initialize(str)
|
4
|
+
@str = str.chars.to_a
|
5
|
+
@len = @str.length
|
6
|
+
@token = Token.new
|
7
|
+
@p = 0
|
8
|
+
end
|
9
|
+
|
10
|
+
def next_token
|
11
|
+
while true
|
12
|
+
@token.start = @p
|
13
|
+
@token.string = nil
|
14
|
+
|
15
|
+
case c
|
16
|
+
when nil
|
17
|
+
@token.value = Token::EOF
|
18
|
+
return @token
|
19
|
+
when ' ', "\n", "\r", "\t"
|
20
|
+
@p += 1
|
21
|
+
next
|
22
|
+
when '`', '"', "'"
|
23
|
+
ending = c
|
24
|
+
while c! != ending && c != nil
|
25
|
+
end
|
26
|
+
raise ParseException.new "Unmatched #{char}" if c != ending
|
27
|
+
@p += 1
|
28
|
+
@token.value = ending == '`' ? Token::ID : Token::STRING
|
29
|
+
@token.string = @str[@token.start + 1 ... @p - 1].join
|
30
|
+
return @token
|
31
|
+
when '0' .. '9'
|
32
|
+
found_dot = false
|
33
|
+
while true
|
34
|
+
case c!
|
35
|
+
when '0' .. '9'
|
36
|
+
next
|
37
|
+
when '.'
|
38
|
+
break if found_dot
|
39
|
+
found_dot = true
|
40
|
+
next
|
41
|
+
else
|
42
|
+
break
|
43
|
+
end
|
44
|
+
end
|
45
|
+
if found_dot
|
46
|
+
@token.value = Token::DECIMAL
|
47
|
+
@token.number = @str[@token.start ... @p].join.to_f
|
48
|
+
else
|
49
|
+
@token.value = Token::INTEGER
|
50
|
+
@token.number = @str[@token.start ... @p].join.to_i
|
51
|
+
end
|
52
|
+
return @token
|
53
|
+
when '.'
|
54
|
+
while true
|
55
|
+
case c!
|
56
|
+
when '0' .. '9'
|
57
|
+
next
|
58
|
+
else
|
59
|
+
break
|
60
|
+
end
|
61
|
+
end
|
62
|
+
@token.value = Token::DECIMAL
|
63
|
+
@token.number = @str[@token.start ... @p].join.to_f
|
64
|
+
return @token
|
65
|
+
when '+'; return keyword! Token::PLUS
|
66
|
+
when '-'; return keyword! Token::MINUS
|
67
|
+
when '*'; return keyword! Token::STAR
|
68
|
+
when '/'; return keyword! Token::SLASH
|
69
|
+
when ','; return keyword! Token::COMMA
|
70
|
+
when '('; return keyword! Token::LPAREN
|
71
|
+
when ')'; return keyword! Token::RPAREN
|
72
|
+
when '='; return keyword! Token::EQ
|
73
|
+
when '!';
|
74
|
+
raise ParseException.new "Unexpected character '!'" if c! != '='
|
75
|
+
return keyword! Token::NEQ
|
76
|
+
when '<';
|
77
|
+
case c!
|
78
|
+
when '='
|
79
|
+
@p += 1
|
80
|
+
@token.value = Token::LTE
|
81
|
+
return @token
|
82
|
+
when '>'
|
83
|
+
@p += 1
|
84
|
+
@token.value = Token::NEQ
|
85
|
+
return @token
|
86
|
+
else
|
87
|
+
@token.value = Token::LT
|
88
|
+
return @token
|
89
|
+
end
|
90
|
+
when '>';
|
91
|
+
if c! == '='
|
92
|
+
@p += 1
|
93
|
+
@token.value = Token::GTE
|
94
|
+
return @token
|
95
|
+
end
|
96
|
+
@token.value = Token::GT
|
97
|
+
return @token
|
98
|
+
when 'a', 'A'
|
99
|
+
case c!
|
100
|
+
when 'n', 'N'
|
101
|
+
case c! when 'd', 'D'
|
102
|
+
return keyword Token::And if end_of_identifier!
|
103
|
+
end
|
104
|
+
when 's', 'S'
|
105
|
+
case c! when 'c', 'C'
|
106
|
+
return keyword Token::Asc if end_of_identifier!
|
107
|
+
end
|
108
|
+
when 'v', 'V'
|
109
|
+
case c! when 'g', 'G'
|
110
|
+
return keyword Token::Avg if end_of_identifier!
|
111
|
+
end
|
112
|
+
end
|
113
|
+
when 'b', 'B'
|
114
|
+
case c! when 'y', 'Y'
|
115
|
+
return keyword Token::By if end_of_identifier!
|
116
|
+
end
|
117
|
+
when 'c', 'C'
|
118
|
+
case c! when 'o', 'O'
|
119
|
+
case c!
|
120
|
+
when 'n', 'N'
|
121
|
+
case c! when 't', 'T'
|
122
|
+
case c! when 'a', 'A'
|
123
|
+
case c! when 'i', 'I'
|
124
|
+
case c! when 'n', 'N'
|
125
|
+
case c! when 's', 'S'
|
126
|
+
return keyword Token::Contains if end_of_identifier!
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
when 'u', 'U'
|
133
|
+
case c! when 'n', 'N'
|
134
|
+
case c! when 't', 'T'
|
135
|
+
return keyword Token::Count if end_of_identifier!
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
when 'd', 'D'
|
141
|
+
case c!
|
142
|
+
when 'a', 'A'
|
143
|
+
case c!
|
144
|
+
when 't', 'T'
|
145
|
+
case c! when 'e', 'E'
|
146
|
+
return keyword Token::Date if end_of_identifier!
|
147
|
+
case c
|
148
|
+
when 'd', 'D'
|
149
|
+
case c! when 'i', 'I'
|
150
|
+
case c! when 'f', 'F'
|
151
|
+
case c! when 'f', 'F'
|
152
|
+
return keyword Token::DateDiff if end_of_identifier!
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
when 't', 'T'
|
157
|
+
case c! when 'i', 'I'
|
158
|
+
case c! when 'm', 'M'
|
159
|
+
case c! when 'e', 'E'
|
160
|
+
return keyword Token::DateTime if end_of_identifier!
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
when 'y', 'Y'
|
167
|
+
return keyword Token::Day if end_of_identifier!
|
168
|
+
case c when 'o', 'O'
|
169
|
+
case c! when 'f', 'F'
|
170
|
+
case c! when 'w', 'W'
|
171
|
+
case c! when 'e', 'E'
|
172
|
+
case c! when 'e', 'E'
|
173
|
+
case c! when 'k', 'K'
|
174
|
+
return keyword Token::DayOfWeek if end_of_identifier!
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
when 'e', 'E'
|
183
|
+
case c! when 's', 'S'
|
184
|
+
case c! when 'c', 'C'
|
185
|
+
return keyword Token::Desc if end_of_identifier!
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
when 'e', 'E'
|
190
|
+
case c! when 'n', 'N'
|
191
|
+
case c! when 'd', 'D'
|
192
|
+
case c! when 's', 'S'
|
193
|
+
return keyword Token::Ends if end_of_identifier!
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
when 'f', 'F'
|
198
|
+
case c!
|
199
|
+
when 'a', 'A'
|
200
|
+
case c! when 'l', 'L'
|
201
|
+
case c! when 's', 'S'
|
202
|
+
case c! when 'e', 'E'
|
203
|
+
return keyword Token::False if end_of_identifier!
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
when 'o', 'O'
|
208
|
+
case c! when 'r', 'R'
|
209
|
+
case c! when 'm', 'M'
|
210
|
+
case c! when 'a', 'A'
|
211
|
+
case c! when 't', 'T'
|
212
|
+
return keyword Token::Format if end_of_identifier!
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
when 'g', 'G'
|
219
|
+
case c! when 'r', 'R'
|
220
|
+
case c! when 'o', 'O'
|
221
|
+
case c! when 'u', 'U'
|
222
|
+
case c! when 'p', 'P'
|
223
|
+
return keyword Token::Group if end_of_identifier!
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
when 'h', 'H'
|
229
|
+
case c! when 'o', 'O'
|
230
|
+
case c! when 'u', 'U'
|
231
|
+
case c! when 'r', 'R'
|
232
|
+
return keyword Token::Hour if end_of_identifier!
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
when 'i', 'I'
|
237
|
+
case c! when 's', 'S'
|
238
|
+
return keyword Token::Is if end_of_identifier!
|
239
|
+
end
|
240
|
+
when 'l', 'L'
|
241
|
+
case c!
|
242
|
+
when 'a', 'A'
|
243
|
+
case c! when 'b', 'B'
|
244
|
+
case c! when 'e', 'E'
|
245
|
+
case c! when 'l', 'L'
|
246
|
+
return keyword Token::Label if end_of_identifier!
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
when 'i', 'I'
|
251
|
+
case c!
|
252
|
+
when 'k', 'K'
|
253
|
+
case c! when 'e', 'E'
|
254
|
+
return keyword Token::Like if end_of_identifier!
|
255
|
+
end
|
256
|
+
when 'm', 'M'
|
257
|
+
case c! when 'i', 'I'
|
258
|
+
case c! when 't', 'T'
|
259
|
+
return keyword Token::Limit if end_of_identifier!
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
when 'o', 'O'
|
264
|
+
case c! when 'w', 'W'
|
265
|
+
case c! when 'e', 'E'
|
266
|
+
case c! when 'r', 'R'
|
267
|
+
return keyword Token::Lower if end_of_identifier!
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
when 'm', 'M'
|
273
|
+
case c!
|
274
|
+
when 'a', 'A'
|
275
|
+
case c!
|
276
|
+
when 't', 'T'
|
277
|
+
case c! when 'c', 'C'
|
278
|
+
case c! when 'h', 'H'
|
279
|
+
case c! when 'e', 'E'
|
280
|
+
case c! when 's', 'S'
|
281
|
+
return keyword Token::Matches if end_of_identifier!
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
when 'x', 'X'
|
287
|
+
return keyword Token::Max if end_of_identifier!
|
288
|
+
end
|
289
|
+
when 'i', 'I'
|
290
|
+
case c! when 'l', 'L'
|
291
|
+
case c! when 'l', 'L'
|
292
|
+
case c! when 'i', 'I'
|
293
|
+
case c! when 's', 'S'
|
294
|
+
case c! when 'e', 'E'
|
295
|
+
case c! when 'c', 'C'
|
296
|
+
case c! when 'o', 'O'
|
297
|
+
case c! when 'n', 'N'
|
298
|
+
case c! when 'd', 'D'
|
299
|
+
return keyword Token::Millisecond if end_of_identifier!
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
308
|
+
when 'n', 'N'
|
309
|
+
return keyword Token::Min if end_of_identifier!
|
310
|
+
case c when 'u', 'U'
|
311
|
+
case c! when 't', 'T'
|
312
|
+
case c! when 'e', 'E'
|
313
|
+
return keyword Token::Minute if end_of_identifier!
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
when 'o', 'O'
|
319
|
+
case c! when 'n', 'N'
|
320
|
+
case c! when 't', 'T'
|
321
|
+
case c! when 'h', 'H'
|
322
|
+
return keyword Token::Month if end_of_identifier!
|
323
|
+
end
|
324
|
+
end
|
325
|
+
end
|
326
|
+
end
|
327
|
+
when 'n', 'N'
|
328
|
+
case c!
|
329
|
+
when 'o', 'O'
|
330
|
+
case c!
|
331
|
+
when 't', 'T'
|
332
|
+
return keyword Token::Not if end_of_identifier!
|
333
|
+
when 'w', 'W'
|
334
|
+
return keyword Token::Now if end_of_identifier!
|
335
|
+
when '_'
|
336
|
+
case c!
|
337
|
+
when 'f', 'F'
|
338
|
+
case c! when 'o', 'O'
|
339
|
+
case c! when 'r', 'R'
|
340
|
+
case c! when 'm', 'M'
|
341
|
+
case c! when 'a', 'A'
|
342
|
+
case c! when 't', 'T'
|
343
|
+
return keyword Token::NoFormat if end_of_identifier!
|
344
|
+
end
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|
349
|
+
when 'v', 'V'
|
350
|
+
case c! when 'a', 'A'
|
351
|
+
case c! when 'l', 'L'
|
352
|
+
case c! when 'u', 'U'
|
353
|
+
case c! when 'e', 'E'
|
354
|
+
case c! when 's', 'S'
|
355
|
+
return keyword Token::NoValues if end_of_identifier!
|
356
|
+
end
|
357
|
+
end
|
358
|
+
end
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|
362
|
+
end
|
363
|
+
when 'u', 'U'
|
364
|
+
case c! when 'l', 'L'
|
365
|
+
case c! when 'l', 'L'
|
366
|
+
return keyword Token::Null if end_of_identifier!
|
367
|
+
end
|
368
|
+
end
|
369
|
+
end
|
370
|
+
when 'o', 'O'
|
371
|
+
case c!
|
372
|
+
when 'f', 'F'
|
373
|
+
case c! when 'f', 'F'
|
374
|
+
case c! when 's', 'S'
|
375
|
+
case c! when 'e', 'E'
|
376
|
+
case c! when 't', 'T'
|
377
|
+
return keyword Token::Offset if end_of_identifier!
|
378
|
+
end
|
379
|
+
end
|
380
|
+
end
|
381
|
+
end
|
382
|
+
when 'p', 'P'
|
383
|
+
case c! when 't', 'T'
|
384
|
+
case c! when 'i', 'I'
|
385
|
+
case c! when 'o', 'O'
|
386
|
+
case c! when 'n', 'N'
|
387
|
+
case c! when 's', 'S'
|
388
|
+
return keyword Token::Options if end_of_identifier!
|
389
|
+
end
|
390
|
+
end
|
391
|
+
end
|
392
|
+
end
|
393
|
+
end
|
394
|
+
when 'r', 'R'
|
395
|
+
return keyword Token::Or if end_of_identifier!
|
396
|
+
case c when 'd', 'D'
|
397
|
+
case c! when 'e', 'E'
|
398
|
+
case c! when 'r', 'R'
|
399
|
+
return keyword Token::Order if end_of_identifier!
|
400
|
+
end
|
401
|
+
end
|
402
|
+
end
|
403
|
+
end
|
404
|
+
when 'p', 'P'
|
405
|
+
case c! when 'i', 'I'
|
406
|
+
case c! when 'v', 'V'
|
407
|
+
case c! when 'o', 'O'
|
408
|
+
case c! when 't', 'T'
|
409
|
+
return keyword Token::Pivot if end_of_identifier!
|
410
|
+
end
|
411
|
+
end
|
412
|
+
end
|
413
|
+
end
|
414
|
+
when 'q', 'Q'
|
415
|
+
case c! when 'u', 'U'
|
416
|
+
case c! when 'a', 'A'
|
417
|
+
case c! when 'r', 'R'
|
418
|
+
case c! when 't', 'T'
|
419
|
+
case c! when 'e', 'E'
|
420
|
+
case c! when 'r', 'R'
|
421
|
+
return keyword Token::Quarter if end_of_identifier!
|
422
|
+
end
|
423
|
+
end
|
424
|
+
end
|
425
|
+
end
|
426
|
+
end
|
427
|
+
end
|
428
|
+
when 's', 'S'
|
429
|
+
case c!
|
430
|
+
when 'e', 'E'
|
431
|
+
case c!
|
432
|
+
when 'c', 'C'
|
433
|
+
case c! when 'o', 'O'
|
434
|
+
case c! when 'n', 'N'
|
435
|
+
case c! when 'd', 'D'
|
436
|
+
return keyword Token::Second if end_of_identifier!
|
437
|
+
end
|
438
|
+
end
|
439
|
+
end
|
440
|
+
when 'l', 'L'
|
441
|
+
case c! when 'e', 'E'
|
442
|
+
case c! when 'c', 'C'
|
443
|
+
case c! when 't', 'T'
|
444
|
+
return keyword Token::Select if end_of_identifier!
|
445
|
+
end
|
446
|
+
end
|
447
|
+
end
|
448
|
+
end
|
449
|
+
when 't', 'T'
|
450
|
+
case c! when 'a', 'A'
|
451
|
+
case c! when 'r', 'R'
|
452
|
+
case c! when 't', 'T'
|
453
|
+
case c! when 's', 'S'
|
454
|
+
return keyword Token::Starts if end_of_identifier!
|
455
|
+
end
|
456
|
+
end
|
457
|
+
end
|
458
|
+
end
|
459
|
+
when 'u', 'U'
|
460
|
+
case c! when 'm', 'M'
|
461
|
+
return keyword Token::Sum if end_of_identifier!
|
462
|
+
end
|
463
|
+
end
|
464
|
+
when 't', 'T'
|
465
|
+
case c!
|
466
|
+
when 'i', 'I'
|
467
|
+
case c! when 'm', 'M'
|
468
|
+
case c! when 'e', 'E'
|
469
|
+
case c!
|
470
|
+
when 'o', 'O'
|
471
|
+
case c! when 'f', 'F'
|
472
|
+
case c! when 'd', 'D'
|
473
|
+
case c! when 'a', 'A'
|
474
|
+
case c! when 'y', 'Y'
|
475
|
+
return keyword Token::TimeOfDay if end_of_identifier!
|
476
|
+
end
|
477
|
+
end
|
478
|
+
end
|
479
|
+
end
|
480
|
+
when 's', 'S'
|
481
|
+
case c! when 't', 'T'
|
482
|
+
case c! when 'a', 'A'
|
483
|
+
case c! when 'm', 'M'
|
484
|
+
case c! when 'p', 'P'
|
485
|
+
return keyword Token::Timestamp if end_of_identifier!
|
486
|
+
end
|
487
|
+
end
|
488
|
+
end
|
489
|
+
end
|
490
|
+
end
|
491
|
+
end
|
492
|
+
end
|
493
|
+
when 'o', 'O'
|
494
|
+
case c! when 'd', 'D'
|
495
|
+
case c! when 'a', 'A'
|
496
|
+
case c! when 't', 'T'
|
497
|
+
case c! when 'e', 'E'
|
498
|
+
return keyword Token::ToDate if end_of_identifier!
|
499
|
+
end
|
500
|
+
end
|
501
|
+
end
|
502
|
+
end
|
503
|
+
when 'r', 'R'
|
504
|
+
case c! when 'u', 'U'
|
505
|
+
case c! when 'e', 'E'
|
506
|
+
return keyword Token::True if end_of_identifier!
|
507
|
+
end
|
508
|
+
end
|
509
|
+
end
|
510
|
+
when 'u', 'U'
|
511
|
+
case c! when 'p', 'P'
|
512
|
+
case c! when 'p', 'P'
|
513
|
+
case c! when 'e', 'E'
|
514
|
+
case c! when 'r', 'R'
|
515
|
+
return keyword Token::Upper if end_of_identifier!
|
516
|
+
end
|
517
|
+
end
|
518
|
+
end
|
519
|
+
end
|
520
|
+
when 'w', 'W'
|
521
|
+
case c!
|
522
|
+
when 'h', 'H'
|
523
|
+
case c! when 'e', 'E'
|
524
|
+
case c! when 'r', 'R'
|
525
|
+
case c! when 'e', 'E'
|
526
|
+
return keyword Token::Where if end_of_identifier!
|
527
|
+
end
|
528
|
+
end
|
529
|
+
end
|
530
|
+
when 'i', 'I'
|
531
|
+
case c! when 't', 'T'
|
532
|
+
case c! when 'h', 'H'
|
533
|
+
return keyword Token::With if end_of_identifier!
|
534
|
+
end
|
535
|
+
end
|
536
|
+
end
|
537
|
+
when 'y', 'Y'
|
538
|
+
case c! when 'e', 'E'
|
539
|
+
case c! when 'a', 'A'
|
540
|
+
case c! when 'r', 'R'
|
541
|
+
return keyword Token::Year if end_of_identifier!
|
542
|
+
end
|
543
|
+
end
|
544
|
+
end
|
545
|
+
end
|
546
|
+
|
547
|
+
if @token.start == @p
|
548
|
+
case c
|
549
|
+
when 'a' .. 'z', 'A' .. 'Z', '_'
|
550
|
+
@p += 1
|
551
|
+
else
|
552
|
+
raise ParseException.new "Unexpected character #{c}"
|
553
|
+
end
|
554
|
+
end
|
555
|
+
|
556
|
+
while true
|
557
|
+
case c
|
558
|
+
when 'a' .. 'z', 'A' .. 'Z', '0' .. '9', '_'
|
559
|
+
@p += 1
|
560
|
+
else
|
561
|
+
break
|
562
|
+
end
|
563
|
+
end
|
564
|
+
|
565
|
+
@token.value = Token::ID
|
566
|
+
@token.string = @str[@token.start ... @p].join
|
567
|
+
return @token
|
568
|
+
end
|
569
|
+
end
|
570
|
+
|
571
|
+
def c
|
572
|
+
@str[@p]
|
573
|
+
end
|
574
|
+
|
575
|
+
def c!
|
576
|
+
@p += 1
|
577
|
+
c
|
578
|
+
end
|
579
|
+
|
580
|
+
def end_of_identifier?
|
581
|
+
case c
|
582
|
+
when ' ', "\n", "\r", "\t", '(', ')', '+', '-', '*', '/', '<', '=', '>', '`', '"', "'", ',', nil
|
583
|
+
true
|
584
|
+
else
|
585
|
+
false
|
586
|
+
end
|
587
|
+
end
|
588
|
+
|
589
|
+
def end_of_identifier!
|
590
|
+
@p += 1
|
591
|
+
end_of_identifier?
|
592
|
+
end
|
593
|
+
|
594
|
+
def keyword(value)
|
595
|
+
@token.value = value
|
596
|
+
@token
|
597
|
+
end
|
598
|
+
|
599
|
+
def keyword!(value)
|
600
|
+
@p += 1
|
601
|
+
@token.value = value
|
602
|
+
@token
|
603
|
+
end
|
604
|
+
end
|
605
|
+
end
|