predicator 1.1.0 → 1.2.0
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +46 -0
- data/HISTORY.md +8 -0
- data/README.md +30 -8
- data/lib/predicator/ast.rb +71 -19
- data/lib/predicator/evaluator.rb +55 -14
- data/lib/predicator/lexer.rex +18 -0
- data/lib/predicator/lexer.rex.rb +27 -0
- data/lib/predicator/parser.rb +233 -97
- data/lib/predicator/parser.y +54 -17
- data/lib/predicator/version.rb +1 -1
- data/lib/predicator/visitors/dot.rb +21 -8
- data/lib/predicator/visitors/instructions.rb +72 -6
- data/lib/predicator/visitors/string.rb +16 -0
- data/lib/predicator/visitors/visitor.rb +71 -19
- data/predicator.gemspec +1 -0
- metadata +18 -3
data/lib/predicator/parser.rb
CHANGED
@@ -35,91 +35,124 @@ module Predicator
|
|
35
35
|
##### State transition tables begin ###
|
36
36
|
|
37
37
|
racc_action_table = [
|
38
|
-
6, 7, 10, 6, 7, 10, 9,
|
39
|
-
6, 7, 10,
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
38
|
+
6, 7, 10, 6, 7, 10, 9, 15, 31, 9,
|
39
|
+
6, 7, 10, 6, 7, 10, 9, 16, 17, 9,
|
40
|
+
16, 17, 14, 16, 17, 14, 52, 6, 7, 10,
|
41
|
+
25, 28, 14, 9, 53, 14, 20, 21, 22, 23,
|
42
|
+
24, 18, 19, 37, 57, 38, 39, 41, 38, 14,
|
43
|
+
26, 27, 16, 17, 37, 38, 56, 39, 41, 37,
|
44
|
+
38, 60, 39, 41, 37, 38, 70, 39, 41, 72,
|
45
|
+
71, 16, 17, 73, 58, 59, 37, 38, 39, 41,
|
46
|
+
61, 52, 37, 37, 38 ]
|
47
47
|
|
48
48
|
racc_action_check = [
|
49
|
-
0, 0, 0, 9, 9, 9, 0,
|
50
|
-
10, 10, 10,
|
51
|
-
|
52
|
-
10, 17,
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
49
|
+
0, 0, 0, 9, 9, 9, 0, 1, 15, 9,
|
50
|
+
10, 10, 10, 16, 16, 16, 10, 29, 29, 16,
|
51
|
+
1, 1, 0, 32, 32, 9, 24, 17, 17, 17,
|
52
|
+
8, 8, 10, 17, 25, 16, 8, 8, 8, 8,
|
53
|
+
8, 8, 8, 23, 30, 26, 23, 23, 27, 17,
|
54
|
+
8, 8, 30, 30, 20, 20, 28, 20, 20, 21,
|
55
|
+
21, 48, 21, 21, 22, 22, 62, 22, 22, 64,
|
56
|
+
62, 33, 33, 64, 40, 40, 52, 52, 61, 61,
|
57
|
+
49, 53, 60, 71, 73 ]
|
58
58
|
|
59
59
|
racc_action_pointer = [
|
60
|
-
-2,
|
61
|
-
8,
|
62
|
-
|
63
|
-
|
64
|
-
|
60
|
+
-2, 7, nil, nil, nil, nil, nil, nil, 21, 1,
|
61
|
+
8, nil, nil, nil, nil, 8, 11, 25, nil, nil,
|
62
|
+
32, 37, 42, 21, 20, 15, 22, 25, 32, 4,
|
63
|
+
39, nil, 10, 58, nil, nil, nil, nil, nil, nil,
|
64
|
+
47, nil, nil, nil, nil, nil, nil, nil, 48, 67,
|
65
|
+
nil, nil, 54, 75, nil, nil, nil, nil, nil, nil,
|
66
|
+
60, 53, 59, nil, 62, nil, nil, nil, nil, nil,
|
67
|
+
nil, 61, nil, 61, nil, nil ]
|
65
68
|
|
66
69
|
racc_action_default = [
|
67
|
-
-
|
68
|
-
-
|
69
|
-
|
70
|
-
-
|
71
|
-
-
|
70
|
+
-48, -48, -1, -2, -3, -4, -5, -6, -7, -48,
|
71
|
+
-48, -14, -15, -16, -46, -48, -48, -48, -11, -12,
|
72
|
+
-48, -48, -48, -48, -48, -48, -48, -48, -48, -8,
|
73
|
+
-48, 76, -9, -10, -17, -23, -30, -40, -41, -42,
|
74
|
+
-48, -45, -18, -24, -31, -19, -25, -32, -48, -48,
|
75
|
+
-21, -26, -48, -48, -28, -29, -47, -13, -43, -44,
|
76
|
+
-48, -48, -48, -35, -48, -38, -22, -27, -20, -33,
|
77
|
+
-34, -48, -37, -48, -36, -39 ]
|
72
78
|
|
73
79
|
racc_goto_table = [
|
74
|
-
|
75
|
-
|
76
|
-
|
80
|
+
35, 43, 46, 62, 50, 51, 54, 55, 34, 42,
|
81
|
+
45, 48, 1, 36, 44, 47, 49, 64, nil, nil,
|
82
|
+
nil, 29, 30, nil, nil, nil, nil, nil, 32, 33,
|
83
|
+
nil, nil, 65, 66, 67, nil, nil, nil, nil, nil,
|
84
|
+
63, nil, nil, nil, nil, nil, nil, nil, 68, nil,
|
85
|
+
nil, nil, nil, 75, 69, nil, nil, nil, nil, 74 ]
|
77
86
|
|
78
87
|
racc_goto_check = [
|
79
|
-
|
80
|
-
|
81
|
-
|
88
|
+
12, 12, 12, 15, 11, 13, 12, 12, 10, 10,
|
89
|
+
10, 10, 1, 14, 14, 14, 14, 16, nil, nil,
|
90
|
+
nil, 1, 1, nil, nil, nil, nil, nil, 1, 1,
|
91
|
+
nil, nil, 12, 11, 13, nil, nil, nil, nil, nil,
|
92
|
+
10, nil, nil, nil, nil, nil, nil, nil, 10, nil,
|
93
|
+
nil, nil, nil, 12, 14, nil, nil, nil, nil, 10 ]
|
82
94
|
|
83
95
|
racc_goto_pointer = [
|
84
|
-
nil,
|
85
|
-
-
|
96
|
+
nil, 12, nil, nil, nil, nil, nil, nil, nil, nil,
|
97
|
+
-12, -20, -20, -19, -7, -49, -35, nil ]
|
86
98
|
|
87
99
|
racc_goto_default = [
|
88
|
-
nil, nil, 2, 3, 4, 5, 8, 11,
|
89
|
-
|
100
|
+
nil, nil, 2, 3, 4, 5, 8, 11, 12, 13,
|
101
|
+
nil, nil, nil, nil, nil, nil, nil, 40 ]
|
90
102
|
|
91
103
|
racc_reduce_table = [
|
92
104
|
0, 0, :racc_error,
|
93
|
-
1, 24, :_reduce_none,
|
94
|
-
1, 24, :_reduce_none,
|
95
|
-
1, 24, :_reduce_none,
|
96
|
-
1, 24, :_reduce_none,
|
97
|
-
1, 25, :_reduce_5,
|
98
|
-
1, 25, :_reduce_6,
|
99
|
-
1, 25, :_reduce_7,
|
100
|
-
2, 26, :_reduce_8,
|
101
|
-
3, 26, :_reduce_9,
|
102
|
-
3, 26, :_reduce_10,
|
103
|
-
3, 27, :_reduce_11,
|
104
|
-
3, 28, :_reduce_12,
|
105
|
-
3, 28, :_reduce_13,
|
106
|
-
3, 28, :_reduce_14,
|
107
|
-
5, 28, :_reduce_15,
|
108
|
-
3, 28, :_reduce_16,
|
109
|
-
4, 28, :_reduce_17,
|
110
|
-
3, 31, :_reduce_18,
|
111
105
|
1, 32, :_reduce_none,
|
112
|
-
|
113
|
-
1,
|
114
|
-
1,
|
115
|
-
1, 33, :
|
116
|
-
1, 33, :
|
117
|
-
1,
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
106
|
+
1, 32, :_reduce_none,
|
107
|
+
1, 32, :_reduce_none,
|
108
|
+
1, 32, :_reduce_none,
|
109
|
+
1, 33, :_reduce_5,
|
110
|
+
1, 33, :_reduce_6,
|
111
|
+
1, 33, :_reduce_7,
|
112
|
+
2, 34, :_reduce_8,
|
113
|
+
3, 34, :_reduce_9,
|
114
|
+
3, 34, :_reduce_10,
|
115
|
+
2, 34, :_reduce_11,
|
116
|
+
2, 34, :_reduce_12,
|
117
|
+
3, 35, :_reduce_13,
|
118
|
+
1, 36, :_reduce_none,
|
119
|
+
1, 36, :_reduce_none,
|
120
|
+
1, 36, :_reduce_none,
|
121
|
+
3, 38, :_reduce_17,
|
122
|
+
3, 38, :_reduce_18,
|
123
|
+
3, 38, :_reduce_19,
|
124
|
+
5, 38, :_reduce_20,
|
125
|
+
3, 38, :_reduce_21,
|
126
|
+
4, 38, :_reduce_22,
|
127
|
+
3, 39, :_reduce_23,
|
128
|
+
3, 39, :_reduce_24,
|
129
|
+
3, 39, :_reduce_25,
|
130
|
+
3, 39, :_reduce_26,
|
131
|
+
4, 39, :_reduce_27,
|
132
|
+
3, 39, :_reduce_28,
|
133
|
+
3, 39, :_reduce_29,
|
134
|
+
3, 40, :_reduce_30,
|
135
|
+
3, 40, :_reduce_31,
|
136
|
+
3, 40, :_reduce_32,
|
137
|
+
5, 40, :_reduce_33,
|
138
|
+
3, 42, :_reduce_34,
|
139
|
+
1, 46, :_reduce_none,
|
140
|
+
3, 46, :_reduce_36,
|
141
|
+
3, 44, :_reduce_37,
|
142
|
+
1, 47, :_reduce_none,
|
143
|
+
3, 47, :_reduce_39,
|
144
|
+
1, 41, :_reduce_40,
|
145
|
+
1, 43, :_reduce_41,
|
146
|
+
1, 45, :_reduce_42,
|
147
|
+
2, 45, :_reduce_43,
|
148
|
+
2, 45, :_reduce_44,
|
149
|
+
1, 48, :_reduce_45,
|
150
|
+
1, 37, :_reduce_46,
|
151
|
+
3, 37, :_reduce_47 ]
|
152
|
+
|
153
|
+
racc_reduce_n = 48
|
154
|
+
|
155
|
+
racc_shift_n = 76
|
123
156
|
|
124
157
|
racc_token_table = {
|
125
158
|
false => 0,
|
@@ -142,11 +175,19 @@ racc_token_table = {
|
|
142
175
|
:LT => 17,
|
143
176
|
:BETWEEN => 18,
|
144
177
|
:IN => 19,
|
145
|
-
:
|
146
|
-
:
|
147
|
-
:
|
148
|
-
|
149
|
-
|
178
|
+
:PRESENT => 20,
|
179
|
+
:BLANK => 21,
|
180
|
+
:INTEGER => 22,
|
181
|
+
:STRING => 23,
|
182
|
+
:IDENTIFIER => 24,
|
183
|
+
:DATE => 25,
|
184
|
+
:DURATION => 26,
|
185
|
+
:AGO => 27,
|
186
|
+
:FROMNOW => 28,
|
187
|
+
:STARTSWITH => 29,
|
188
|
+
:ENDSWITH => 30 }
|
189
|
+
|
190
|
+
racc_nt_base = 31
|
150
191
|
|
151
192
|
racc_use_result_var = false
|
152
193
|
|
@@ -187,9 +228,17 @@ Racc_token_to_s_table = [
|
|
187
228
|
"LT",
|
188
229
|
"BETWEEN",
|
189
230
|
"IN",
|
231
|
+
"PRESENT",
|
232
|
+
"BLANK",
|
190
233
|
"INTEGER",
|
191
234
|
"STRING",
|
192
235
|
"IDENTIFIER",
|
236
|
+
"DATE",
|
237
|
+
"DURATION",
|
238
|
+
"AGO",
|
239
|
+
"FROMNOW",
|
240
|
+
"STARTSWITH",
|
241
|
+
"ENDSWITH",
|
193
242
|
"$start",
|
194
243
|
"predicate",
|
195
244
|
"boolean_predicate",
|
@@ -197,10 +246,17 @@ Racc_token_to_s_table = [
|
|
197
246
|
"group_predicate",
|
198
247
|
"comparison_predicate",
|
199
248
|
"variable",
|
200
|
-
"
|
201
|
-
"
|
202
|
-
"
|
203
|
-
"
|
249
|
+
"integer_comparison_predicate",
|
250
|
+
"string_comparison_predicate",
|
251
|
+
"date_comparison_predicate",
|
252
|
+
"integer",
|
253
|
+
"integer_array",
|
254
|
+
"string",
|
255
|
+
"string_array",
|
256
|
+
"date",
|
257
|
+
"integer_array_contents",
|
258
|
+
"string_array_contents",
|
259
|
+
"duration" ]
|
204
260
|
|
205
261
|
Racc_debug_parser = false
|
206
262
|
|
@@ -241,60 +297,140 @@ def _reduce_10(val, _values)
|
|
241
297
|
end
|
242
298
|
|
243
299
|
def _reduce_11(val, _values)
|
244
|
-
AST::
|
300
|
+
AST::Present.new val.first
|
245
301
|
end
|
246
302
|
|
247
303
|
def _reduce_12(val, _values)
|
248
|
-
AST::
|
304
|
+
AST::Blank.new val.first
|
249
305
|
end
|
250
306
|
|
251
307
|
def _reduce_13(val, _values)
|
252
|
-
AST::
|
308
|
+
AST::Group.new val[1]
|
253
309
|
end
|
254
310
|
|
255
|
-
|
256
|
-
AST::LessThan.new val.first, val.last
|
257
|
-
end
|
311
|
+
# reduce 14 omitted
|
258
312
|
|
259
|
-
|
260
|
-
AST::Between.new val.first, val[2], val.last
|
261
|
-
end
|
313
|
+
# reduce 15 omitted
|
262
314
|
|
263
|
-
|
264
|
-
AST::In.new val.first, val.last
|
265
|
-
end
|
315
|
+
# reduce 16 omitted
|
266
316
|
|
267
317
|
def _reduce_17(val, _values)
|
268
|
-
AST::
|
318
|
+
AST::IntegerEqual.new val.first, val.last
|
269
319
|
end
|
270
320
|
|
271
321
|
def _reduce_18(val, _values)
|
272
|
-
AST::
|
322
|
+
AST::IntegerGreaterThan.new val.first, val.last
|
273
323
|
end
|
274
324
|
|
275
|
-
|
325
|
+
def _reduce_19(val, _values)
|
326
|
+
AST::IntegerLessThan.new val.first, val.last
|
327
|
+
end
|
276
328
|
|
277
329
|
def _reduce_20(val, _values)
|
278
|
-
|
330
|
+
AST::IntegerBetween.new val.first, val[2], val.last
|
279
331
|
end
|
280
332
|
|
281
|
-
|
333
|
+
def _reduce_21(val, _values)
|
334
|
+
AST::IntegerIn.new val.first, val.last
|
335
|
+
end
|
282
336
|
|
283
|
-
|
337
|
+
def _reduce_22(val, _values)
|
338
|
+
AST::IntegerNotIn.new val.first, val.last
|
339
|
+
end
|
284
340
|
|
285
341
|
def _reduce_23(val, _values)
|
286
|
-
AST::
|
342
|
+
AST::StringEqual.new val.first, val.last
|
287
343
|
end
|
288
344
|
|
289
345
|
def _reduce_24(val, _values)
|
290
|
-
AST::
|
346
|
+
AST::StringGreaterThan.new val.first, val.last
|
291
347
|
end
|
292
348
|
|
293
349
|
def _reduce_25(val, _values)
|
294
|
-
AST::
|
350
|
+
AST::StringLessThan.new val.first, val.last
|
295
351
|
end
|
296
352
|
|
297
353
|
def _reduce_26(val, _values)
|
354
|
+
AST::StringIn.new val.first, val.last
|
355
|
+
end
|
356
|
+
|
357
|
+
def _reduce_27(val, _values)
|
358
|
+
AST::StringNotIn.new val.first, val.last
|
359
|
+
end
|
360
|
+
|
361
|
+
def _reduce_28(val, _values)
|
362
|
+
AST::StringStartsWith.new val.first, val.last
|
363
|
+
end
|
364
|
+
|
365
|
+
def _reduce_29(val, _values)
|
366
|
+
AST::StringEndsWith.new val.first, val.last
|
367
|
+
end
|
368
|
+
|
369
|
+
def _reduce_30(val, _values)
|
370
|
+
AST::DateEqual.new val.first, val.last
|
371
|
+
end
|
372
|
+
|
373
|
+
def _reduce_31(val, _values)
|
374
|
+
AST::DateGreaterThan.new val.first, val.last
|
375
|
+
end
|
376
|
+
|
377
|
+
def _reduce_32(val, _values)
|
378
|
+
AST::DateLessThan.new val.first, val.last
|
379
|
+
end
|
380
|
+
|
381
|
+
def _reduce_33(val, _values)
|
382
|
+
AST::DateBetween.new val.first, val[2], val.last
|
383
|
+
end
|
384
|
+
|
385
|
+
def _reduce_34(val, _values)
|
386
|
+
AST::IntegerArray.new val[1]
|
387
|
+
end
|
388
|
+
|
389
|
+
# reduce 35 omitted
|
390
|
+
|
391
|
+
def _reduce_36(val, _values)
|
392
|
+
[val.first, val.last].flatten
|
393
|
+
end
|
394
|
+
|
395
|
+
def _reduce_37(val, _values)
|
396
|
+
AST::StringArray.new val[1]
|
397
|
+
end
|
398
|
+
|
399
|
+
# reduce 38 omitted
|
400
|
+
|
401
|
+
def _reduce_39(val, _values)
|
402
|
+
[val.first, val.last].flatten
|
403
|
+
end
|
404
|
+
|
405
|
+
def _reduce_40(val, _values)
|
406
|
+
AST::Integer.new val.first.to_i
|
407
|
+
end
|
408
|
+
|
409
|
+
def _reduce_41(val, _values)
|
410
|
+
AST::String.new val.first
|
411
|
+
end
|
412
|
+
|
413
|
+
def _reduce_42(val, _values)
|
414
|
+
AST::Date.new val.first
|
415
|
+
end
|
416
|
+
|
417
|
+
def _reduce_43(val, _values)
|
418
|
+
AST::DateAgo.new val.first
|
419
|
+
end
|
420
|
+
|
421
|
+
def _reduce_44(val, _values)
|
422
|
+
AST::DateFromNow.new val.first
|
423
|
+
end
|
424
|
+
|
425
|
+
def _reduce_45(val, _values)
|
426
|
+
AST::Duration.new val.first
|
427
|
+
end
|
428
|
+
|
429
|
+
def _reduce_46(val, _values)
|
430
|
+
AST::Variable.new val.first
|
431
|
+
end
|
432
|
+
|
433
|
+
def _reduce_47(val, _values)
|
298
434
|
AST::Variable.new [val.first, val.last].flatten.join(".")
|
299
435
|
end
|
300
436
|
|
data/lib/predicator/parser.y
CHANGED
@@ -4,8 +4,10 @@ options no_result_var
|
|
4
4
|
|
5
5
|
token TRUE FALSE LPAREN RPAREN LBRACKET RBRACKET
|
6
6
|
BANG NOT DOT COMMA AT AND OR
|
7
|
-
EQ GT LT BETWEEN IN
|
7
|
+
EQ GT LT BETWEEN IN PRESENT BLANK
|
8
8
|
INTEGER STRING IDENTIFIER
|
9
|
+
DATE DURATION AGO FROMNOW
|
10
|
+
STARTSWITH ENDSWITH
|
9
11
|
|
10
12
|
rule
|
11
13
|
predicate
|
@@ -23,32 +25,67 @@ rule
|
|
23
25
|
: BANG predicate { AST::Not.new val.last }
|
24
26
|
| predicate AND predicate { AST::And.new val.first, val.last }
|
25
27
|
| predicate OR predicate { AST::Or.new val.first, val.last }
|
28
|
+
| variable PRESENT { AST::Present.new val.first }
|
29
|
+
| variable BLANK { AST::Blank.new val.first }
|
26
30
|
;
|
27
31
|
group_predicate
|
28
32
|
: LPAREN predicate RPAREN { AST::Group.new val[1] }
|
29
33
|
;
|
30
34
|
comparison_predicate
|
31
|
-
:
|
32
|
-
|
|
33
|
-
|
|
34
|
-
| value BETWEEN value AND value { AST::Between.new val.first, val[2], val.last }
|
35
|
-
| value IN array { AST::In.new val.first, val.last }
|
36
|
-
| value NOT IN array { AST::NotIn.new val.first, val.last }
|
35
|
+
: integer_comparison_predicate
|
36
|
+
| string_comparison_predicate
|
37
|
+
| date_comparison_predicate
|
37
38
|
;
|
38
|
-
|
39
|
-
:
|
39
|
+
integer_comparison_predicate
|
40
|
+
: variable EQ integer { AST::IntegerEqual.new val.first, val.last }
|
41
|
+
| variable GT integer { AST::IntegerGreaterThan.new val.first, val.last }
|
42
|
+
| variable LT integer { AST::IntegerLessThan.new val.first, val.last }
|
43
|
+
| variable BETWEEN integer AND integer { AST::IntegerBetween.new val.first, val[2], val.last }
|
44
|
+
| variable IN integer_array { AST::IntegerIn.new val.first, val.last }
|
45
|
+
| variable NOT IN integer_array { AST::IntegerNotIn.new val.first, val.last }
|
40
46
|
;
|
41
|
-
|
42
|
-
:
|
43
|
-
|
|
47
|
+
string_comparison_predicate
|
48
|
+
: variable EQ string { AST::StringEqual.new val.first, val.last }
|
49
|
+
| variable GT string { AST::StringGreaterThan.new val.first, val.last }
|
50
|
+
| variable LT string { AST::StringLessThan.new val.first, val.last }
|
51
|
+
| variable IN string_array { AST::StringIn.new val.first, val.last }
|
52
|
+
| variable NOT IN string_array { AST::StringNotIn.new val.first, val.last }
|
53
|
+
| variable STARTSWITH string { AST::StringStartsWith.new val.first, val.last }
|
54
|
+
| variable ENDSWITH string { AST::StringEndsWith.new val.first, val.last }
|
44
55
|
;
|
45
|
-
|
46
|
-
:
|
47
|
-
| variable
|
56
|
+
date_comparison_predicate
|
57
|
+
: variable EQ date { AST::DateEqual.new val.first, val.last }
|
58
|
+
| variable GT date { AST::DateGreaterThan.new val.first, val.last }
|
59
|
+
| variable LT date { AST::DateLessThan.new val.first, val.last }
|
60
|
+
| variable BETWEEN date AND date { AST::DateBetween.new val.first, val[2], val.last }
|
48
61
|
;
|
49
|
-
|
62
|
+
integer_array
|
63
|
+
: LBRACKET integer_array_contents RBRACKET { AST::IntegerArray.new val[1] }
|
64
|
+
;
|
65
|
+
integer_array_contents
|
66
|
+
: integer
|
67
|
+
| integer_array_contents COMMA integer { [val.first, val.last].flatten }
|
68
|
+
;
|
69
|
+
string_array
|
70
|
+
: LBRACKET string_array_contents RBRACKET { AST::StringArray.new val[1] }
|
71
|
+
;
|
72
|
+
string_array_contents
|
73
|
+
: string
|
74
|
+
| string_array_contents COMMA string { [val.first, val.last].flatten }
|
75
|
+
;
|
76
|
+
integer
|
77
|
+
: INTEGER { AST::Integer.new val.first.to_i }
|
78
|
+
;
|
79
|
+
string
|
50
80
|
: STRING { AST::String.new val.first }
|
51
|
-
|
81
|
+
;
|
82
|
+
date
|
83
|
+
: DATE { AST::Date.new val.first }
|
84
|
+
| duration AGO { AST::DateAgo.new val.first }
|
85
|
+
| duration FROMNOW { AST::DateFromNow.new val.first }
|
86
|
+
;
|
87
|
+
duration
|
88
|
+
: DURATION { AST::Duration.new val.first }
|
52
89
|
;
|
53
90
|
variable
|
54
91
|
: IDENTIFIER { AST::Variable.new val.first }
|