json_p3 0.2.1 → 0.3.1

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.
data/lib/json_p3/lexer.rb CHANGED
@@ -15,7 +15,7 @@ module JSONP3 # rubocop:disable Style/Documentation
15
15
  lexer.run
16
16
  tokens = lexer.tokens
17
17
 
18
- if !tokens.empty? && tokens.last.type == Token::ERROR
18
+ if !tokens.empty? && tokens.last.type == :token_error
19
19
  raise JSONPathSyntaxError.new(tokens.last.message || raise,
20
20
  tokens.last)
21
21
  end
@@ -26,7 +26,7 @@ module JSONP3 # rubocop:disable Style/Documentation
26
26
  # JSONPath query expression lexical scanner.
27
27
  #
28
28
  # @see tokenize
29
- class Lexer # rubocop:disable Metrics/ClassLength
29
+ class Lexer
30
30
  RE_INT = /-?[0-9]+/
31
31
  RE_NAME = /[\u0080-\uFFFFa-zA-Z_][\u0080-\uFFFFa-zA-Z0-9_-]*/
32
32
  RE_WHITESPACE = /[ \n\r\t]+/
@@ -46,7 +46,7 @@ module JSONP3 # rubocop:disable Style/Documentation
46
46
 
47
47
  def run
48
48
  state = :lex_root
49
- state = method(state).call until state.nil?
49
+ state = send(state) until state.nil?
50
50
  end
51
51
 
52
52
  protected
@@ -56,12 +56,12 @@ module JSONP3 # rubocop:disable Style/Documentation
56
56
  # @param value [String | nil] a the token's value, if it is known, otherwise the
57
57
  # value will be sliced from @query. This is a performance optimization.
58
58
  def emit(token_type, value = nil)
59
- @tokens << Token.new(token_type, value || @query[@start...@scanner.charpos], @start, @query)
59
+ @tokens << Token.new(token_type, value || @query[@start, @scanner.charpos - @start], @start, @query)
60
60
  @start = @scanner.charpos
61
61
  end
62
62
 
63
63
  def next
64
- @scanner.getch || ""
64
+ @scanner.get_byte || ""
65
65
  end
66
66
 
67
67
  def ignore
@@ -69,7 +69,6 @@ module JSONP3 # rubocop:disable Style/Documentation
69
69
  end
70
70
 
71
71
  def backup
72
- # Assumes we're backing-up from a single byte character.
73
72
  @scanner.pos -= 1
74
73
  end
75
74
 
@@ -78,7 +77,7 @@ module JSONP3 # rubocop:disable Style/Documentation
78
77
  @scanner.peek(1)
79
78
  end
80
79
 
81
- # Advance the lexer if the next character is equal to _char_.
80
+ # Advance the lexer if _pattern_ matches from the current position.
82
81
  def accept?(pattern)
83
82
  !@scanner.scan(pattern).nil?
84
83
  end
@@ -100,7 +99,7 @@ module JSONP3 # rubocop:disable Style/Documentation
100
99
 
101
100
  def error(message)
102
101
  @tokens << Token.new(
103
- Token::ERROR, @query[@start...@scanner.charpos] || "", @start, @query, message: message
102
+ :token_error, @query[@start, @scanner.charpos - @start] || "", @start, @query, message: message
104
103
  )
105
104
  end
106
105
 
@@ -112,11 +111,11 @@ module JSONP3 # rubocop:disable Style/Documentation
112
111
  return nil
113
112
  end
114
113
 
115
- emit(Token::ROOT, "$")
114
+ emit(:token_root, "$")
116
115
  :lex_segment
117
116
  end
118
117
 
119
- def lex_segment # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
118
+ def lex_segment
120
119
  if accept?(RE_WHITESPACE) && peek.empty?
121
120
  error "unexpected trailing whitespace"
122
121
  return nil
@@ -127,16 +126,16 @@ module JSONP3 # rubocop:disable Style/Documentation
127
126
 
128
127
  case c
129
128
  when ""
130
- emit(Token::EOI, "")
129
+ emit(:token_eoi, "")
131
130
  nil
132
131
  when "."
133
132
  return :lex_shorthand_selector unless peek == "."
134
133
 
135
134
  self.next
136
- emit(Token::DOUBLE_DOT, "..")
135
+ emit(:token_double_dot, "..")
137
136
  :lex_descendant_segment
138
137
  when "["
139
- emit(Token::LBRACKET, "[")
138
+ emit(:token_lbracket, "[")
140
139
  :lex_inside_bracketed_segment
141
140
  else
142
141
  if @filter_depth.positive?
@@ -149,21 +148,21 @@ module JSONP3 # rubocop:disable Style/Documentation
149
148
  end
150
149
  end
151
150
 
152
- def lex_descendant_segment # rubocop:disable Metrics/MethodLength
151
+ def lex_descendant_segment
153
152
  case self.next
154
153
  when ""
155
154
  error "bald descendant segment"
156
155
  nil
157
156
  when "*"
