synvert-core 1.1.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -7,6 +7,8 @@ macros
7
7
  CLOSE_ARRAY /\)/
8
8
  OPEN_SELECTOR /\(/
9
9
  CLOSE_SELECTOR /\)/
10
+ OPEN_GOTO_SCOPE /</
11
+ CLOSE_GOTO_SCOPE />/
10
12
  OPEN_DYNAMIC_ATTRIBUTE /{{/
11
13
  CLOSE_DYNAMIC_ATTRIBUTE /}}/
12
14
  NODE_TYPE /\.[a-z]+/
@@ -20,8 +22,8 @@ macros
20
22
  REGEXP /\/(#{REGEXP_BODY})(?<!\\)\/([imxo]*)/
21
23
  SYMBOL /:[\w!\?<>=]+/
22
24
  TRUE /true/
23
- SINGLE_QUOTE_STRING /'(.*?)'/
24
- DOUBLE_QUOTE_STRING /"(.*?)"/
25
+ SINGLE_QUOTE_STRING /'.*?'/
26
+ DOUBLE_QUOTE_STRING /".*?"/
25
27
 
26
28
  rules
27
29
 
@@ -34,24 +36,31 @@ rules
34
36
  /:has/ { [:tPSEUDO_CLASS, text[1..-1]] }
35
37
  /:not_has/ { [:tPSEUDO_CLASS, text[1..-1]] }
36
38
  /#{NODE_TYPE}/ { [:tNODE_TYPE, text[1..]] }
37
- />/ { [:tCHILD, text] }
38
- /~/ { [:tSUBSEQUENT_SIBLING, text] }
39
- /\+/ { [:tNEXT_SIBLING, text] }
39
+ />/ { [:tRELATIONSHIP, text] }
40
+ /~/ { [:tRELATIONSHIP, text] }
41
+ /\+/ { [:tRELATIONSHIP, text] }
40
42
  /#{OPEN_SELECTOR}/ { [:tOPEN_SELECTOR, text] }
41
43
  /#{CLOSE_SELECTOR}/ { [:tCLOSE_SELECTOR, text] }
44
+ /#{OPEN_GOTO_SCOPE}/ { @state = :GOTO_SCOPE; [:tOPEN_GOTO_SCOPE, text] }
42
45
  /#{OPEN_ATTRIBUTE}/ { @nested_count += 1; @state = :KEY; [:tOPEN_ATTRIBUTE, text] }
46
+ :GOTO_SCOPE /\s+/
47
+ :GOTO_SCOPE /#{IDENTIFIER}/ { [:tIDENTIFIER, text] }
48
+ :GOTO_SCOPE /#{CLOSE_GOTO_SCOPE}/ { @state = nil; [:tCLOSE_GOTO_SCOPE, text] }
43
49
  :KEY /\s+/
44
- :KEY /!=/ { @state = :VALUE; [:tNOT_EQUAL, text] }
45
- :KEY /=~/ { @state = :VALUE; [:tMATCH, text] }
46
- :KEY /!~/ { @state = :VALUE; [:tNOT_MATCH, text] }
47
- :KEY />=/ { @state = :VALUE; [:tGREATER_THAN_OR_EQUAL, text] }
48
- :KEY /<=/ { @state = :VALUE; [:tLESS_THAN_OR_EQUAL, text] }
49
- :KEY />/ { @state = :VALUE; [:tGREATER_THAN, text] }
50
- :KEY /</ { @state = :VALUE; [:tLESS_THAN, text] }
51
- :KEY /=/ { @state = :VALUE; [:tEQUAL, text] }
52
- :KEY /includes/i { @state = :VALUE; [:tINCLUDES, text] }
53
- :KEY /not in/i { @state = :VALUE; [:tNOT_IN, text] }
54
- :KEY /in/i { @state = :VALUE; [:tIN, text] }
50
+ :KEY /\^=/ { @state = :VALUE; [:tOPERATOR, '^='] }
51
+ :KEY /\$=/ { @state = :VALUE; [:tOPERATOR, '$='] }
52
+ :KEY /\*=/ { @state = :VALUE; [:tOPERATOR, '*='] }
53
+ :KEY /!=/ { @state = :VALUE; [:tOPERATOR, '!='] }
54
+ :KEY /=~/ { @state = :VALUE; [:tOPERATOR, '=~'] }
55
+ :KEY /!~/ { @state = :VALUE; [:tOPERATOR, '!~'] }
56
+ :KEY />=/ { @state = :VALUE; [:tOPERATOR, '>='] }
57
+ :KEY /<=/ { @state = :VALUE; [:tOPERATOR, '<='] }
58
+ :KEY />/ { @state = :VALUE; [:tOPERATOR, '>'] }
59
+ :KEY /</ { @state = :VALUE; [:tOPERATOR, '<'] }
60
+ :KEY /=/ { @state = :VALUE; [:tOPERATOR, '=='] }
61
+ :KEY /includes/i { @state = :VALUE; [:tOPERATOR, 'includes'] }
62
+ :KEY /not in/i { @state = :VALUE; [:tOPERATOR, 'not_in'] }
63
+ :KEY /in/i { @state = :VALUE; [:tOPERATOR, 'in'] }
55
64
  :KEY /#{IDENTIFIER}/ { [:tKEY, text] }
56
65
  :VALUE /\s+/
57
66
  :VALUE /\[\]=/ { [:tIDENTIFIER_VALUE, text] }
@@ -61,6 +70,7 @@ rules
61
70
  :VALUE /#{OPEN_DYNAMIC_ATTRIBUTE}/ { @state = :DYNAMIC_ATTRIBUTE; [:tOPEN_DYNAMIC_ATTRIBUTE, text] }
62
71
  :VALUE /#{OPEN_ARRAY}/ { @state = :ARRAY_VALUE; [:tOPEN_ARRAY, text] }
63
72
  :VALUE /#{CLOSE_ATTRIBUTE}/ { @nested_count -= 1; @state = @nested_count == 0 ? nil : :VALUE; [:tCLOSE_ATTRIBUTE, text] }
73
+ :VALUE /#{NIL}\?/ { [:tIDENTIFIER_VALUE, text] }
64
74
  :VALUE /#{NIL}/ { [:tNIL, nil] }
65
75
  :VALUE /#{TRUE}/ { [:tBOOLEAN, true] }
66
76
  :VALUE /#{FALSE}/ { [:tBOOLEAN, false] }
@@ -76,8 +86,8 @@ rules
76
86
  :DYNAMIC_ATTRIBUTE /#{CLOSE_DYNAMIC_ATTRIBUTE}/ { @state = :VALUE; [:tCLOSE_DYNAMIC_ATTRIBUTE, text] }
77
87
  :DYNAMIC_ATTRIBUTE /#{IDENTIFIER}/ { [:tDYNAMIC_ATTRIBUTE, text] }
78
88
  :ARRAY_VALUE /\s+/
79
- :ARRAY_VALUE /,/ { [:tCOMMA, text] }
80
89
  :ARRAY_VALUE /#{CLOSE_ARRAY}/ { @state = :VALUE; [:tCLOSE_ARRAY, text] }
90
+ :ARRAY_VALUE /#{NIL}\?/ { [:tIDENTIFIER_VALUE, text] }
81
91
  :ARRAY_VALUE /#{NIL}/ { [:tNIL, nil] }
82
92
  :ARRAY_VALUE /#{TRUE}/ { [:tBOOLEAN, true] }
83
93
  :ARRAY_VALUE /#{FALSE}/ { [:tBOOLEAN, false] }
@@ -20,6 +20,8 @@ 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 = />/
23
25
  OPEN_DYNAMIC_ATTRIBUTE = /{{/
24
26
  CLOSE_DYNAMIC_ATTRIBUTE = /}}/
25
27
  NODE_TYPE = /\.[a-z]+/
@@ -33,8 +35,8 @@ class Synvert::Core::NodeQuery::Lexer
33
35
  REGEXP = /\/(#{REGEXP_BODY})(?<!\\)\/([imxo]*)/
34
36
  SYMBOL = /:[\w!\?<>=]+/
35
37
  TRUE = /true/
36
- SINGLE_QUOTE_STRING = /'(.*?)'/
37
- DOUBLE_QUOTE_STRING = /"(.*?)"/
38
+ SINGLE_QUOTE_STRING = /'.*?'/
39
+ DOUBLE_QUOTE_STRING = /".*?"/
38
40
  # :startdoc:
39
41
  # :stopdoc:
40
42
  class LexerError < StandardError ; end
@@ -140,47 +142,67 @@ class Synvert::Core::NodeQuery::Lexer
140
142
  when text = ss.scan(/#{NODE_TYPE}/) then
141
143
  action { [:tNODE_TYPE, text[1..]] }
142
144
  when text = ss.scan(/>/) then
143
- action { [:tCHILD, text] }
145
+ action { [:tRELATIONSHIP, text] }
144
146
  when text = ss.scan(/~/) then
145
- action { [:tSUBSEQUENT_SIBLING, text] }
147
+ action { [:tRELATIONSHIP, text] }
146
148
  when text = ss.scan(/\+/) then
147
- action { [:tNEXT_SIBLING, text] }
149
+ action { [:tRELATIONSHIP, text] }
148
150
  when text = ss.scan(/#{OPEN_SELECTOR}/) then
149
151
  action { [:tOPEN_SELECTOR, text] }
150
152
  when text = ss.scan(/#{CLOSE_SELECTOR}/) then
151
153
  action { [:tCLOSE_SELECTOR, text] }
154
+ when text = ss.scan(/#{OPEN_GOTO_SCOPE}/) then
155
+ action { @state = :GOTO_SCOPE; [:tOPEN_GOTO_SCOPE, text] }
152
156
  when text = ss.scan(/#{OPEN_ATTRIBUTE}/) then
153
157
  action { @nested_count += 1; @state = :KEY; [:tOPEN_ATTRIBUTE, text] }
154
158
  else
155
159
  text = ss.string[ss.pos .. -1]
156
160
  raise ScanError, "can not match (#{state.inspect}) at #{location}: '#{text}'"
157
161
  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
158
174
  when :KEY then
159
175
  case
160
176
  when ss.skip(/\s+/) then
161
177
  # do nothing
162
- when text = ss.scan(/!=/) then
163
- action { @state = :VALUE; [:tNOT_EQUAL, text] }
164
- when text = ss.scan(/=~/) then
165
- action { @state = :VALUE; [:tMATCH, text] }
166
- when text = ss.scan(/!~/) then
167
- action { @state = :VALUE; [:tNOT_MATCH, text] }
168
- when text = ss.scan(/>=/) then
169
- action { @state = :VALUE; [:tGREATER_THAN_OR_EQUAL, text] }
170
- when text = ss.scan(/<=/) then
171
- action { @state = :VALUE; [:tLESS_THAN_OR_EQUAL, text] }
172
- when text = ss.scan(/>/) then
173
- action { @state = :VALUE; [:tGREATER_THAN, text] }
174
- when text = ss.scan(/</) then
175
- action { @state = :VALUE; [:tLESS_THAN, text] }
176
- when text = ss.scan(/=/) then
177
- action { @state = :VALUE; [:tEQUAL, text] }
178
- when text = ss.scan(/includes/i) then
179
- action { @state = :VALUE; [:tINCLUDES, text] }
180
- when text = ss.scan(/not in/i) then
181
- action { @state = :VALUE; [:tNOT_IN, text] }
182
- when text = ss.scan(/in/i) then
183
- action { @state = :VALUE; [:tIN, text] }
178
+ when ss.skip(/\^=/) then
179
+ action { @state = :VALUE; [:tOPERATOR, '^='] }
180
+ when ss.skip(/\$=/) then
181
+ action { @state = :VALUE; [:tOPERATOR, '$='] }
182
+ when ss.skip(/\*=/) then
183
+ action { @state = :VALUE; [:tOPERATOR, '*='] }
184
+ when ss.skip(/!=/) then
185
+ action { @state = :VALUE; [:tOPERATOR, '!='] }
186
+ when ss.skip(/=~/) then
187
+ action { @state = :VALUE; [:tOPERATOR, '=~'] }
188
+ when ss.skip(/!~/) then
189
+ action { @state = :VALUE; [:tOPERATOR, '!~'] }
190
+ when ss.skip(/>=/) then
191
+ action { @state = :VALUE; [:tOPERATOR, '>='] }
192
+ when ss.skip(/<=/) then
193
+ action { @state = :VALUE; [:tOPERATOR, '<='] }
194
+ when ss.skip(/>/) then
195
+ action { @state = :VALUE; [:tOPERATOR, '>'] }
196
+ when ss.skip(/</) then
197
+ action { @state = :VALUE; [:tOPERATOR, '<'] }
198
+ when ss.skip(/=/) then
199
+ action { @state = :VALUE; [:tOPERATOR, '=='] }
200
+ when ss.skip(/includes/i) then
201
+ action { @state = :VALUE; [:tOPERATOR, 'includes'] }
202
+ when ss.skip(/not in/i) then
203
+ action { @state = :VALUE; [:tOPERATOR, 'not_in'] }
204
+ when ss.skip(/in/i) then
205
+ action { @state = :VALUE; [:tOPERATOR, 'in'] }
184
206
  when text = ss.scan(/#{IDENTIFIER}/) then
185
207
  action { [:tKEY, text] }
186
208
  else
@@ -205,6 +227,8 @@ class Synvert::Core::NodeQuery::Lexer
205
227
  action { @state = :ARRAY_VALUE; [:tOPEN_ARRAY, text] }
206
228
  when text = ss.scan(/#{CLOSE_ATTRIBUTE}/) then
207
229
  action { @nested_count -= 1; @state = @nested_count == 0 ? nil : :VALUE; [:tCLOSE_ATTRIBUTE, text] }
230
+ when text = ss.scan(/#{NIL}\?/) then
231
+ action { [:tIDENTIFIER_VALUE, text] }
208
232
  when ss.skip(/#{NIL}/) then
209
233
  action { [:tNIL, nil] }
210
234
  when ss.skip(/#{TRUE}/) then
@@ -247,10 +271,10 @@ class Synvert::Core::NodeQuery::Lexer
247
271
  case
248
272
  when ss.skip(/\s+/) then
249
273
  # do nothing
250
- when text = ss.scan(/,/) then
251
- action { [:tCOMMA, text] }
252
274
  when text = ss.scan(/#{CLOSE_ARRAY}/) then
253
275
  action { @state = :VALUE; [:tCLOSE_ARRAY, text] }
276
+ when text = ss.scan(/#{NIL}\?/) then
277
+ action { [:tIDENTIFIER_VALUE, text] }
254
278
  when ss.skip(/#{NIL}/) then
255
279
  action { [:tNIL, nil] }
256
280
  when ss.skip(/#{TRUE}/) then