predicator 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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