158
- emit(Token::WILD, "*")
157
+ emit(:token_wild, "*")
159
158
  :lex_segment
160
159
  when "["
161
- emit(Token::LBRACKET, "[")
160
+ emit(:token_lbracket, "[")
162
161
  :lex_inside_bracketed_segment
163
162
  else
164
163
  backup
165
164
  if accept?(RE_NAME)
166
- emit(Token::NAME)
165
+ emit(:token_name)
167
166
  :lex_segment
168
167
  else
169
168
  c = self.next
@@ -173,7 +172,7 @@ module JSONP3 # rubocop:disable Style/Documentation
173
172
  end
174
173
  end
175
174
 
176
- def lex_shorthand_selector # rubocop:disable Metrics/MethodLength
175
+ def lex_shorthand_selector
177
176
  if peek == ""
178
177
  error "unexpected trailing dot"
179
178
  return nil
@@ -188,12 +187,12 @@ module JSONP3 # rubocop:disable Style/Documentation
188
187
 
189
188
  if peek == "*"
190
189
  self.next
191
- emit(Token::WILD, "*")
190
+ emit(:token_wild, "*")
192
191
  return :lex_segment
193
192
  end
194
193
 
195
194
  if accept?(RE_NAME)
196
- emit(Token::NAME)
195
+ emit(:token_name)
197
196
  return :lex_segment
198
197
  end
199
198
 
@@ -202,28 +201,28 @@ module JSONP3 # rubocop:disable Style/Documentation
202
201
  nil
203
202
  end
204
203
 
205
- def lex_inside_bracketed_segment # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity
204
+ def lex_inside_bracketed_segment
206
205
  loop do # rubocop:disable Metrics/BlockLength
207
206
  ignore_whitespace?
208
207
  c = self.next
209
208
 
210
209
  case c
211
210
  when "]"
212
- emit(Token::RBRACKET, "]")
211
+ emit(:token_rbracket, "]")
213
212
  return @filter_depth.positive? ? :lex_inside_filter : :lex_segment
214
213
  when ""
215
214
  error "unclosed bracketed selection"
216
215
  return nil
217
216
  when "*"
218
- emit(Token::WILD, "*")
217
+ emit(:token_wild, "*")
219
218
  when "?"
220
- emit(Token::FILTER, "?")
219
+ emit(:token_filter, "?")
221
220
  @filter_depth += 1
222
221
  return :lex_inside_filter
223
222
  when ","
224
- emit(Token::COMMA, ",")
223
+ emit(:token_comma, ",")
225
224
  when ":"
226
- emit(Token::COLON, ":")
225
+ emit(:token_colon, ":")
227
226
  when "'"
228
227
  return :lex_single_quoted_string_inside_bracketed_segment
229
228
  when '"'
@@ -232,7 +231,7 @@ module JSONP3 # rubocop:disable Style/Documentation
232
231
  backup
233
232
  if accept_int?
234
233
  # Index selector or part of a slice selector.
235
- emit Token::INDEX
234
+ emit(:token_index)
236
235
  else
237
236
  error "unexpected token '#{c}' in bracketed selection"
238
237
  return nil
@@ -259,7 +258,7 @@ module JSONP3 # rubocop:disable Style/Documentation
259
258
  backup
260
259
  return :lex_inside_bracketed_segment
261
260
  when ","
262
- emit(Token::COMMA, ",")
261
+ emit(:token_comma, ",")
263
262
  # If we have unbalanced parens, we are inside a function call and a
264
263
  # comma separates arguments. Otherwise a comma separates selectors.
265
264
  next if @paren_stack.length.positive?
@@ -271,11 +270,11 @@ module JSONP3 # rubocop:disable Style/Documentation
271
270
  when '"'
272
271
  return :lex_double_quoted_string_inside_filter_expression
273
272
  when "("
274
- emit(Token::LPAREN, "(")
273
+ emit(:token_lparen, "(")
275
274
  # Are we in a function call? If so, a function argument contains parens.
276
275
  @paren_stack[-1] += 1 if @paren_stack.length.positive?
277
276
  when ")"
278
- emit(Token::RPAREN, ")")
277
+ emit(:token_rparen, ")")
279
278
  # Are we closing a function call or a parenthesized expression?
280
279
  if @paren_stack.length.positive?
281
280
  if @paren_stack[-1] == 1
@@ -285,10 +284,10 @@ module JSONP3 # rubocop:disable Style/Documentation
285
284
  end
286
285
  end
287
286
  when "$"
288
- emit(Token::ROOT, "$")
287
+ emit(:token_root, "$")
289
288
  return :lex_segment
290
289
  when "@"
291
- emit(Token::CURRENT, "@")
290
+ emit(:token_current, "@")
292
291
  return :lex_segment
293
292
  when "."
294
293
  backup
@@ -296,32 +295,32 @@ module JSONP3 # rubocop:disable Style/Documentation
296
295
  when "!"
297
296
  if peek == "="
298
297
  self.next
299
- emit(Token::NE, "!=")
298
+ emit(:token_ne, "!=")
300
299
  else
