predicator 0.3.0 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b6f75523bd14777d85c7d52472823bad7eafa31f
4
- data.tar.gz: cbf63f511abaccbac93ed564256d5d0caea7da87
3
+ metadata.gz: cccb4a93e1358c39913a03aff288de916bf3fe43
4
+ data.tar.gz: e28bf0d18f7b94d27c94baaec203eb99a1457ed7
5
5
  SHA512:
6
- metadata.gz: 7c0c9e0fa3737b4c6f1ec27a20254197fbe0a52825f37cb2978c02c829473d3fd3777f5e5937cb08c754783acc0c1a9188f8e31054a4ab4eb1dfab325873c68a
7
- data.tar.gz: af32c18e7d32ccf7047f02d7bafaa71fbb7d3fa0b7383d47f78854440fdb1ef45884d832f37e1ff364ca19a5ff90783fe6715b4e33c9b7e247ff6cb169a80444
6
+ metadata.gz: a6e74e9fae07264c552612a5fcd6c804b6f0deaf42b6a81012fd1e48900ee923e7b21ebd2e36a6b828bc6942358c1fada37ab25436a5d6dc090db89ee22d3d0b
7
+ data.tar.gz: 394b6bd004026f79cd6aed9bada7fefa863df8a44a1f2b64056c53f455b94106da9a5cc4fb54741f9894e848f763f7f4d30b4a7554c68addeb23ecaf3efa34b1
data/HISTORY.md CHANGED
@@ -1,3 +1,9 @@
1
+ ### 0.4.0 / 2016-06-09
2
+
3
+ * Adds double dispatch for relation predicates
4
+ * Adds method predicate (.blank? and .present?)
5
+ * Adds Context#eval
6
+
1
7
  ### 0.3.0 / 2016-03-11
2
8
 
3
9
  * Adds more relation predicates (GT, LT, GTE, LTE, NEQ)
@@ -1,6 +1,12 @@
1
+ require "date"
2
+
1
3
  require "predicator/context"
4
+ require "predicator/errors"
2
5
  require "predicator/lexer"
6
+ require "predicator/nodes"
3
7
  require "predicator/parser"
8
+ require "predicator/predicates"
9
+ require "predicator/variable"
4
10
  require "predicator/version"
5
11
 
6
12
  module Predicator
@@ -4,20 +4,71 @@ module Predicator
4
4
  class Context
5
5
  attr_reader :bindings
6
6
 
7
- def initialize
7
+ def initialize attrs={}
8
8
  @bindings = {}
9
+ attrs.each{ |key, val| bind key, val }
9
10
  end
10
11
 
11
- def bind name, value
12
- value = OpenStruct.new(value) if value.kind_of? Hash
13
- bindings[name.to_s] = value
12
+ def bind name, obj
13
+ if obj.kind_of? Hash
14
+ obj = OpenStruct.new obj
15
+ end
16
+ bindings[name.to_s] = obj
14
17
  end
18
+ alias :[]= :bind
15
19
 
16
- def value_for input
17
- return input unless input.kind_of? Predicator::Variable
20
+ def node_for input
21
+ value = value_for input
22
+ node_class = Predicator::Nodes::BaseNode.class_for value
23
+ node_class.new value
24
+ end
18
25
 
19
- input.value_in self
26
+ def value_for input
27
+ if input.kind_of? Predicator::Variable
28
+ input.value_in self
29
+ else
30
+ input
31
+ end
20
32
  end
21
33
  alias :[] :value_for
34
+
35
+ def respond_to? method
36
+ bindings.key?(method.to_s) || super
37
+ end
38
+
39
+ def method_missing method, *args, &block
40
+ found_binding = bindings.fetch method.to_s, nil
41
+ if found_binding.nil?
42
+ super
43
+ else
44
+ found_binding
45
+ end
46
+ end
47
+
48
+ def eval string
49
+ string.gsub(/{{([^}]+)}}/) do |match|
50
+ name, attribute = $1.strip.split "."
51
+ variable = Predicator::Variable.new name, attribute
52
+ value_for variable
53
+ end
54
+ end
55
+
56
+ def to_hash
57
+ hsh = {}
58
+ bindings.each do |key, value|
59
+ hsh[key] = hash_value_for value
60
+ end
61
+ hsh
62
+ end
63
+
64
+ private
65
+
66
+ def hash_value_for value
67
+ if value.kind_of? OpenStruct
68
+ value.to_h
69
+ else
70
+ value.to_hash
71
+ end
72
+ end
22
73
  end
23
74
  end
@@ -0,0 +1,5 @@
1
+ module Predicator
2
+ class UnknownNodeTypeError < StandardError; end
3
+ class NilValueError < StandardError; end
4
+ class ParseError < StandardError; end
5
+ end
@@ -10,92 +10,97 @@ module Predicator
10
10
  ##### State transition tables begin ###
