siren 0.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.
@@ -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
+