siren 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,184 @@
1
+ module Siren
2
+ grammar JsonQuery
3
+ rule expression
4
+ sum / product / divmod / atom
5
+ end
6
+
7
+ rule boolean_expression
8
+ or_expression / and_expression / comparison / boolean_atom
9
+ end
10
+
11
+ rule or_expression
12
+ first:and_expression "|" second:or_expression <Or> / and_expression
13
+ end
14
+
15
+ rule and_expression
16
+ first:comparison "&" second:and_expression <And> / comparison
17
+ end
18
+
19
+ rule comparison
20
+ first:expression comparator second:expression <Comparison> / boolean_atom
21
+ end
22
+
23
+ rule boolean_atom
24
+ space ("(" boolean_expression ")" / boolean) space <BooleanAtom>
25
+ end
26
+
27
+ rule sum
28
+ first:product operator:(add / subtract) second:sum <Sum> / product
29
+ end
30
+
31
+ rule product
32
+ first:divmod operator:(times / divide) second:product <Product> / divmod
33
+ end
34
+
35
+ rule divmod
36
+ first:atom '%' second:divmod <Divmod> / atom
37
+ end
38
+
39
+ rule atom
40
+ space ("(" expression ")" / query / number / string / boolean / null) space <Atom>
41
+ end
42
+
43
+ rule times
44
+ "*" <Multiplication>
45
+ end
46
+
47
+ rule divide
48
+ "/" <Division>
49
+ end
50
+
51
+ rule add
52
+ "+" <Addition>
53
+ end
54
+
55
+ rule subtract
56
+ "-" <Subtraction>
57
+ end
58
+
59
+ rule comparator
60
+ (not_equal / lte / gte / equal / match / lt / gt) <Comparator>
61
+ end
62
+
63
+ rule equal
64
+ "=" <Equal>
65
+ end
66
+
67
+ rule match
68
+ "~" <Match>
69
+ end
70
+
71
+ rule not_equal
72
+ "!=" <NotEqual>
73
+ end
74
+
75
+ rule lt
76
+ "<" <LessThan>
77
+ end
78
+
79
+ rule lte
80
+ "<=" <LessThanOrEqual>
81
+ end
82
+
83
+ rule gt
84
+ ">" <GreaterThan>
85
+ end
86
+
87
+ rule gte
88
+ ">=" <GreaterThanOrEqual>
89
+ end
90
+
91
+ rule string
92
+ "'" ('\\' ("'" / '\\' / '/' / 'b' / 'f' / 'n' / 'r' / 't' / 'u' hex hex hex hex) / [^\'\\])* "'" <String>
93
+ end
94
+
95
+ rule number
96
+ "-"? ("0" / [1-9] digit*) ("." digit+)? ([eE] [+-]? digit+)? <Number>
97
+ end
98
+
99
+ rule digit
100
+ [0-9]
101
+ end
102
+
103
+ rule boolean
104
+ (true / false) <Boolean>
105
+ end
106
+
107
+ rule true
108
+ "true" <True>
109
+ end
110
+
111
+ rule false
112
+ "false" <False>
113
+ end
114
+
115
+ rule null
116
+ "null" <Null>
117
+ end
118
+
119
+ rule space
120
+ " "*
121
+ end
122
+
123
+ rule query
124
+ identifier filter* <Query>
125
+ end
126
+
127
+ rule identifier
128
+ (root / current / symbol) <Identifier>
129
+ end
130
+
131
+ rule root
132
+ "$" <Root>
133
+ end
134
+
135
+ rule current
136
+ "@" <Current>
137
+ end
138
+
139
+ rule symbol
140
+ [A-Za-z$_] [A-Za-z0-9$_]* <Symbol>
141
+ end
142
+
143
+ rule filter
144
+ (slice_access / recursive_access / field_access / boolean_filter / map_filter / sort_filter) <Filter>
145
+ end
146
+
147
+ rule slice_access
148
+ "[" head:number ":" tail:number step:(":" number)? "]" <SliceAccess>
149
+ end
150
+
151
+ rule recursive_access
152
+ ".." symbol <RecursiveAccess>
153
+ end
154
+
155
+ rule field_access
156
+ ("." (symbol / all) / "[" (field_access_expression / all) "]") <FieldAccess>
157
+ end
158
+
159
+ rule field_access_expression
160
+ first:expression others:("," expression)* <FieldAccessExpression>
161
+ end
162
+
163
+ rule all
164
+ "*" <AllFilter>
165
+ end
166
+
167
+ rule boolean_filter
168
+ recursive:".."? "[?" boolean_expression "]" <BooleanFilter>
169
+ end
170
+
171
+ rule map_filter
172
+ "[=" expression "]" <MapFilter>
173
+ end
174
+
175
+ rule sort_filter
176
+ "[" first:(sorter expression) others:("," sorter expression)* "]" <SortFilter>
177
+ end
178
+
179
+ rule sorter
180
+ space ("/" / "\\") space <Sorter>
181
+ end
182
+ end
183
+ end
184
+
@@ -0,0 +1,333 @@
1
+ module Siren
2
+ module JsonQuery
3
+
4
+ module Query
5
+ def value(root, symbols, current = nil)
6
+ object = identifier.value(root, symbols, current)
7
+ filters.inject(object) { |value, filter| filter.value(value, root, symbols, current) }
8
+ end
9
+
10
+ def filters
11
+ elements[1].elements
12
+ end
13
+ end
14
+
15
+ module Identifier
16
+ end
17
+
18
+ module Root
19
+ def value(root, symbols, current = nil)
20
+ root
21
+ end
22
+ end
23
+
24
+ module Current
25
+ def value(root, symbols, current = nil)
26
+ current
27
+ end
28
+ end
29
+
30
+ module Symbol
31
+ def value(root, symbols, current = nil)
32
+ symbols[text_value] || FieldAccess.access(current, text_value)
33
+ end
34
+ end
35
+
36
+ module Filter
37
+ end
38
+
39
+ module SliceAccess
40
+ def value(object, root, symbols, current = nil)
41
+ a, b = *[head, tail].map { |x| x.value(root, symbols, current) }
42
+ s = step.respond_to?(:number) ? step.number.value(root, symbols, current) : 1
43
+ result = []
44
+ while a <= b
45
+ result << object[a]
46
+ a += s
47
+ end
48
+ result
49
+ end
50
+ end
51
+
52
+ module RecursiveAccess
53
+ def value(object, root, symbols, current = nil)
54
+ name = elements[1].text_value
55
+ results, visited = [], Set.new
56
+
57
+ visitor = lambda do |visitee|
58
+ return unless visited.add?(visitee)
59
+ Siren.each(visitee) do |index, value|
60
+ results << value if index == name
61
+ visitor.call(value)
62
+ end
63
+ end
64
+
65
+ visitor.call(object)
66
+ results
67
+ end
68
+ end
69
+
70
+ module FieldAccess
71
+ def index(object, root, symbols, current = nil)
72
+ element = elements[1]
73
+ return [element.text_value] if Symbol === element
74
+ element.value(root, symbols, object)
75
+ end
76
+
77
+ def value(object, root, symbols, current = nil)
78
+ indexes = index(object, root, symbols, current)
79
+ indexes.size == 1 ?
80
+ FieldAccess.access(object, indexes.first) :
81
+ indexes.map { |i| FieldAccess.access(object, i) }
82
+ end
83
+
84
+ def self.access(object, index)
85
+ return (Hash === object ? object.values : object) if index == :*
86
+ return object[index] if Array === object and Numeric === index
87
+
88
+ if Hash === object
89
+ key = [index, index.to_s, index.to_sym].find { |i| object.has_key?(i) }
90
+ return object[key] if key
91
+ end
92
+
93
+ return object.__send__(index) if object.respond_to?(index)
94
+ object.instance_variable_get("@#{ index }")
95
+ end
96
+ end
97
+
98
+ module FieldAccessExpression
99
+ def value(root, symbols, current = nil)
100
+ exprs = [first] + others.elements.map { |e| e.expression }
101
+ exprs.map { |e| e.value(root, symbols, current) }
102
+ end
103
+ end
104
+
105
+ module AllFilter
106
+ def value(root, symbols, current = nil)
107
+ [:*]
108
+ end
109
+ end
110
+
111
+ module BooleanFilter
112
+ def value(list, root, symbols, current = nil)
113
+ results, visited = [], Set.new
114
+
115
+ visitor = lambda do |visitee|
116
+ return unless visited.add?(visitee)
117
+ Siren.each(visitee) do |index, value|
118
+ begin
119
+ results << value if boolean_expression.value(root, symbols, value)
120
+ rescue
121
+ end
122
+ visitor.call(value) if recursive.text_value == '..'
123
+ end
124
+ end
125
+
126
+ visitor.call(list)
127
+ results
128
+ end
129
+ end
130
+
131
+ module MapFilter
132
+ def value(list, root, symbols, current = nil)
133
+ list.map do |object|
134
+ expression.value(root, symbols, object)
135
+ end
136
+ end
137
+ end
138
+
139
+ module SortFilter
140
+ def value(list, root, symbols, current = nil)
141
+ sorters = [[first.expression, first.sorter]] +
142
+ others.elements.map { |e| [e.expression, e.sorter] }
143
+
144
+ list.sort do |a, b|
145
+ sorters.inject(0) do |outcome, sorter|
146
+ if outcome.nonzero?
147
+ outcome
148
+ else
149
+ f, g = sorter[0].value(root, symbols, a), sorter[0].value(root, symbols, b)
150
+ sorter[1].value * (f <=> g)
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
156
+
157
+ module Sorter
158
+ ORDERS = {"/" => 1, "\\" => -1}
159
+
160
+ def value
161
+ ORDERS[elements[1].text_value]
162
+ end
163
+ end
164
+
165
+ module And
166
+ def value(root, symbols, current = nil)
167
+ first.value(root, symbols, current) && second.value(root, symbols, current)
168
+ end
169
+ end
170
+
171
+ module Or
172
+ def value(root, symbols, current = nil)
173
+ first.value(root, symbols, current) || second.value(root, symbols, current)
174
+ end
175
+ end
176
+
177
+ module Comparison
178
+ def value(root, symbols, current = nil)
179
+ comparator.value(first.value(root, symbols, current), second.value(root, symbols, current))
180
+ end
181
+ end
182
+
183
+ module BooleanAtom
184
+ def value(root, symbols, current = nil)
185
+ element = elements[1]
186
+ return element.boolean_expression.value(root, symbols, current) if element.respond_to?(:boolean_expression)
187
+ element.value(root, symbols, current)
188
+ end
189
+ end
190
+
191
+ module Divmod
192
+ def value(root, symbols, current = nil)
193
+ first.value(root, symbols, current) % second.value(root, symbols, current)
194
+ end
195
+ end
196
+
197
+ module Product
198
+ def value(root, symbols, current = nil)
199
+ operator.value(first.value(root, symbols, current), second.value(root, symbols, current))
200
+ end
201
+ end
202
+
203
+ module Sum
204
+ def value(root, symbols, current = nil)
205
+ operator.value(first.value(root, symbols, current), second.value(root, symbols, current))
206
+ end
207
+ end
208
+
209
+ module Atom
210
+ def value(root, symbols, current = nil)
211
+ element = elements[1]
212
+ return element.expression.value(root, symbols, current) if element.respond_to?(:expression)
213
+ element.value(root, symbols, current)
214
+ end
215
+ end
216
+
217
+ module Multiplication
218
+ def value(expr1, expr2)
219
+ expr1 * expr2
220
+ end
221
+ end
222
+
223
+ module Division
224
+ def value(expr1, expr2)
225
+ expr1 / expr2
226
+ end
227
+ end
228
+
229
+ module Addition
230
+ def value(expr1, expr2)
231
+ String === expr1 || String === expr2 ?
232
+ expr1.to_s + expr2.to_s :
233
+ expr1 + expr2
234
+ end
235
+ end
236
+
237
+ module Subtraction
238
+ def value(expr1, expr2)
239
+ expr1 - expr2
240
+ end
241
+ end
242
+
243
+ module Comparator
244
+ end
245
+
246
+ module Equal
247
+ def value(expr1, expr2)
248
+ return expr1 == expr2 unless expr2.respond_to?(:gsub)
249
+ expr1 =~ %r{^#{Match.convert(expr2)}$}
250
+ end
251
+ end
252
+
253
+ module Match
254
+ def value(expr1, expr2)
255
+ return expr1 == expr2 unless expr2.respond_to?(:gsub)
256
+ expr1 =~ %r{^#{Match.convert(expr2)}$}i
257
+ end
258
+
259
+ def self.convert(string)
260
+ string.gsub(/([\.\+\[\]\{\}\(\)\^\$])/) { "\\#{$1}" }.
261
+ gsub('*', '.*').gsub('?', '.')
262
+ end
263
+ end
264
+
265
+ module NotEqual
266
+ def value(expr1, expr2)
267
+ expr1 != expr2
268
+ end
269
+ end
270
+
271
+ module LessThan
272
+ def value(expr1, expr2)
273
+ expr1 < expr2
274
+ end
275
+ end
276
+
277
+ module LessThanOrEqual
278
+ def value(expr1, expr2)
279
+ expr1 <= expr2
280
+ end
281
+ end
282
+
283
+ module GreaterThan
284
+ def value(expr1, expr2)
285
+ expr1 > expr2
286
+ end
287
+ end
288
+
289
+ module GreaterThanOrEqual
290
+ def value(expr1, expr2)
291
+ expr1 >= expr2
292
+ end
293
+ end
294
+
295
+ module String
296
+ def value(root, symbols, current = nil)
297
+ @value ||= eval(text_value)
298
+ end
299
+ end
300
+
301
+ module Number
302
+ def value(root, symbols, current = nil)
303
+ @value ||= eval(text_value)
304
+ end
305
+ end
306
+
307
+ module Boolean
308
+ def value(root, symbols, current = nil)
309
+ data.value
310
+ end
311
+ end
312
+
313
+ module True
314
+ def value(root, symbols, current = nil)
315
+ true
316
+ end
317
+ end
318
+
319
+ module False
320
+ def value(root, symbols, current = nil)
321
+ false
322
+ end
323
+ end
324
+
325
+ module Null
326
+ def value(root, symbols, current = nil)
327
+ nil
328
+ end
329
+ end
330
+
331
+ end
332
+ end
333
+