11
11
 
12
12
  racc_action_table = [
13
- 9, 31, 32, 7, 8, 14, 15, 16, 17, 18,
14
- 9, 43, 6, 7, 8, 14, 15, 16, 17, 18,
15
- 9, 44, 6, 7, 8, 14, 15, 16, 17, 18,
16
- 9, nil, 6, 7, 8, 14, 15, 16, 17, 18,
17
- 9, nil, 6, 7, 8, 14, 15, 16, 17, 18,
18
- 20, 21, 6, 19, nil, nil, 20, 21, nil, 22,
19
- nil, nil, 42, 23, 28, 27, 26, 25, 24, 14,
20
- 15, 16, 17, 18, 14, 15, 16, 17, 18, 14,
21
- 15, 16, 17, 18, 14, 15, 16, 17, 18, 14,
22
- 15, 16, 17, 18, 14, 15, 16, 17, 18, 14,
23
- 15, 16, 17, 18, 14, 15, 16, 17, 18 ]
13
+ 10, 21, 22, 8, 9, 15, 16, 17, 18, 19,
14
+ 47, 10, 6, 37, 8, 9, 15, 16, 17, 18,
15
+ 19, 10, 34, 6, 8, 9, 15, 16, 17, 18,
16
+ 19, 10, 48, 6, 8, 9, 15, 16, 17, 18,
17
+ 19, 10, 33, 6, 8, 9, 15, 16, 17, 18,
18
+ 19, 24, 31, 6, nil, 25, 30, 29, 28, 27,
19
+ 26, 15, 16, 17, 18, 19, 15, 16, 17, 18,
20
+ 19, 20, 45, 46, 21, 22, 15, 16, 17, 18,
21
+ 19, 15, 16, 17, 18, 19, 15, 16, 17, 18,
22
+ 19, 15, 16, 17, 18, 19, 15, 16, 17, 18,
23
+ 19, 15, 16, 17, 18, 19 ]
24
24
 
25
25
  racc_action_check = [
26
- 0, 18, 19, 0, 0, 0, 0, 0, 0, 0,
27
- 6, 31, 0, 6, 6, 6, 6, 6, 6, 6,
28
- 9, 35, 6, 9, 9, 9, 9, 9, 9, 9,
29
- 20, nil, 9, 20, 20, 20, 20, 20, 20, 20,
30
- 21, nil, 20, 21, 21, 21, 21, 21, 21, 21,
31
- 29, 29, 21, 1, nil, nil, 1, 1, nil, 5,
32
- nil, nil, 29, 5, 5, 5, 5, 5, 5, 22,
33
- 22, 22, 22, 22, 23, 23, 23, 23, 23, 24,
34
- 24, 24, 24, 24, 25, 25, 25, 25, 25, 26,
35
- 26, 26, 26, 26, 27, 27, 27, 27, 27, 28,
36
- 28, 28, 28, 28, 44, 44, 44, 44, 44 ]
26
+ 0, 23, 23, 0, 0, 0, 0, 0, 0, 0,
27
+ 33, 6, 0, 23, 6, 6, 6, 6, 6, 6,
28
+ 6, 22, 20, 6, 22, 22, 22, 22, 22, 22,
29
+ 22, 10, 38, 22, 10, 10, 10, 10, 10, 10,
30
+ 10, 21, 19, 10, 21, 21, 21, 21, 21, 21,
31
+ 21, 7, 7, 21, nil, 7, 7, 7, 7, 7,
32
+ 7, 24, 24, 24, 24, 24, 48, 48, 48, 48,
33
+ 48, 1, 31, 31, 1, 1, 30, 30, 30, 30,
34
+ 30, 25, 25, 25, 25, 25, 26, 26, 26, 26,
35
+ 26, 27, 27, 27, 27, 27, 29, 29, 29, 29,
36
+ 29, 28, 28, 28, 28, 28 ]
37
37
 
38
38
  racc_action_pointer = [
39
- -2, 53, nil, nil, nil, 47, 8, nil, nil, 18,
40
- nil, nil, nil, nil, nil, nil, nil, nil, -12, 2,
41
- 28, 38, 62, 67, 72, 77, 82, 87, 92, 47,
42
- nil, 0, nil, nil, nil, 18, nil, nil, nil, nil,
43
- nil, nil, nil, nil, 97, nil ]
39
+ -2, 71, nil, nil, nil, nil, 9, 39, nil, nil,
40
+ 29, nil, nil, nil, nil, nil, nil, nil, nil, 29,
41
+ 22, 39, 19, -2, 54, 74, 79, 84, 94, 89,
42
+ 69, 50, nil, -1, nil, nil, nil, nil, 29, nil,
43
+ nil, nil, nil, nil, nil, nil, nil, nil, 59, nil ]
44
44
 
