json_select 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitmodules +3 -0
- data/.travis.yml +1 -1
- data/Gemfile +1 -0
- data/README.md +52 -1
- data/Rakefile +12 -1
- data/lib/json_select/helpers/depth.rb +6 -2
- data/lib/json_select/helpers/key.rb +6 -2
- data/lib/json_select/helpers/position.rb +15 -7
- data/lib/json_select/helpers/size.rb +14 -6
- data/lib/json_select/helpers/type.rb +8 -4
- data/lib/json_select/selector.rb +47 -11
- data/lib/json_select/selector_parser.rb +179 -44
- data/lib/json_select/selector_parser.tt +9 -2
- data/lib/json_select/version.rb +1 -1
- data/spec/conformance_spec.rb +94 -38
- data/spec/fixtures/{basic_children.selector → parser/level_1/basic_children.output} +0 -0
- data/spec/fixtures/parser/level_1/basic_children.selector +1 -0
- data/spec/fixtures/{basic_combination.selector → parser/level_1/basic_combination.output} +0 -0
- data/spec/fixtures/parser/level_1/basic_combination.selector +1 -0
- data/spec/fixtures/parser/level_1/basic_first-child.output +1 -0
- data/spec/fixtures/{basic_first-child.selector → parser/level_1/basic_first-child.selector} +0 -0
- data/spec/fixtures/parser/level_1/basic_grouping.output +1 -0
- data/spec/fixtures/{basic_grouping.selector → parser/level_1/basic_grouping.selector} +0 -0
- data/spec/fixtures/parser/level_1/basic_id.output +1 -0
- data/spec/fixtures/{basic_id.selector → parser/level_1/basic_id.selector} +0 -0
- data/spec/fixtures/parser/level_1/basic_id_multiple.output +1 -0
- data/spec/fixtures/{basic_id_multiple.selector → parser/level_1/basic_id_multiple.selector} +0 -0
- data/spec/fixtures/parser/level_1/basic_id_quotes.output +1 -0
- data/spec/fixtures/{basic_id_quotes.selector → parser/level_1/basic_id_quotes.selector} +0 -0
- data/spec/fixtures/parser/level_1/basic_id_with_type.output +1 -0
- data/spec/fixtures/{basic_id_with_type.selector → parser/level_1/basic_id_with_type.selector} +0 -0
- data/spec/fixtures/parser/level_1/basic_last-child.output +1 -0
- data/spec/fixtures/{basic_last-child.selector → parser/level_1/basic_last-child.selector} +0 -0
- data/spec/fixtures/parser/level_1/basic_nth-child-2.output +1 -0
- data/spec/fixtures/{basic_nth-child-2.selector → parser/level_1/basic_nth-child-2.selector} +0 -0
- data/spec/fixtures/parser/level_1/basic_nth-child.output +1 -0
- data/spec/fixtures/{basic_nth-child.selector → parser/level_1/basic_nth-child.selector} +0 -0
- data/spec/fixtures/parser/level_1/basic_nth-last-child.output +1 -0
- data/spec/fixtures/{basic_nth-last-child.selector → parser/level_1/basic_nth-last-child.selector} +0 -0
- data/spec/fixtures/parser/level_1/basic_root_pseudo.output +1 -0
- data/spec/fixtures/{basic_root_pseudo.selector → parser/level_1/basic_root_pseudo.selector} +0 -0
- data/spec/fixtures/{basic_type.selector → parser/level_1/basic_type.output} +0 -0
- data/spec/fixtures/parser/level_1/basic_type.selector +1 -0
- data/spec/fixtures/{basic_type2.selector → parser/level_1/basic_type2.output} +0 -0
- data/spec/fixtures/parser/level_1/basic_type2.selector +1 -0
- data/spec/fixtures/parser/level_1/basic_type3.output +1 -0
- data/spec/fixtures/{basic_type3.selector → parser/level_1/basic_type3.selector} +0 -0
- data/spec/fixtures/parser/level_1/basic_universal.output +1 -0
- data/spec/fixtures/{basic_universal.selector → parser/level_1/basic_universal.selector} +0 -0
- data/spec/fixtures/parser/level_3/basic_has-sans-paren.output +1 -0
- data/spec/fixtures/parser/level_3/basic_has-sans-paren.selector +2 -0
- data/spec/fixtures/parser/level_3/basic_has-whitespace.output +1 -0
- data/spec/fixtures/parser/level_3/basic_has-whitespace.selector +3 -0
- data/spec/fixtures/parser/level_3/basic_has.output +1 -0
- data/spec/fixtures/parser/level_3/basic_has.selector +1 -0
- data/spec/parser_spec.rb +52 -0
- metadata +123 -148
- data/spec/fixtures/README.md +0 -14
- data/spec/fixtures/alltests.txt +0 -31
- data/spec/fixtures/basic.json +0 -31
- data/spec/fixtures/basic.xml +0 -31
- data/spec/fixtures/basic_children.ast +0 -14
- data/spec/fixtures/basic_children.output +0 -1
- data/spec/fixtures/basic_combination.ast +0 -13
- data/spec/fixtures/basic_combination.output +0 -1
- data/spec/fixtures/basic_first-child.ast +0 -11
- data/spec/fixtures/basic_first-child.output +0 -2
- data/spec/fixtures/basic_grouping.ast +0 -22
- data/spec/fixtures/basic_grouping.output +0 -4
- data/spec/fixtures/basic_id.ast +0 -7
- data/spec/fixtures/basic_id.output +0 -1
- data/spec/fixtures/basic_id_multiple.ast +0 -7
- data/spec/fixtures/basic_id_multiple.output +0 -3
- data/spec/fixtures/basic_id_quotes.ast +0 -7
- data/spec/fixtures/basic_id_quotes.output +0 -2
- data/spec/fixtures/basic_id_with_type.ast +0 -10
- data/spec/fixtures/basic_id_with_type.output +0 -1
- data/spec/fixtures/basic_last-child.ast +0 -11
- data/spec/fixtures/basic_last-child.output +0 -2
- data/spec/fixtures/basic_nth-child-2.ast +0 -11
- data/spec/fixtures/basic_nth-child-2.output +0 -4
- data/spec/fixtures/basic_nth-child.ast +0 -11
- data/spec/fixtures/basic_nth-child.output +0 -3
- data/spec/fixtures/basic_nth-last-child.ast +0 -11
- data/spec/fixtures/basic_nth-last-child.output +0 -2
- data/spec/fixtures/basic_root_pseudo.ast +0 -6
- data/spec/fixtures/basic_root_pseudo.output +0 -31
- data/spec/fixtures/basic_type.ast +0 -7
- data/spec/fixtures/basic_type.output +0 -14
- data/spec/fixtures/basic_type2.ast +0 -7
- data/spec/fixtures/basic_type2.output +0 -1
- data/spec/fixtures/basic_type3.ast +0 -7
- data/spec/fixtures/basic_type3.output +0 -47
- data/spec/fixtures/basic_universal.ast +0 -5
- data/spec/fixtures/basic_universal.output +0 -86
data/.gitmodules
ADDED
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -53,8 +53,59 @@ JSONSelect('string:first-child').match(json) # => "window"
|
|
53
53
|
JSONSelect('string:first-child').matches(json) # => ["window", "beer"]
|
54
54
|
```
|
55
55
|
|
56
|
+
## Language support
|
57
|
+
|
58
|
+
✓ — **Level 1** — `*`<br>
|
59
|
+
Any node
|
60
|
+
|
61
|
+
✓ — **Level 1** — `T`<br>
|
62
|
+
A node of type `T`, where `T` is one `string`, `number`, `object`, `array`, `boolean`, or `null`
|
63
|
+
|
64
|
+
✓ — **Level 1** — `T.key`<br>
|
65
|
+
A node of type `T` which is the child of an object and is the value its parents key property
|
66
|
+
|
67
|
+
✓ — **Level 1** — `T."complex key"`<br>
|
68
|
+
Same as previous, but with property name specified as a JSON string
|
69
|
+
|
70
|
+
✓ — **Level 1** — `T:root`<br>
|
71
|
+
A node of type `T` which is the root of the JSON document
|
72
|
+
|
73
|
+
✓ — **Level 1** — `T:nth-child(n)`<br>
|
74
|
+
A node of type `T` which is the nth child of an array parent
|
75
|
+
|
76
|
+
✓ — **Level 2** — `T:nth-last-child(n)`<br>
|
77
|
+
A node of type `T` which is the nth child of an array parent counting from the end
|
78
|
+
|
79
|
+
✓ — **Level 1** — `T:first-child`<br>
|
80
|
+
A node of type `T` which is the first child of an array parent (equivalent to `T:nth-child(1)`)
|
81
|
+
|
82
|
+
✓ — **Level 2** — `T:last-child`<br>
|
83
|
+
A node of type `T` which is the last child of an array parent (equivalent to `T:nth-last-child(1)`)
|
84
|
+
|
85
|
+
✓ — **Level 2** — `T:only-child`<br>
|
86
|
+
A node of type `T` which is the only child of an array parent
|
87
|
+
|
88
|
+
✓ — **Level 2** — `T:empty`<br>
|
89
|
+
A node of type `T` which is an array or object with no child
|
90
|
+
|
91
|
+
✓ — **Level 1** — `T U`<br>
|
92
|
+
A node of type `U` with an ancestor of type `T`
|
93
|
+
|
94
|
+
✓ — **Level 1** — `T > U`<br>
|
95
|
+
A node of type `U` with a parent of type `T`
|
96
|
+
|
97
|
+
✗ — **Level 2** — `T ~ U`<br>
|
98
|
+
A node of type `U` with a sibling of type `T`
|
99
|
+
|
100
|
+
✓ — **Level 1** — `S1, S2`<br>
|
101
|
+
Any node which matches either selector `S1` or `S2`
|
102
|
+
|
103
|
+
✗ — **Level 3** — `T:has(S)`<br>
|
104
|
+
A node of type `T` which has a child node satisfying the selector `S`
|
105
|
+
|
106
|
+
|
56
107
|
## Note on Patches/Pull Requests
|
57
|
-
|
108
|
+
|
58
109
|
* Fork the project.
|
59
110
|
* Make your feature addition or bug fix.
|
60
111
|
* Add tests for it. This is important so I don't break it in a future version
|
data/Rakefile
CHANGED
@@ -9,6 +9,11 @@ RSpec::Core::RakeTask.new do |t|
|
|
9
9
|
'-r', File.expand_path("../spec/spec_helper.rb", __FILE__)]
|
10
10
|
end
|
11
11
|
|
12
|
+
task :checkout_conformance_tests do
|
13
|
+
sh "git submodule init"
|
14
|
+
sh "git submodule update"
|
15
|
+
end
|
16
|
+
|
12
17
|
task :build_parser do
|
13
18
|
sh "bundle exec tt lib/json_select/selector_parser.tt -o lib/json_select/selector_parser.rb"
|
14
19
|
|
@@ -18,6 +23,12 @@ task :build_parser do
|
|
18
23
|
File.open(path, 'w+') { |f| f.write src }
|
19
24
|
end
|
20
25
|
|
21
|
-
task :
|
26
|
+
task :build do
|
27
|
+
h = Bundler::GemHelper.instance
|
28
|
+
path = Dir[File.join(h.base, "pkg", "#{h.gemspec.name}-*.gem")].sort_by{|f| File.mtime(f)}.last
|
29
|
+
sh "gem sign #{path}"
|
30
|
+
end
|
31
|
+
|
32
|
+
task :spec => [:checkout_conformance_tests, :build_parser]
|
22
33
|
task :build => :build_parser
|
23
34
|
task :default => :spec
|
@@ -1,24 +1,32 @@
|
|
1
1
|
module JSONSelect::PositionHelpers
|
2
|
-
|
2
|
+
|
3
3
|
def nth_child(object, test, key, idx, size, depth)
|
4
4
|
return false unless idx and size
|
5
|
-
|
5
|
+
|
6
6
|
idx += 1
|
7
|
-
|
7
|
+
|
8
8
|
a = test[:a]
|
9
9
|
b = test[:b]
|
10
|
-
|
10
|
+
|
11
11
|
if a == 0
|
12
12
|
(b == idx)
|
13
13
|
else
|
14
14
|
(((idx - b) % a) == 0) and ((idx * a + b) >= 0)
|
15
15
|
end
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
|
+
def format_nth_child(test)
|
19
|
+
":nth-child(#{test[:a]}n#{test[:b]})"
|
20
|
+
end
|
21
|
+
|
18
22
|
def nth_last_child(object, test, key, idx, size, depth)
|
19
23
|
return false unless idx and size
|
20
|
-
|
24
|
+
|
21
25
|
nth_child(object, test, key, (size - idx) - 1, size, depth)
|
22
26
|
end
|
23
|
-
|
27
|
+
|
28
|
+
def format_nth_last_child(test)
|
29
|
+
":nth-last-child(#{test[:a]}n#{test[:b]})"
|
30
|
+
end
|
31
|
+
|
24
32
|
end
|
@@ -1,14 +1,18 @@
|
|
1
1
|
module JSONSelect::SizeHelpers
|
2
|
-
|
2
|
+
|
3
3
|
def only_child(object, test, key, idx, size, depth)
|
4
4
|
return false unless size
|
5
|
-
|
5
|
+
|
6
6
|
size == 1
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
|
+
def format_only_child(test)
|
10
|
+
":only-child"
|
11
|
+
end
|
12
|
+
|
9
13
|
def empty(object, test, key, idx, size, depth)
|
10
14
|
return false unless size
|
11
|
-
|
15
|
+
|
12
16
|
case object
|
13
17
|
when Array then return object.empty?
|
14
18
|
else
|
@@ -17,8 +21,12 @@ module JSONSelect::SizeHelpers
|
|
17
21
|
return true
|
18
22
|
end
|
19
23
|
end
|
20
|
-
|
24
|
+
|
21
25
|
return false
|
22
26
|
end
|
23
|
-
|
27
|
+
|
28
|
+
def format_empty(test)
|
29
|
+
":empty"
|
30
|
+
end
|
31
|
+
|
24
32
|
end
|
@@ -1,20 +1,24 @@
|
|
1
1
|
module JSONSelect::TypeHelpers
|
2
|
-
|
2
|
+
|
3
3
|
def instance_of_type(object, test, key, idx, size, depth)
|
4
4
|
test[:n] == type_of(object)
|
5
5
|
end
|
6
6
|
|
7
|
+
def format_instance_of_type(test)
|
8
|
+
test[:n].to_s
|
9
|
+
end
|
10
|
+
|
7
11
|
private
|
8
12
|
|
9
13
|
def type_of(object)
|
10
14
|
if object.respond_to?(:json_select_each)
|
11
15
|
return 'array'
|
12
16
|
end
|
13
|
-
|
17
|
+
|
14
18
|
if object.respond_to?(:json_select_each_pair)
|
15
19
|
return 'object'
|
16
20
|
end
|
17
|
-
|
21
|
+
|
18
22
|
case object
|
19
23
|
when Hash then 'object'
|
20
24
|
when Array then 'array'
|
@@ -27,5 +31,5 @@ private
|
|
27
31
|
else raise "Invalid object of class #{object.class} for JSONSelect: #{object.inspect}"
|
28
32
|
end
|
29
33
|
end
|
30
|
-
|
34
|
+
|
31
35
|
end
|
data/lib/json_select/selector.rb
CHANGED
@@ -42,7 +42,7 @@ class JSONSelect
|
|
42
42
|
raise ArgumentError, "Expected a string for ast"
|
43
43
|
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
46
|
@helpers = Module.new
|
47
47
|
@helpers.send(:extend,
|
48
48
|
JSONSelect::KeyHelpers,
|
@@ -50,7 +50,7 @@ class JSONSelect
|
|
50
50
|
JSONSelect::SizeHelpers,
|
51
51
|
JSONSelect::DepthHelpers,
|
52
52
|
JSONSelect::PositionHelpers)
|
53
|
-
|
53
|
+
|
54
54
|
@helper_methods = {}
|
55
55
|
(@helpers.public_methods - Module.public_methods).map do |name|
|
56
56
|
@helper_methods[name.to_sym] = @helpers.method(name)
|
@@ -90,6 +90,42 @@ class JSONSelect
|
|
90
90
|
|
91
91
|
alias_method :===, :test
|
92
92
|
|
93
|
+
def to_s
|
94
|
+
selectors = @ast
|
95
|
+
selectors = (selectors[0] == ',' ? selectors[1..-1] : [selectors])
|
96
|
+
|
97
|
+
selectors.map do |selector|
|
98
|
+
selector.map do |part|
|
99
|
+
case part
|
100
|
+
|
101
|
+
when :>
|
102
|
+
'>'
|
103
|
+
|
104
|
+
when Hash
|
105
|
+
tests = (part[:tests].empty? ? ['*'] : part[:tests])
|
106
|
+
|
107
|
+
tests.map do |test|
|
108
|
+
case test
|
109
|
+
|
110
|
+
when '*'
|
111
|
+
'*'
|
112
|
+
|
113
|
+
when Hash
|
114
|
+
@helpers.send("format_#{test[:f]}", test)
|
115
|
+
|
116
|
+
end
|
117
|
+
end.join('')
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
end.join(' ')
|
122
|
+
end.join(', ')
|
123
|
+
end
|
124
|
+
|
125
|
+
def inspect
|
126
|
+
"#<JSONSelect (#{to_s})>"
|
127
|
+
end
|
128
|
+
|
93
129
|
private
|
94
130
|
|
95
131
|
def _each(selector, object, id, number, total, depth, &block)
|
@@ -129,21 +165,21 @@ private
|
|
129
165
|
object.json_select_each do |value|
|
130
166
|
children << value
|
131
167
|
end
|
132
|
-
|
168
|
+
|
133
169
|
a1.unshift(',')
|
134
170
|
size = children.size
|
135
|
-
|
171
|
+
|
136
172
|
children.each_with_index do |child, idx|
|
137
173
|
_each(a1, child, nil, idx, size, depth + 1, &block)
|
138
174
|
end
|
139
|
-
|
175
|
+
|
140
176
|
elsif object.respond_to?(:json_select_each_pair)
|
141
177
|
a1.unshift(',')
|
142
|
-
|
178
|
+
|
143
179
|
object.json_select_each_pair do |key, child|
|
144
180
|
_each(a1, child, key, nil, nil, depth + 1, &block)
|
145
181
|
end
|
146
|
-
|
182
|
+
|
147
183
|
end
|
148
184
|
end
|
149
185
|
end
|
@@ -163,7 +199,7 @@ private
|
|
163
199
|
if test[:f] == :is_root
|
164
200
|
has_root_test = true
|
165
201
|
end
|
166
|
-
|
202
|
+
|
167
203
|
if match
|
168
204
|
match = !!@helper_methods[test[:f].to_sym].call(object, test, id, number, total, depth)
|
169
205
|
end
|
@@ -183,16 +219,16 @@ private
|
|
183
219
|
unless match
|
184
220
|
return [match, selectors]
|
185
221
|
end
|
186
|
-
|
222
|
+
|
187
223
|
# continue search for decendants
|
188
224
|
unless selector[0] == :>
|
189
225
|
match = false
|
190
226
|
selectors.push selector[1..-1]
|
191
227
|
return [match, selectors]
|
192
228
|
end
|
193
|
-
|
229
|
+
|
194
230
|
# continue search for children
|
195
|
-
if selector.length > 2
|
231
|
+
if selector.length > 2
|
196
232
|
match = false
|
197
233
|
selectors.push selector[2..-1]
|
198
234
|
end
|
@@ -619,7 +619,18 @@ module JSONSelect::Selector
|
|
619
619
|
end
|
620
620
|
|
621
621
|
def e
|
622
|
-
elements[
|
622
|
+
elements[5]
|
623
|
+
end
|
624
|
+
|
625
|
+
end
|
626
|
+
|
627
|
+
module Pseudo2
|
628
|
+
def a
|
629
|
+
elements[1]
|
630
|
+
end
|
631
|
+
|
632
|
+
def s
|
633
|
+
elements[5]
|
623
634
|
end
|
624
635
|
|
625
636
|
end
|
@@ -669,53 +680,66 @@ module JSONSelect::Selector
|
|
669
680
|
end
|
670
681
|
s4 << r5
|
671
682
|
if r5
|
672
|
-
r6 =
|
683
|
+
r6 = _nt_positional_pseudo_function_name
|
673
684
|
s4 << r6
|
674
685
|
if r6
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
686
|
+
s7, i7 = [], index
|
687
|
+
loop do
|
688
|
+
r8 = _nt_ws
|
689
|
+
if r8
|
690
|
+
s7 << r8
|
691
|
+
else
|
692
|
+
break
|
693
|
+
end
|
681
694
|
end
|
695
|
+
r7 = instantiate_node(SyntaxNode,input, i7...index, s7)
|
682
696
|
s4 << r7
|
683
697
|
if r7
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
break
|
691
|
-
end
|
698
|
+
if has_terminal?('(', false, index)
|
699
|
+
r9 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
700
|
+
@index += 1
|
701
|
+
else
|
702
|
+
terminal_parse_failure('(')
|
703
|
+
r9 = nil
|
692
704
|
end
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
705
|
+
s4 << r9
|
706
|
+
if r9
|
707
|
+
s10, i10 = [], index
|
708
|
+
loop do
|
709
|
+
r11 = _nt_ws
|
710
|
+
if r11
|
711
|
+
s10 << r11
|
712
|
+
else
|
713
|
+
break
|
714
|
+
end
|
715
|
+
end
|
716
|
+
r10 = instantiate_node(SyntaxNode,input, i10...index, s10)
|
697
717
|
s4 << r10
|
698
718
|
if r10
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
if r11
|
711
|
-
if has_terminal?(')', false, index)
|
712
|
-
r13 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
713
|
-
@index += 1
|
714
|
-
else
|
715
|
-
terminal_parse_failure(')')
|
716
|
-
r13 = nil
|
719
|
+
r12 = _nt_expression
|
720
|
+
s4 << r12
|
721
|
+
if r12
|
722
|
+
s13, i13 = [], index
|
723
|
+
loop do
|
724
|
+
r14 = _nt_ws
|
725
|
+
if r14
|
726
|
+
s13 << r14
|
727
|
+
else
|
728
|
+
break
|
729
|
+
end
|
717
730
|
end
|
731
|
+
r13 = instantiate_node(SyntaxNode,input, i13...index, s13)
|
718
732
|
s4 << r13
|
733
|
+
if r13
|
734
|
+
if has_terminal?(')', false, index)
|
735
|
+
r15 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
736
|
+
@index += 1
|
737
|
+
else
|
738
|
+
terminal_parse_failure(')')
|
739
|
+
r15 = nil
|
740
|
+
end
|
741
|
+
s4 << r15
|
742
|
+
end
|
719
743
|
end
|
720
744
|
end
|
721
745
|
end
|
@@ -732,8 +756,95 @@ module JSONSelect::Selector
|
|
732
756
|
if r4
|
733
757
|
r0 = r4
|
734
758
|
else
|
735
|
-
|
736
|
-
|
759
|
+
i16, s16 = index, []
|
760
|
+
if has_terminal?(':', false, index)
|
761
|
+
r17 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
762
|
+
@index += 1
|
763
|
+
else
|
764
|
+
terminal_parse_failure(':')
|
765
|
+
r17 = nil
|
766
|
+
end
|
767
|
+
s16 << r17
|
768
|
+
if r17
|
769
|
+
r18 = _nt_subselector_pseudo_function_name
|
770
|
+
s16 << r18
|
771
|
+
if r18
|
772
|
+
s19, i19 = [], index
|
773
|
+
loop do
|
774
|
+
r20 = _nt_ws
|
775
|
+
if r20
|
776
|
+
s19 << r20
|
777
|
+
else
|
778
|
+
break
|
779
|
+
end
|
780
|
+
end
|
781
|
+
r19 = instantiate_node(SyntaxNode,input, i19...index, s19)
|
782
|
+
s16 << r19
|
783
|
+
if r19
|
784
|
+
if has_terminal?('(', false, index)
|
785
|
+
r21 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
786
|
+
@index += 1
|
787
|
+
else
|
788
|
+
terminal_parse_failure('(')
|
789
|
+
r21 = nil
|
790
|
+
end
|
791
|
+
s16 << r21
|
792
|
+
if r21
|
793
|
+
s22, i22 = [], index
|
794
|
+
loop do
|
795
|
+
r23 = _nt_ws
|
796
|
+
if r23
|
797
|
+
s22 << r23
|
798
|
+
else
|
799
|
+
break
|
800
|
+
end
|
801
|
+
end
|
802
|
+
r22 = instantiate_node(SyntaxNode,input, i22...index, s22)
|
803
|
+
s16 << r22
|
804
|
+
if r22
|
805
|
+
r24 = _nt_selectors_group
|
806
|
+
s16 << r24
|
807
|
+
if r24
|
808
|
+
s25, i25 = [], index
|
809
|
+
loop do
|
810
|
+
r26 = _nt_ws
|
811
|
+
if r26
|
812
|
+
s25 << r26
|
813
|
+
else
|
814
|
+
break
|
815
|
+
end
|
816
|
+
end
|
817
|
+
r25 = instantiate_node(SyntaxNode,input, i25...index, s25)
|
818
|
+
s16 << r25
|
819
|
+
if r25
|
820
|
+
if has_terminal?(')', false, index)
|
821
|
+
r27 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
822
|
+
@index += 1
|
823
|
+
else
|
824
|
+
terminal_parse_failure(')')
|
825
|
+
r27 = nil
|
826
|
+
end
|
827
|
+
s16 << r27
|
828
|
+
end
|
829
|
+
end
|
830
|
+
end
|
831
|
+
end
|
832
|
+
end
|
833
|
+
end
|
834
|
+
end
|
835
|
+
if s16.last
|
836
|
+
r16 = instantiate_node(JSONSelect::Ast::PseudoSelector,input, i16...index, s16)
|
837
|
+
r16.extend(Pseudo2)
|
838
|
+
else
|
839
|
+
@index = i16
|
840
|
+
r16 = nil
|
841
|
+
end
|
842
|
+
if r16
|
843
|
+
r0 = r16
|
844
|
+
else
|
845
|
+
@index = i0
|
846
|
+
r0 = nil
|
847
|
+
end
|
737
848
|
end
|
738
849
|
end
|
739
850
|
|
@@ -817,10 +928,10 @@ module JSONSelect::Selector
|
|
817
928
|
r0
|
818
929
|
end
|
819
930
|
|
820
|
-
def
|
931
|
+
def _nt_positional_pseudo_function_name
|
821
932
|
start_index = index
|
822
|
-
if node_cache[:
|
823
|
-
cached = node_cache[:
|
933
|
+
if node_cache[:positional_pseudo_function_name].has_key?(index)
|
934
|
+
cached = node_cache[:positional_pseudo_function_name][index]
|
824
935
|
if cached
|
825
936
|
cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
|
826
937
|
@index = cached.interval.end
|
@@ -854,7 +965,31 @@ module JSONSelect::Selector
|
|
854
965
|
end
|
855
966
|
end
|
856
967
|
|
857
|
-
node_cache[:
|
968
|
+
node_cache[:positional_pseudo_function_name][start_index] = r0
|
969
|
+
|
970
|
+
r0
|
971
|
+
end
|
972
|
+
|
973
|
+
def _nt_subselector_pseudo_function_name
|
974
|
+
start_index = index
|
975
|
+
if node_cache[:subselector_pseudo_function_name].has_key?(index)
|
976
|
+
cached = node_cache[:subselector_pseudo_function_name][index]
|
977
|
+
if cached
|
978
|
+
cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
|
979
|
+
@index = cached.interval.end
|
980
|
+
end
|
981
|
+
return cached
|
982
|
+
end
|
983
|
+
|
984
|
+
if has_terminal?('has', false, index)
|
985
|
+
r0 = instantiate_node(SyntaxNode,input, index...(index + 3))
|
986
|
+
@index += 3
|
987
|
+
else
|
988
|
+
terminal_parse_failure('has')
|
989
|
+
r0 = nil
|
990
|
+
end
|
991
|
+
|
992
|
+
node_cache[:subselector_pseudo_function_name][start_index] = r0
|
858
993
|
|
859
994
|
r0
|
860
995
|
end
|