301
- emit(Token::NOT, "!")
300
+ emit(:token_not, "!")
302
301
  end
303
302
  when "="
304
303
  if peek == "="
305
304
  self.next
306
- emit(Token::EQ, "==")
305
+ emit(:token_eq, "==")
307
306
  else
308
307
  backup
309
- error "unexpected filter selector token '#{c}'"
308
+ error "found '=', did you mean '==', '!=', '<=' or '>='?"
310
309
  return nil
311
310
  end
312
311
  when "<"
313
312
  if peek == "="
314
313
  self.next
315
- emit(Token::LE, "<=")
314
+ emit(:token_le, "<=")
316
315
  else
317
- emit(Token::LT, "<")
316
+ emit(:token_lt, "<")
318
317
  end
319
318
  when ">"
320
319
  if peek == "="
321
320
  self.next
322
- emit(Token::GE, ">=")
321
+ emit(:token_ge, ">=")
323
322
  else
324
- emit(Token::GT, ">")
323
+ emit(:token_gt, ">")
325
324
  end
326
325
  else
327
326
  backup
@@ -335,24 +334,24 @@ module JSONP3 # rubocop:disable Style/Documentation
335
334
  end
336
335
 
337
336
  accept?(/[eE][+-]?[0-9]+/)
338
- emit Token::FLOAT
337
+ emit :token_float
339
338
  # An int, or float if exponent is negative
340
339
  elsif accept?(/[eE]-[0-9]+/)
341
- emit Token::FLOAT
340
+ emit :token_float
342
341
  else
343
342
  accept?(/[eE][+-]?[0-9]+/)
344
- emit Token::INT
343
+ emit :token_int
345
344
  end
346
345
  elsif accept?("&&")
347
- emit(Token::AND, "&&")
346
+ emit(:token_and, "&&")
348
347
  elsif accept?("||")
349
- emit(Token::OR, "||")
348
+ emit(:token_or, "||")
350
349
  elsif accept?("true")
351
- emit(Token::TRUE, "true")
350
+ emit(:token_true, "true")
352
351
  elsif accept?("false")
353
- emit(Token::FALSE, "false")
352
+ emit(:token_false, "false")
354
353
  elsif accept?("null")
355
- emit(Token::NULL, "null")
354
+ emit(:token_null, "null")
356
355
  elsif accept?(/[a-z][a-z_0-9]*/)
357
356
  unless peek == "("
358
357
  error "unexpected filter selector token"
@@ -361,7 +360,7 @@ module JSONP3 # rubocop:disable Style/Documentation
361
360
  # Function name
362
361
  # Keep track of parentheses for this function call.
363
362
  @paren_stack << 1
364
- emit Token::FUNCTION
363
+ emit :token_function
365
364
  self.next
366
365
  ignore # move past LPAREN
367
366
  else
@@ -373,20 +372,20 @@ module JSONP3 # rubocop:disable Style/Documentation
373
372
  end
374
373
 
375
374
  class << self
376
- def lex_string_factory(quote, state, token) # rubocop:disable Metrics/MethodLength
375
+ def lex_string_factory(quote, state, token)
377
376
  proc {
378
377
  # @type self: Lexer
379
378
  ignore # move past opening quote
380
379
 
381
380
  loop do
382
381
  c = self.next
383
- peeked = peek
384
382
 
385
383
  case c
386
384
  when ""
387
385
  error "unclosed string starting at index #{@start}"
388
386
  return nil
389
387
  when "\\"
388
+ peeked = peek
390
389
  if S_ESCAPES.member?(peeked) || peeked == quote
391
390
  self.next
392
391
  else
@@ -406,15 +405,15 @@ module JSONP3 # rubocop:disable Style/Documentation
406
405
  end
407
406
 
408
407
  define_method(:lex_double_quoted_string_inside_bracketed_segment,
409
- lex_string_factory('"', :lex_inside_bracketed_segment, Token::DOUBLE_QUOTE_STRING))
408
+ lex_string_factory('"', :lex_inside_bracketed_segment, :token_double_quote_string))
410
409
 
411
410
  define_method(:lex_single_quoted_string_inside_bracketed_segment,
412
- lex_string_factory("'", :lex_inside_bracketed_segment, Token::SINGLE_QUOTE_STRING))
411
+ lex_string_factory("'", :lex_inside_bracketed_segment, :token_single_quote_string))
413
412
 
414
413
  define_method(:lex_double_quoted_string_inside_filter_expression,
415
- lex_string_factory('"', :lex_inside_filter, Token::DOUBLE_QUOTE_STRING))
414
+ lex_string_factory('"', :lex_inside_filter, :token_double_quote_string))
416
415
 
417
416
  define_method(:lex_single_quoted_string_inside_filter_expression,
418
- lex_string_factory("'", :lex_inside_filter, Token::SINGLE_QUOTE_STRING))
417
+ lex_string_factory("'", :lex_inside_filter, :token_single_quote_string))
419
418
  end
420
419
  end