45
45
  racc_action_default = [
46
- -26, -26, -1, -2, -3, -26, -26, -12, -13, -26,
47
- -17, -18, -19, -20, -21, -22, -23, -24, -26, -26,
48
- -26, -26, -26, -26, -26, -26, -26, -26, -26, -26,
49
- -16, -26, 46, -14, -15, -26, -6, -7, -8, -9,
50
- -10, -11, -5, -25, -26, -4 ]
46
+ -29, -29, -1, -2, -3, -4, -29, -29, -7, -8,
47
+ -29, -20, -21, -22, -23, -24, -25, -26, -27, -29,
48
+ -29, -29, -29, -29, -29, -29, -29, -29, -29, -29,
49
+ -29, -29, -11, -29, 50, -9, -10, -5, -29, -12,
50
+ -13, -14, -15, -16, -17, -18, -19, -28, -29, -6 ]
51
51
 
52
52
  racc_goto_table = [
53
- 35, 36, 37, 38, 39, 40, 41, 1, nil, nil,
54
- nil, nil, nil, 29, nil, nil, 30, nil, nil, nil,
55
- nil, nil, 45, nil, nil, nil, nil, 33, 34 ]
53
+ 38, 39, 40, 41, 42, 43, 44, 1, nil, nil,
54
+ nil, nil, nil, 23, nil, nil, nil, 32, nil, nil,
55
+ nil, nil, nil, nil, 49, nil, nil, nil, 35, 36 ]
56
56
 
57
57
  racc_goto_check = [
58
- 5, 5, 5, 5, 5, 5, 5, 1, nil, nil,
59
- nil, nil, nil, 1, nil, nil, 1, nil, nil, nil,
60
- nil, nil, 5, nil, nil, nil, nil, 1, 1 ]
58
+ 6, 6, 6, 6, 6, 6, 6, 1, nil, nil,
59
+ nil, nil, nil, 1, nil, nil, nil, 1, nil, nil,
60
+ nil, nil, nil, nil, 6, nil, nil, nil, 1, 1 ]
61
61
 
62
62
  racc_goto_pointer = [
63
- nil, 7, nil, nil, nil, -22, nil, nil, nil, nil ]
63
+ nil, 7, nil, nil, nil, nil, -24, nil, nil, nil,
64
+ nil ]
64
65
 
65
66
  racc_goto_default = [
66
- nil, nil, 2, 3, 4, 5, 10, 11, 12, 13 ]
67
+ nil, nil, 2, 3, 4, 5, 7, 11, 12, 13,
68
+ 14 ]
67
69
 
68
70
  racc_reduce_table = [
69
71
  0, 0, :racc_error,
70
- 1, 23, :_reduce_none,
71
- 1, 23, :_reduce_none,
72
- 1, 23, :_reduce_none,
73
- 5, 23, :_reduce_4,
74
- 3, 23, :_reduce_none,
75
- 3, 24, :_reduce_6,
76
- 3, 24, :_reduce_7,
77
- 3, 24, :_reduce_8,
78
- 3, 24, :_reduce_9,
79
- 3, 24, :_reduce_10,
80
- 3, 24, :_reduce_11,
81
- 1, 25, :_reduce_12,
82
- 1, 25, :_reduce_13,
83
- 3, 26, :_reduce_14,
84
- 3, 26, :_reduce_15,
85
- 2, 26, :_reduce_16,
86
- 1, 27, :_reduce_none,
87
- 1, 27, :_reduce_none,
88
- 1, 28, :_reduce_none,
89
- 1, 28, :_reduce_none,
90
- 1, 30, :_reduce_21,
91
- 1, 31, :_reduce_22,
92
- 1, 31, :_reduce_23,
93
- 1, 31, :_reduce_24,
94
- 3, 29, :_reduce_25 ]
95
-
96
- racc_reduce_n = 26
97
-
98
- racc_shift_n = 46
72
+ 1, 25, :_reduce_none,
73
+ 1, 25, :_reduce_none,
74
+ 1, 25, :_reduce_none,
75
+ 1, 25, :_reduce_none,
76
+ 3, 25, :_reduce_5,
77
+ 5, 25, :_reduce_6,
78
+ 1, 26, :_reduce_7,
79
+ 1, 26, :_reduce_8,
80
+ 3, 27, :_reduce_9,
81
+ 3, 27, :_reduce_10,
82
+ 2, 27, :_reduce_11,
83
+ 3, 28, :_reduce_12,
84
+ 3, 28, :_reduce_13,
85
+ 3, 28, :_reduce_14,
86
+ 3, 28, :_reduce_15,
87
+ 3, 28, :_reduce_16,
88
+ 3, 28, :_reduce_17,
89
+ 3, 29, :_reduce_18,
90
+ 3, 29, :_reduce_19,
91
+ 1, 30, :_reduce_none,
92
+ 1, 30, :_reduce_none,
93
+ 1, 31, :_reduce_none,
94
+ 1, 31, :_reduce_none,
95
+ 1, 33, :_reduce_24,
96
+ 1, 34, :_reduce_25,
97
+ 1, 34, :_reduce_26,
98
+ 1, 34, :_reduce_27,
99
+ 3, 32, :_reduce_28 ]
100
+
101
+ racc_reduce_n = 29
102
+
103
+ racc_shift_n = 50
99
104
 
