synvert-core 1.2.1 → 1.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 +4 -4
- data/CHANGELOG.md +16 -0
- data/Gemfile +9 -0
- data/lib/synvert/core/node_query/compiler/attribute.rb +6 -18
- data/lib/synvert/core/node_query/compiler/basic_selector.rb +28 -0
- data/lib/synvert/core/node_query/compiler/comparable.rb +26 -19
- data/lib/synvert/core/node_query/compiler/expression.rb +8 -93
- data/lib/synvert/core/node_query/compiler/identifier.rb +1 -1
- data/lib/synvert/core/node_query/compiler/regexp.rb +2 -2
- data/lib/synvert/core/node_query/compiler/selector.rb +91 -34
- data/lib/synvert/core/node_query/compiler/string.rb +1 -1
- data/lib/synvert/core/node_query/compiler.rb +1 -0
- data/lib/synvert/core/node_query/lexer.rex +20 -26
- data/lib/synvert/core/node_query/lexer.rex.rb +35 -51
- data/lib/synvert/core/node_query/parser.racc.rb +115 -293
- data/lib/synvert/core/node_query/parser.y +16 -35
- data/lib/synvert/core/node_query.rb +3 -4
- data/lib/synvert/core/rewriter/action/delete_action.rb +4 -2
- data/lib/synvert/core/rewriter/action/remove_action.rb +5 -2
- data/lib/synvert/core/rewriter/instance.rb +8 -4
- data/lib/synvert/core/version.rb +1 -1
- data/spec/synvert/core/node_query/lexer_spec.rb +46 -106
- data/spec/synvert/core/node_query/parser_spec.rb +116 -129
- data/spec/synvert/core/rewriter/instance_spec.rb +12 -7
- data/spec/synvert/core/rewriter/scope/query_scope_spec.rb +9 -2
- data/synvert-core-ruby.gemspec +0 -10
- metadata +3 -128
@@ -20,8 +20,6 @@ class Synvert::Core::NodeQuery::Lexer
|
|
20
20
|
CLOSE_ARRAY = /\)/
|
21
21
|
OPEN_SELECTOR = /\(/
|
22
22
|
CLOSE_SELECTOR = /\)/
|
23
|
-
OPEN_GOTO_SCOPE = /</
|
24
|
-
CLOSE_GOTO_SCOPE = />/
|
25
23
|
OPEN_DYNAMIC_ATTRIBUTE = /{{/
|
26
24
|
CLOSE_DYNAMIC_ATTRIBUTE = /}}/
|
27
25
|
NODE_TYPE = /\.[a-z]+/
|
@@ -35,8 +33,8 @@ class Synvert::Core::NodeQuery::Lexer
|
|
35
33
|
REGEXP = /\/(#{REGEXP_BODY})(?<!\\)\/([imxo]*)/
|
36
34
|
SYMBOL = /:[\w!\?<>=]+/
|
37
35
|
TRUE = /true/
|
38
|
-
SINGLE_QUOTE_STRING = /'
|
39
|
-
DOUBLE_QUOTE_STRING = /"
|
36
|
+
SINGLE_QUOTE_STRING = /'.*?'/
|
37
|
+
DOUBLE_QUOTE_STRING = /".*?"/
|
40
38
|
# :startdoc:
|
41
39
|
# :stopdoc:
|
42
40
|
class LexerError < StandardError ; end
|
@@ -127,76 +125,62 @@ class Synvert::Core::NodeQuery::Lexer
|
|
127
125
|
case
|
128
126
|
when ss.skip(/\s+/) then
|
129
127
|
# do nothing
|
130
|
-
when ss.skip(/:first-child/) then
|
131
|
-
action { [:tINDEX, 0] }
|
132
|
-
when ss.skip(/:last-child/) then
|
133
|
-
action { [:tINDEX, -1] }
|
134
|
-
when text = ss.scan(/:nth-child\(\d+\)/) then
|
135
|
-
action { [:tINDEX, text.sub(':nth-child(', '').to_i - 1] }
|
136
|
-
when text = ss.scan(/:nth-last-child\(\d+\)/) then
|
137
|
-
action { [:tINDEX, -text.sub(':nth-last-child(', '').to_i] }
|
138
128
|
when text = ss.scan(/:has/) then
|
139
129
|
action { [:tPSEUDO_CLASS, text[1..-1]] }
|
140
130
|
when text = ss.scan(/:not_has/) then
|
141
131
|
action { [:tPSEUDO_CLASS, text[1..-1]] }
|
142
132
|
when text = ss.scan(/#{NODE_TYPE}/) then
|
143
133
|
action { [:tNODE_TYPE, text[1..]] }
|
134
|
+
when text = ss.scan(/#{IDENTIFIER}/) then
|
135
|
+
action { [:tGOTO_SCOPE, text] }
|
144
136
|
when text = ss.scan(/>/) then
|
145
|
-
action { [:
|
137
|
+
action { [:tRELATIONSHIP, text] }
|
146
138
|
when text = ss.scan(/~/) then
|
147
|
-
action { [:
|
139
|
+
action { [:tRELATIONSHIP, text] }
|
148
140
|
when text = ss.scan(/\+/) then
|
149
|
-
action { [:
|
141
|
+
action { [:tRELATIONSHIP, text] }
|
150
142
|
when text = ss.scan(/#{OPEN_SELECTOR}/) then
|
151
143
|
action { [:tOPEN_SELECTOR, text] }
|
152
144
|
when text = ss.scan(/#{CLOSE_SELECTOR}/) then
|
153
145
|
action { [:tCLOSE_SELECTOR, text] }
|
154
|
-
when text = ss.scan(/#{OPEN_GOTO_SCOPE}/) then
|
155
|
-
action { @state = :GOTO_SCOPE; [:tOPEN_GOTO_SCOPE, text] }
|
156
146
|
when text = ss.scan(/#{OPEN_ATTRIBUTE}/) then
|
157
147
|
action { @nested_count += 1; @state = :KEY; [:tOPEN_ATTRIBUTE, text] }
|
158
148
|
else
|
159
149
|
text = ss.string[ss.pos .. -1]
|
160
150
|
raise ScanError, "can not match (#{state.inspect}) at #{location}: '#{text}'"
|
161
151
|
end
|
162
|
-
when :GOTO_SCOPE then
|
163
|
-
case
|
164
|
-
when ss.skip(/\s+/) then
|
165
|
-
# do nothing
|
166
|
-
when text = ss.scan(/#{IDENTIFIER}/) then
|
167
|
-
action { [:tIDENTIFIER, text] }
|
168
|
-
when text = ss.scan(/#{CLOSE_GOTO_SCOPE}/) then
|
169
|
-
action { @state = nil; [:tCLOSE_GOTO_SCOPE, text] }
|
170
|
-
else
|
171
|
-
text = ss.string[ss.pos .. -1]
|
172
|
-
raise ScanError, "can not match (#{state.inspect}) at #{location}: '#{text}'"
|
173
|
-
end
|
174
152
|
when :KEY then
|
175
153
|
case
|
176
154
|
when ss.skip(/\s+/) then
|
177
155
|
# do nothing
|
178
|
-
when
|
179
|
-
action { @state = :VALUE; [:
|
180
|
-
when
|
181
|
-
action { @state = :VALUE; [:
|
182
|
-
when
|
183
|
-
action { @state = :VALUE; [:
|
184
|
-
when
|
185
|
-
action { @state = :VALUE; [:
|
186
|
-
when
|
187
|
-
action { @state = :VALUE; [:
|
188
|
-
when
|
189
|
-
action { @state = :VALUE; [:
|
190
|
-
when
|
191
|
-
action { @state = :VALUE; [:
|
192
|
-
when
|
193
|
-
action { @state = :VALUE; [:
|
194
|
-
when
|
195
|
-
action { @state = :VALUE; [:
|
196
|
-
when
|
197
|
-
action { @state = :VALUE; [:
|
198
|
-
when
|
199
|
-
action { @state = :VALUE; [:
|
156
|
+
when ss.skip(/\^=/) then
|
157
|
+
action { @state = :VALUE; [:tOPERATOR, '^='] }
|
158
|
+
when ss.skip(/\$=/) then
|
159
|
+
action { @state = :VALUE; [:tOPERATOR, '$='] }
|
160
|
+
when ss.skip(/\*=/) then
|
161
|
+
action { @state = :VALUE; [:tOPERATOR, '*='] }
|
162
|
+
when ss.skip(/!=/) then
|
163
|
+
action { @state = :VALUE; [:tOPERATOR, '!='] }
|
164
|
+
when ss.skip(/=~/) then
|
165
|
+
action { @state = :VALUE; [:tOPERATOR, '=~'] }
|
166
|
+
when ss.skip(/!~/) then
|
167
|
+
action { @state = :VALUE; [:tOPERATOR, '!~'] }
|
168
|
+
when ss.skip(/>=/) then
|
169
|
+
action { @state = :VALUE; [:tOPERATOR, '>='] }
|
170
|
+
when ss.skip(/<=/) then
|
171
|
+
action { @state = :VALUE; [:tOPERATOR, '<='] }
|
172
|
+
when ss.skip(/>/) then
|
173
|
+
action { @state = :VALUE; [:tOPERATOR, '>'] }
|
174
|
+
when ss.skip(/</) then
|
175
|
+
action { @state = :VALUE; [:tOPERATOR, '<'] }
|
176
|
+
when ss.skip(/=/) then
|
177
|
+
action { @state = :VALUE; [:tOPERATOR, '=='] }
|
178
|
+
when ss.skip(/includes/i) then
|
179
|
+
action { @state = :VALUE; [:tOPERATOR, 'includes'] }
|
180
|
+
when ss.skip(/not in/i) then
|
181
|
+
action { @state = :VALUE; [:tOPERATOR, 'not_in'] }
|
182
|
+
when ss.skip(/in/i) then
|
183
|
+
action { @state = :VALUE; [:tOPERATOR, 'in'] }
|
200
184
|
when text = ss.scan(/#{IDENTIFIER}/) then
|
201
185
|
action { [:tKEY, text] }
|
202
186
|
else
|