100
105
  racc_token_table = {
101
106
  false => 0,
@@ -119,9 +124,11 @@ racc_token_table = {
119
124
  :tLEQ => 18,
120
125
  :tGEQ => 19,
121
126
  :tLT => 20,
122
- :tGT => 21 }
127
+ :tGT => 21,
128
+ :tBLANK => 22,
129
+ :tPRESENT => 23 }
123
130
 
124
- racc_nt_base = 22
131
+ racc_nt_base = 24
125
132
 
126
133
  racc_use_result_var = false
127
134
 
@@ -164,11 +171,14 @@ Racc_token_to_s_table = [
164
171
  "tGEQ",
165
172
  "tLT",
166
173
  "tGT",
174
+ "tBLANK",
175
+ "tPRESENT",
167
176
  "$start",
168
177
  "predicate",
169
- "relation_predicate",
170
178
  "boolean_predicate",
171
179
  "logical_predicate",
180
+ "relation_predicate",
181
+ "method_predicate",
172
182
  "value",
173
183
  "scalar",
174
184
  "variable",
@@ -187,114 +197,132 @@ Racc_debug_parser = false
187
197
 
188
198
  # reduce 3 omitted
189
199
 
190
- module_eval(<<'.,.,', 'parser.y', 13)
191
- def _reduce_4(val, _values)
192
- Predicator::Predicates::Between.new val[0], val[2], val[4]
200
+ # reduce 4 omitted
201
+
202
+ module_eval(<<'.,.,', 'parser.y', 14)
203
+ def _reduce_5(val, _values)
204
+ val[1]
193
205
  end
194
206
  .,.,
195
207
 
196
- # reduce 5 omitted
197
-
198
- module_eval(<<'.,.,', 'parser.y', 17)
208
+ module_eval(<<'.,.,', 'parser.y', 15)
199
209
  def _reduce_6(val, _values)
200
- Predicator::Predicates::Equal.new val[0], val[2]
210
+ Predicator::Predicates::Between.new val[0], val[2], val[4]
201
211
  end
202
212
  .,.,
203
213
 
204
214
  module_eval(<<'.,.,', 'parser.y', 18)
205
215
  def _reduce_7(val, _values)
206
- Predicator::Predicates::GreaterThan.new val[0], val[2]
216
+ Predicator::Predicates::True.new
207
217
  end
208
218
  .,.,
209
219
 
210
220
  module_eval(<<'.,.,', 'parser.y', 19)
211
221
  def _reduce_8(val, _values)
212
- Predicator::Predicates::LessThan.new val[0], val[2]
222
+ Predicator::Predicates::False.new
213
223
  end
214
224
  .,.,
215
225
 
216
- module_eval(<<'.,.,', 'parser.y', 20)
226
+ module_eval(<<'.,.,', 'parser.y', 22)
217
227
  def _reduce_9(val, _values)
218
- Predicator::Predicates::GreaterThanOrEqual.new val[0], val[2]
228
+ Predicator::Predicates::And.new [val[0], val[2]]
219
229
  end
220
230
  .,.,
221
231
 
222
- module_eval(<<'.,.,', 'parser.y', 21)
232
+ module_eval(<<'.,.,', 'parser.y', 23)
223
233
  def _reduce_10(val, _values)
224
- Predicator::Predicates::LessThanOrEqual.new val[0], val[2]
234
+ Predicator::Predicates::Or.new [val[0], val[2]]
225
235
  end
226
236
  .,.,
227
237
 
228
- module_eval(<<'.,.,', 'parser.y', 22)
238
+ module_eval(<<'.,.,', 'parser.y', 24)
229
239
  def _reduce_11(val, _values)
230
- Predicator::Predicates::NotEqual.new val[0], val[2]
240
+ Predicator::Predicates::Not.new val[0]
231
241
  end
232
242
  .,.,
233
243
 
234
- module_eval(<<'.,.,', 'parser.y', 25)
244
+ module_eval(<<'.,.,', 'parser.y', 27)
235
245
  def _reduce_12(val, _values)
236
- Predicator::Predicates::True.new
246
+ Predicator::Predicates::Equal.new val[0], val[2]
237
247
  end
238
248
  .,.,
239
249
 
240
- module_eval(<<'.,.,', 'parser.y', 26)
250
+ module_eval(<<'.,.,', 'parser.y', 28)
241
251
  def _reduce_13(val, _values)
242
- Predicator::Predicates::False.new
252
+ Predicator::Predicates::GreaterThan.new val[0], val[2]
243
253
  end
244
254
  .,.,
245
255
 
246
256
  module_eval(<<'.,.,', 'parser.y', 29)
247
257
  def _reduce_14(val, _values)
248
- Predicator::Predicates::And.new [val[0], val[2]]
258
+ Predicator::Predicates::LessThan.new val[0], val[2]
249
259
  end
250
260
  .,.,
251
261
 
252
262
  module_eval(<<'.,.,', 'parser.y', 30)
253
263
  def _reduce_15(val, _values)
254
- Predicator::Predicates::Or.new [val[0], val[2]]
264
+ Predicator::Predicates::GreaterThanOrEqual.new val[0], val[2]
255
265
  end
256
266
  .,.,
257
267
 
258
268
  module_eval(<<'.,.,', 'parser.y', 31)
259
269
  def _reduce_16(val, _values)
260
- Predicator::Predicates::Not.new val[0]
270
+ Predicator::Predicates::LessThanOrEqual.new val[0], val[2]
261
271
  end
262
272
  .,.,
263
273
 
264
- # reduce 17 omitted
274
+ module_eval(<<'.,.,', 'parser.y', 32)
275
+ def _reduce_17(val, _values)
276
+ Predicator::Predicates::NotEqual.new val[0], val[2]
277
+ end
278
+ .,.,
265
279
 
266
- # reduce 18 omitted
280
+ module_eval(<<'.,.,', 'parser.y', 35)
281
+ def _reduce_18(val, _values)
282
+ Predicator::Predicates::Method.new val[0], val[2]
283
+ end
284
+ .,.,
267
285
 
268
- # reduce 19 omitted
286
+ module_eval(<<'.,.,', 'parser.y', 36)
287
+ def _reduce_19(val, _values)
288
+ Predicator::Predicates::Method.new val[0], val[2]
289
+ end
290
+ .,.,
269
291
 
270
292
  # reduce 20 omitted
271
293
 
272
- module_eval(<<'.,.,', 'parser.y', 42)
273
- def _reduce_21(val, _values)
294
+ # reduce 21 omitted
295
+
296
+ # reduce 22 omitted
297
+
298
+ # reduce 23 omitted
299
+
300
+ module_eval(<<'.,.,', 'parser.y', 47)
301
+ def _reduce_24(val, _values)
274
302
  val[0]
275
303
  end
276
304
  .,.,
277
305
 
278
- module_eval(<<'.,.,', 'parser.y', 45)
279
- def _reduce_22(val, _values)
306
+ module_eval(<<'.,.,', 'parser.y', 50)
307
+ def _reduce_25(val, _values)
280
308
  val[0].to_f
281
309
  end
282
310
  .,.,
283
311
 
284
- module_eval(<<'.,.,', 'parser.y', 46)
285
- def _reduce_23(val, _values)
312
+ module_eval(<<'.,.,', 'parser.y', 51)
313
+ def _reduce_26(val, _values)
286
314
  val[0].to_i
287
315
  end
288
316
  .,.,
289
317
 
290
- module_eval(<<'.,.,', 'parser.y', 47)
291
- def _reduce_24(val, _values)
318
+ module_eval(<<'.,.,', 'parser.y', 52)
319
+ def _reduce_27(val, _values)
292
320
  Date.new *val[0]
293
321
  end
294
322
  .,.,
295
323
 
296
- module_eval(<<'.,.,', 'parser.y', 50)
297
- def _reduce_25(val, _values)
324
+ module_eval(<<'.,.,', 'parser.y', 55)
325
+ def _reduce_28(val, _values)
298
326
  Predicator::Variable.new val[0], val[2]
299
327
  end
300
328
  .,.,
@@ -22,6 +22,8 @@ module Predicator
22
22
  AND = /and/i
23
23
  OR = /or/i
24
24
  BETWEEN = /between/i
25
+ BLANK = /blank\?/i
26
+ PRESENT = /present\?/i
25
27
  STRING = /(["])(?:\\?.)*?\1/
26
28
  IDENTIFIER = /[a-z][A-Za-z0-9_]*/
27
29
 
@@ -100,6 +102,12 @@ module Predicator
100
102
  when text = @ss.scan(BETWEEN)
101
103
  @tokens.push [:tBETWEEN, text]
102
104
 
105
+ when text = @ss.scan(BLANK)
106
+ @tokens.push [:tBLANK, text]
107
+
108
+ when text = @ss.scan(PRESENT)
109
+ @tokens.push [:tPRESENT, text]
110
+
103
111
  when text = @ss.scan(STRING)
104
112
  @tokens.push [:tSTRING, text[1..-2]]
105
113
 
@@ -0,0 +1,6 @@
1
+ require "predicator/nodes/base_node"
2
+ require "predicator/nodes/date_node"
3
+ require "predicator/nodes/fixnum_node"
4
+ require "predicator/nodes/float_node"
5
+ require "predicator/nodes/nil_class_node"
6
+ require "predicator/nodes/string_node"
@@ -0,0 +1,53 @@
1
+ module Predicator
2
+ module Nodes
3
+ class BaseNode
4
+ attr_reader :value
5
+
6
+ def self.class_for value
7
+ class_name = "#{value.class.name}Node"
8
+ if ::Predicator::Nodes.const_defined? class_name
9
+ ::Predicator::Nodes.const_get class_name
10
+ else
11
+ raise UnknownNodeTypeError, "Unknown node type for #{value.class} (#{value.inspect})"
12
+ end
13
+ end
14
+
15
+ def initialize value
16
+ @value = value
17
+ end
18
+
19
+ def blank?
20
+ value.respond_to?(:empty?) ?
21
+ !!value.empty? :
22
+ !value
23
+ end
24
+
25
+ def present?
26
+ !blank?
27
+ end
28
+
29
+ def comparison_method
30
+ "compare_to_#{type}"
31
+ end
32
+
33
+ def compare_to_nil
34
+ raise NilValueError
35
+ end
36
+
37
+ #def compare_to_date
38
+ #end
39
+
40
+ def compare_to_fixnum
41
+ value.to_i
42
+ end
43
+
44
+ def compare_to_float
45
+ value.to_f
46
+ end
47
+
48
+ def compare_to_string
49
+ value.to_s
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,13 @@
1
+ module Predicator
2
+ module Nodes
3
+ class DateNode < BaseNode
4
+ def type
5
+ :date
6
+ end
7
+
8
+ def compare_to_date
9
+ value
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ module Predicator
2
+ module Nodes
3
+ class FixnumNode < BaseNode
4
+ def type
5
+ :fixnum
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Predicator
2
+ module Nodes
3
+ class FloatNode < BaseNode
4
+ def type
5
+ :float
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,25 @@
1
+ module Predicator
2
+ module Nodes
3
+ class NilClassNode < BaseNode
4
+ def type
5
+ :nil
6
+ end
7
+
8
+ def compare_to_date
9
+ raise NilValueError
10
+ end
11
+
12
+ def compare_to_fixnum
13
+ raise NilValueError
14
+ end
15
+
16
+ def compare_to_float
17
+ raise NilValueError
18
+ end
19
+
20
+ def compare_to_string
21
+ raise NilValueError
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,13 @@
1
+ module Predicator
2
+ module Nodes
3
+ class StringNode < BaseNode
4
+ def type
5
+ :string
6
+ end
7
+
8
+ def compare_to_date
9
+ Date.parse value
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,26 +1,7 @@
1
- require "date"
2
-
3
1
  require "predicator/generated_parser"
4
2
  require "predicator/lexer"
5
- require "predicator/variable"
6
-
7
- require "predicator/predicates/relation"
8
- require "predicator/predicates/equal"
9
- require "predicator/predicates/not_equal"
10
- require "predicator/predicates/greater_than"
11
- require "predicator/predicates/less_than"
12
- require "predicator/predicates/greater_than_or_equal"
13
- require "predicator/predicates/less_than_or_equal"
14
- require "predicator/predicates/between"
15
- require "predicator/predicates/true"
16
- require "predicator/predicates/false"
17
- require "predicator/predicates/and"
18
- require "predicator/predicates/or"
19
- require "predicator/predicates/not"
20
3
 
21
4
  module Predicator
22
- class ParseError < StandardError; end
23
-
24
5
  class Parser < GeneratedParser
25
6
  def next_token
26
7
  @lexer.next_token
@@ -33,7 +14,7 @@ module Predicator
33
14
 
34
15
  def on_error type, val, values
35
16
  super
36
- rescue Racc::ParseError => e
17
+ rescue Racc::ParseError
37
18
  trace = values.each_with_index.map{|l, i| "#{' ' * i}#{l}"}
38
19
  raise ParseError, "\nparse error on value #{val.inspect}\n#{trace.join("\n")}"
39
20
  end
@@ -5,22 +5,15 @@ prechigh
5
5
  left tAND tOR
6
6
  preclow
7
7
  token tTRUE tFALSE tSTRING tFLOAT tINTEGER tDATE tIDENTIFIER tAND tOR tBETWEEN
8
- tDOT tLPAREN tRPAREN tBANG tEQ tNEQ tLEQ tGEQ tLT tGT
8
+ tDOT tLPAREN tRPAREN tBANG tEQ tNEQ tLEQ tGEQ tLT tGT tBLANK tPRESENT
9
9
  rule
10
10
  predicate
11
- : relation_predicate
12
- | boolean_predicate
11
+ : boolean_predicate
13
12
  | logical_predicate
13
+ | relation_predicate
14
+ | method_predicate
15
+ | tLPAREN predicate tRPAREN { val[1] }
14
16
  | value tBETWEEN value tAND value { Predicator::Predicates::Between.new val[0], val[2], val[4] }
15
- | tLPAREN predicate tRPAREN
16
- ;
17
- relation_predicate
18
- : value tEQ value { Predicator::Predicates::Equal.new val[0], val[2] }
19
- | value tGT value { Predicator::Predicates::GreaterThan.new val[0], val[2] }
20
- | value tLT value { Predicator::Predicates::LessThan.new val[0], val[2] }
21
- | value tGEQ value { Predicator::Predicates::GreaterThanOrEqual.new val[0], val[2] }
22
- | value tLEQ value { Predicator::Predicates::LessThanOrEqual.new val[0], val[2] }
23
- | value tNEQ value { Predicator::Predicates::NotEqual.new val[0], val[2] }
24
17
  ;
25
18
  boolean_predicate
26
19
  : tTRUE { Predicator::Predicates::True.new }
@@ -31,6 +24,18 @@ rule
31
24
  | predicate tOR predicate { Predicator::Predicates::Or.new [val[0], val[2]] }
32
25
  | tBANG predicate { Predicator::Predicates::Not.new val[0] }
33
26
  ;
27
+ relation_predicate
28
+ : value tEQ value { Predicator::Predicates::Equal.new val[0], val[2] }
29
+ | value tGT value { Predicator::Predicates::GreaterThan.new val[0], val[2] }
30
+ | value tLT value { Predicator::Predicates::LessThan.new val[0], val[2] }
31
+ | value tGEQ value { Predicator::Predicates::GreaterThanOrEqual.new val[0], val[2] }
32
+ | value tLEQ value { Predicator::Predicates::LessThanOrEqual.new val[0], val[2] }
33
+ | value tNEQ value { Predicator::Predicates::NotEqual.new val[0], val[2] }
34
+ ;
35
+ method_predicate
36
+ : value tDOT tBLANK { Predicator::Predicates::Method.new val[0], val[2] }
37
+ | value tDOT tPRESENT { Predicator::Predicates::Method.new val[0], val[2] }
38
+ ;
34
39
  value
35
40
  : scalar
36
41
  | variable
@@ -0,0 +1,14 @@
1
+ require "predicator/predicates/relation"
2
+ require "predicator/predicates/equal"
3
+ require "predicator/predicates/not_equal"
4
+ require "predicator/predicates/greater_than"
5
+ require "predicator/predicates/less_than"
6
+ require "predicator/predicates/greater_than_or_equal"
7
+ require "predicator/predicates/less_than_or_equal"
8
+ require "predicator/predicates/between"
9
+ require "predicator/predicates/true"
10
+ require "predicator/predicates/false"
11
+ require "predicator/predicates/and"
12
+ require "predicator/predicates/or"
13
+ require "predicator/predicates/not"
14
+ require "predicator/predicates/method"
@@ -8,8 +8,16 @@ module Predicator
8
8
  end
9
9
 
10
10
  def satisfied? context=Predicator::Context.new
11
- context.value_for(value) >= context.value_for(left) &&
12
- context.value_for(value) <= context.value_for(right)
11
+ value_node = context.node_for value
12
+ left_node = context.node_for left
13
+ right_node = context.node_for right
14
+ method = "compare_to_#{value_node.type}"
15
+
16
+ left_value = left_node.send method
17
+ right_value = right_node.send method
18
+
19
+ (value_node.value >= left_value) &&
20
+ (value_node.value <= right_value)
13
21
  end
14
22
 
15
23
  def == other
@@ -1,8 +1,8 @@
1
1
  module Predicator
2
2
  module Predicates
3
3
  class Equal < Predicator::Predicates::Relation
4
- def satisfied? context=Predicator::Context.new
5
- context.value_for(left) == context.value_for(right)
4
+ def compare_values lhs, rhs
5
+ lhs == rhs
6
6
  end
7
7
  end
8
8
  end
@@ -1,8 +1,8 @@
1
1
  module Predicator
2
2
  module Predicates
3
3
  class GreaterThan < Predicator::Predicates::Relation
4
- def satisfied? context=Predicator::Context.new
5
- context.value_for(left) > context.value_for(right)
4
+ def compare_values lhs, rhs
5
+ lhs > rhs
6
6
  end
7
7
  end
8
8
  end
@@ -1,8 +1,8 @@
1
1
  module Predicator
2
2
  module Predicates
3
3
  class GreaterThanOrEqual < Predicator::Predicates::Relation
4
- def satisfied? context=Predicator::Context.new
5
- context.value_for(left) >= context.value_for(right)
4
+ def compare_values lhs, rhs
5
+ lhs >= rhs
6
6
  end
7
7
  end
8
8
  end
@@ -1,8 +1,8 @@
1
1
  module Predicator
2
2
  module Predicates
3
3
  class LessThan < Predicator::Predicates::Relation
4
- def satisfied? context=Predicator::Context.new
5
- context.value_for(left) < context.value_for(right)
4
+ def compare_values lhs, rhs
5
+ lhs < rhs
6
6
  end
7
7
  end
8
8
  end
@@ -1,8 +1,8 @@
1
1
  module Predicator
2
2
  module Predicates
3
3
  class LessThanOrEqual < Predicator::Predicates::Relation
4
- def satisfied? context=Predicator::Context.new
5
- context.value_for(left) <= context.value_for(right)
4
+ def compare_values lhs, rhs
5
+ lhs <= rhs
6
6
  end
7
7
  end
8
8
  end
@@ -0,0 +1,17 @@
1
+ module Predicator
2
+ module Predicates
3
+ class Method
4
+ attr_reader :value, :method
5
+
6
+ def initialize value, method
7
+ @value = value
8
+ @method = method
9
+ end
10
+
11
+ def satisfied? context=Predicator::Context.new
12
+ node = context.node_for value
13
+ node.send method
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,8 +1,8 @@
1
1
  module Predicator
2
2
  module Predicates
3
3
  class NotEqual < Predicator::Predicates::Relation
4
- def satisfied? context=Predicator::Context.new
5
- context.value_for(left) != context.value_for(right)
4
+ def compare_values lhs, rhs
5
+ lhs != rhs
6
6
  end
7
7
  end
8
8
  end
@@ -7,6 +7,20 @@ module Predicator
7
7
  @left, @right = left, right
8
8
  end
9
9
 
10
+ def satisfied? context=Predicator::Context.new
11
+ lhs, rhs = values_for_comparison context
12
+ compare_values lhs, rhs
13
+ rescue NilValueError
14
+ return false
15
+ end
16
+
17
+ def values_for_comparison context=Context.new
18
+ left_node = context.node_for left
19
+ right_node = context.node_for right
20
+ method = "compare_to_#{left_node.type}"
21
+ [left_node.value, right_node.send(method)]
22
+ end
23
+
10
24
  def == other
11
25
  other.kind_of?(self.class) &&
12
26
  other.left == left &&
@@ -9,7 +9,7 @@ module Predicator
9
9
 
10
10
  def value_in context
11
11
  entity_name = model.to_s
12
- entity = context.bindings[model]
12
+ entity = context.bindings[entity_name]
13
13
  if entity.nil?
14
14
  raise ArgumentError, "Unknown entity #{entity_name}"
15
15
  else
@@ -1,3 +1,3 @@
1
1
  module Predicator
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -21,6 +21,7 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency "bundler"
22
22
  spec.add_development_dependency "coveralls"
23
23
  spec.add_development_dependency "minitest", "= 5.4.2"
24
+ spec.add_development_dependency "pry"
24
25
  spec.add_development_dependency "racc"
25
26
  spec.add_development_dependency "rake"
26
27
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: predicator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - JohnnyT
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-03-11 00:00:00.000000000 Z
11
+ date: 2016-06-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - '='
53
53
  - !ruby/object:Gem::Version
54
54
  version: 5.4.2
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: racc
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -97,10 +111,19 @@ files:
97
111
  - Rakefile
98
112
  - lib/predicator.rb
99
113
  - lib/predicator/context.rb
114
+ - lib/predicator/errors.rb
100
115
  - lib/predicator/generated_parser.rb
101
116
  - lib/predicator/lexer.rb
117
+ - lib/predicator/nodes.rb
118
+ - lib/predicator/nodes/base_node.rb
119
+ - lib/predicator/nodes/date_node.rb
120
+ - lib/predicator/nodes/fixnum_node.rb
121
+ - lib/predicator/nodes/float_node.rb
122
+ - lib/predicator/nodes/nil_class_node.rb
123
+ - lib/predicator/nodes/string_node.rb
102
124
  - lib/predicator/parser.rb
103
125
  - lib/predicator/parser.y
126
+ - lib/predicator/predicates.rb
104
127
  - lib/predicator/predicates/and.rb
105
128
  - lib/predicator/predicates/between.rb
106
129
  - lib/predicator/predicates/equal.rb
@@ -109,6 +132,7 @@ files:
109
132
  - lib/predicator/predicates/greater_than_or_equal.rb
110
133
  - lib/predicator/predicates/less_than.rb
111
134
  - lib/predicator/predicates/less_than_or_equal.rb
135
+ - lib/predicator/predicates/method.rb
112
136
  - lib/predicator/predicates/not.rb
113
137
  - lib/predicator/predicates/not_equal.rb
114
138
  - lib/predicator/predicates/or.rb