json_p3 0.2.1 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -62,7 +62,7 @@ module JSONP3
62
62
  end
63
63
 
64
64
  # A JSONPath expression parser.
65
- class Parser # rubocop:disable Metrics/ClassLength
65
+ class Parser
66
66
  def initialize(env)
67
67
  @env = env
68
68
  @name_selector = env.class::NAME_SELECTOR
@@ -74,23 +74,23 @@ module JSONP3
74
74
  # @return [Array<Segment>]
75
75
  def parse(tokens)
76
76
  stream = Stream.new(tokens)
77
- stream.expect(Token::ROOT)
77
+ stream.expect(:token_root)
78
78
  stream.next
79
79
  parse_query(stream)
80
80
  end
81
81
 
82
82
  protected
83
83
 
84
- def parse_query(stream) # rubocop:disable Metrics/MethodLength
85
- segments = []
84
+ def parse_query(stream)
85
+ segments = [] # : Array[Segment]
86
86
 
87
87
  loop do
88
88
  case stream.peek.type
89
- when Token::DOUBLE_DOT
89
+ when :token_double_dot
90
90
  token = stream.next
91
91
  selectors = parse_selectors(stream)
92
92
  segments << RecursiveDescentSegment.new(@env, token, selectors)
93
- when Token::LBRACKET, Token::NAME, Token::WILD
93
+ when :token_lbracket, :token_name, :token_wild
94
94
  token = stream.peek
95
95
  selectors = parse_selectors(stream)
96
96
  segments << ChildSegment.new(@env, token, selectors)
@@ -102,60 +102,60 @@ module JSONP3
102
102
  segments
103
103
  end
104
104
 
105
- def parse_selectors(stream) # rubocop:disable Metrics/MethodLength
105
+ def parse_selectors(stream)
106
106
  case stream.peek.type
107
- when Token::NAME
107
+ when :token_name
108
108
  token = stream.next
109
109
  [@name_selector.new(@env, token, token.value)]
110
- when Token::WILD
110
+ when :token_wild
111
111
  [WildcardSelector.new(@env, stream.next)]
112
- when Token::LBRACKET
112
+ when :token_lbracket
113
113
  parse_bracketed_selection(stream)
114
114
  else
115
115
  []
116
116
  end
117
117
  end
118
118
 
119
- def parse_bracketed_selection(stream) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity
120
- stream.expect Token::LBRACKET
119
+ def parse_bracketed_selection(stream)
120
+ stream.expect(:token_lbracket)
121
121
  segment_token = stream.next
122
122
 
123
- selectors = []
123
+ selectors = [] # : Array[Selector]
124
124
 
125
125
  loop do # rubocop:disable Metrics/BlockLength
126
126
  case stream.peek.type
127
- when Token::RBRACKET
127
+ when :token_rbracket
128
128
  break
129
- when Token::INDEX
129
+ when :token_index
130
130
  selectors << parse_index_or_slice(stream)
131
- when Token::DOUBLE_QUOTE_STRING, Token::SINGLE_QUOTE_STRING
131
+ when :token_double_quote_string, :token_single_quote_string
132
132
  token = stream.next
133
133
  selectors << @name_selector.new(@env, token, decode_string_literal(token))
134
- when Token::COLON
134
+ when :token_colon
135
135
  selectors << parse_slice_selector(stream)
136
- when Token::WILD
136
+ when :token_wild
137
137
  selectors << WildcardSelector.new(@env, stream.next)
138
- when Token::FILTER
138
+ when :token_filter
139
139
  selectors << parse_filter_selector(stream)
140
- when Token::EOI
140
+ when :token_eoi
141
141
  raise JSONPathSyntaxError.new("unexpected end of query", stream.next)
142
142
  else
143
143
  raise JSONPathSyntaxError.new("unexpected token in bracketed selection", stream.next)
144
144
  end
145
145
 
146
146
  case stream.peek.type
147
- when Token::EOI
147
+ when :token_eoi
148
148
  raise JSONPathSyntaxError.new("unexpected end of selector list", stream.next)
149
- when Token::RBRACKET
149
+ when :token_rbracket
150
150
  break
151
151
  else
152
- stream.expect Token::COMMA
152
+ stream.expect(:token_comma)
153
153
  stream.next
154
- stream.expect_not(Token::RBRACKET, "unexpected trailing comma")
154
+ stream.expect_not(:token_rbracket, "unexpected trailing comma")
155
155
  end
156
156
  end
157
157
 
158
- stream.expect(Token::RBRACKET)
158
+ stream.expect(:token_rbracket)
159
159
  stream.next
160
160
 
161
161
  raise JSONPathSyntaxError.new("empty segment", segment_token) if selectors.empty?
@@ -163,29 +163,29 @@ module JSONP3
163
163
  selectors
164
164
  end
165
165
 
166
- def parse_index_or_slice(stream) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
166
+ def parse_index_or_slice(stream)
167
167
  token = stream.next
168
168
  index = parse_i_json_int(token)
169
169
 
170
- return @index_selector.new(@env, token, index) unless stream.peek.type == Token::COLON
170
+ return @index_selector.new(@env, token, index) unless stream.peek.type == :token_colon
171
171
 
172
172
  stream.next # move past colon
173
173
  stop = nil
174
174
  step = nil
175
175
 
176
176
  case stream.peek.type
177
- when Token::INDEX
177
+ when :token_index
178
178
  stop = parse_i_json_int(stream.next)
179
- when Token::COLON
179
+ when :token_colon
180
180
  stream.next # move past colon
181
181
  end
182
182
 
183
- stream.next if stream.peek.type == Token::COLON
183
+ stream.next if stream.peek.type == :token_colon
184
184
 
185
185
  case stream.peek.type
186
- when Token::INDEX
186
+ when :token_index
187
187
  step = parse_i_json_int(stream.next)
188
- when Token::RBRACKET
188
+ when :token_rbracket
189
189
  nil
190
190
  else
191
191
  error_token = stream.next
@@ -195,8 +195,8 @@ module JSONP3
195
195
  SliceSelector.new(@env, token, index, stop, step)
196
196
  end
197
197
 
198
- def parse_slice_selector(stream) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
199
- stream.expect(Token::COLON)
198
+ def parse_slice_selector(stream)
199
+ stream.expect(:token_colon)
200
200
  token = stream.next
201
201
 
202
202
  start = nil
@@ -204,18 +204,18 @@ module JSONP3
204
204
  step = nil
205
205
 
206
206
  case stream.peek.type
207
- when Token::INDEX
207
+ when :token_index
208
208
  stop = parse_i_json_int(stream.next)
209
- when Token::COLON
209
+ when :token_colon
210
210
  stream.next # move past colon
211
211
  end
212
212
 
213
- stream.next if stream.peek.type == Token::COLON
213
+ stream.next if stream.peek.type == :token_colon
214
214
 
215
215
  case stream.peek.type
216
- when Token::INDEX
216
+ when :token_index
217
217
  step = parse_i_json_int(stream.next)
218
- when Token::RBRACKET
218
+ when :token_rbracket
219
219
  nil
220
220
  else
221
221
  error_token = stream.next
@@ -225,14 +225,14 @@ module JSONP3
225
225
  SliceSelector.new(@env, token, start, stop, step)
226
226
  end
227
227
 
228
- def parse_filter_selector(stream) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
228
+ def parse_filter_selector(stream)
229
229
  token = stream.next
230
230
  expression = parse_filter_expression(stream)
231
231
 
232
232
  # Raise if expression must be compared.
233
233
  if expression.is_a? FunctionExpression
234
234
  func = @env.function_extensions[expression.name]
235
- if func.class::RETURN_TYPE == ExpressionType::VALUE
235
+ if func.class::RETURN_TYPE == :value_expression
236
236
  raise JSONPathTypeError.new("result of #{expression.name}() must be compared", expression.token)
237
237
  end
238
238
  end
@@ -245,30 +245,30 @@ module JSONP3
245
245
  FilterSelector.new(@env, token, FilterExpression.new(token, expression))
246
246
  end
247
247
 
248
- def parse_filter_expression(stream, precedence = Precedence::LOWEST) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity
248
+ def parse_filter_expression(stream, precedence = Precedence::LOWEST) # rubocop:disable Metrics/CyclomaticComplexity
249
249
  left = case stream.peek.type
250
- when Token::DOUBLE_QUOTE_STRING, Token::SINGLE_QUOTE_STRING
250
+ when :token_double_quote_string, :token_single_quote_string
251
251
  token = stream.next
252
252
  StringLiteral.new(token, decode_string_literal(token))
253
- when Token::FALSE
253
+ when :token_false
254
254
  BooleanLiteral.new(stream.next, false)
255
- when Token::TRUE
255
+ when :token_true
256
256
  BooleanLiteral.new(stream.next, true)
257
- when Token::FLOAT
257
+ when :token_float
258
258
  parse_float_literal(stream)
259
- when Token::FUNCTION
259
+ when :token_function
260
260
  parse_function_expression(stream)
261
- when Token::INT
261
+ when :token_int
262
262
  parse_integer_literal(stream)
263
- when Token::LPAREN
263
+ when :token_lparen
264
264
  parse_grouped_expression(stream)
265
- when Token::NOT
265
+ when :token_not
266
266
  parse_prefix_expression(stream)
267
- when Token::NULL
267
+ when :token_null
268
268
  NullLiteral.new(stream.next, nil)
269
- when Token::ROOT
269
+ when :token_root
270
270
  parse_root_query(stream)
271
- when Token::CURRENT
271
+ when :token_current
272
272
  parse_relative_query(stream)
273
273
  else
274
274
  token = stream.next
@@ -277,8 +277,8 @@ module JSONP3
277
277
 
278
278
  loop do
279
279
  peeked = stream.peek
280
- if peeked.type == Token::EOI ||
281
- peeked.type == Token::RBRACKET ||
280
+ if peeked.type == :token_eoi ||
281
+ peeked.type == :token_rbracket ||
282
282
  PRECEDENCES.fetch(peeked.type, Precedence::LOWEST) < precedence
283
283
  break
284
284
  end
@@ -313,30 +313,30 @@ module JSONP3
313
313
  end
314
314
  end
315
315
 
316
- def parse_function_expression(stream) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity
316
+ def parse_function_expression(stream)
317
317
  token = stream.next
318
- args = []
318
+ args = [] # : Array[Expression]
319
319
 
320
- while stream.peek.type != Token::RPAREN
320
+ while stream.peek.type != :token_rparen
321
321
  expr = case stream.peek.type
322
- when Token::DOUBLE_QUOTE_STRING, Token::SINGLE_QUOTE_STRING
322
+ when :token_double_quote_string, :token_single_quote_string
323
323
  arg_token = stream.next
324
324
  StringLiteral.new(arg_token, decode_string_literal(arg_token))
325
- when Token::FALSE
325
+ when :token_false
326
326
  BooleanLiteral.new(stream.next, false)
327
- when Token::TRUE
327
+ when :token_true
328
328
  BooleanLiteral.new(stream.next, true)
329
- when Token::FLOAT
329
+ when :token_float
330
330
  parse_float_literal(stream)
331
- when Token::FUNCTION
331
+ when :token_function
332
332
  parse_function_expression(stream)
333
- when Token::INT
333
+ when :token_int
334
334
  parse_integer_literal(stream)
335
- when Token::NULL
335
+ when :token_null
336
336
  NullLiteral.new(stream.next, nil)
337
- when Token::ROOT
337
+ when :token_root
338
338
  parse_root_query(stream)
339
- when Token::CURRENT
339
+ when :token_current
340
340
  parse_relative_query(stream)
341
341
  else
342
342
  arg_token = stream.next
@@ -347,13 +347,13 @@ module JSONP3
347
347
 
348
348
  args << expr
349
349
 
350
- if stream.peek.type != Token::RPAREN
351
- stream.expect(Token::COMMA)
350
+ if stream.peek.type != :token_rparen
351
+ stream.expect(:token_comma)
352
352
  stream.next
353
353
  end
354
354
  end
355
355
 
356
- stream.expect(Token::RPAREN)
356
+ stream.expect(:token_rparen)
357
357
  stream.next
358
358
 
359
359
  validate_function_extension_signature(token, args)
@@ -364,13 +364,13 @@ module JSONP3
364
364
  stream.next # discard "("
365
365
  expr = parse_filter_expression(stream)
366
366
 
367
- while stream.peek.type != Token::RPAREN
368
- raise JSONPathSyntaxError.new("unbalanced parentheses", stream.peek) if stream.peek.type == Token::EOI
367
+ while stream.peek.type != :token_rparen
368
+ raise JSONPathSyntaxError.new("unbalanced parentheses", stream.peek) if stream.peek.type == :token_eoi
369
369
 
370
370
  expr = parse_infix_expression(stream, expr)
371
371
  end
372
372
 
373
- stream.expect(Token::RPAREN)
373
+ stream.expect(:token_rparen)
374
374
  stream.next
375
375
  expr
376
376
  end
@@ -390,7 +390,7 @@ module JSONP3
390
390
  RelativeQueryExpression.new(token, JSONPath.new(@env, parse_query(stream)))
391
391
  end
392
392
 
393
- def parse_infix_expression(stream, left) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity
393
+ def parse_infix_expression(stream, left)
394
394
  token = stream.next
395
395
  precedence = PRECEDENCES.fetch(token.type, Precedence::LOWEST)
396
396
  right = parse_filter_expression(stream, precedence)
@@ -399,28 +399,28 @@ module JSONP3
399
399
  raise_for_non_comparable_function(left)
400
400
  raise_for_non_comparable_function(right)
401
401
  case token.type
402
- when Token::EQ
402
+ when :token_eq
403
403
  EqExpression.new(token, left, right)
404
- when Token::GE
404
+ when :token_ge
405
405
  GeExpression.new(token, left, right)
406
- when Token::GT
406
+ when :token_gt
407
407
  GtExpression.new(token, left, right)
408
- when Token::LE
408
+ when :token_le
409
409
  LeExpression.new(token, left, right)
410
- when Token::LT
410
+ when :token_lt
411
411
  LtExpression.new(token, left, right)
412
- when Token::NE
412
+ when :token_ne
413
413
  NeExpression.new(token, left, right)
414
414
  else
415
415
  raise JSONPathSyntaxError.new("unexpected token", token)
416
416
  end
417
417
  else
418
- raise_for_uncompared_literal(left)
419
- raise_for_uncompared_literal(right)
418
+ raise_for_not_compared_literal(left)
419
+ raise_for_not_compared_literal(right)
420
420
  case token.type
421
- when Token::AND
421
+ when :token_and
422
422
  LogicalAndExpression.new(token, left, right)
423
- when Token::OR
423
+ when :token_or
424
424
  LogicalOrExpression.new(token, left, right)
425
425
  else
426
426
  raise JSONPathSyntaxError.new("unexpected token", token)
@@ -428,7 +428,7 @@ module JSONP3
428
428
  end
429
429
  end
430
430
 
431
- def parse_i_json_int(token) # rubocop:disable Metrics/MethodLength
431
+ def parse_i_json_int(token)
432
432
  value = token.value
433
433
 
434
434
  if value.length > 1 && value.start_with?("0", "-0")
@@ -450,7 +450,7 @@ module JSONP3
450
450
  end
451
451
 
452
452
  def decode_string_literal(token)
453
- if token.type == Token::SINGLE_QUOTE_STRING
453
+ if token.type == :token_single_quote_string
454
454
  JSONP3.unescape_string(token.value, "'", token)
455
455
  else
456
456
  JSONP3.unescape_string(token.value, '"', token)
@@ -465,19 +465,19 @@ module JSONP3
465
465
  return unless expression.is_a?(FunctionExpression)
466
466
 
467
467
  func = @env.function_extensions[expression.name]
468
- return unless func.class::RETURN_TYPE != ExpressionType::VALUE
468
+ return unless func.class::RETURN_TYPE != :value_expression
469
469
 
470
470
  raise JSONPathTypeError.new("result of #{expression.name}() is not comparable", expression.token)
471
471
  end
472
472
 
473
- def raise_for_uncompared_literal(expression)
473
+ def raise_for_not_compared_literal(expression)
474
474
  return unless expression.is_a? FilterExpressionLiteral
475
475
 
476
476
  raise JSONPathSyntaxError.new("expression literals must be compared",
477
477
  expression.token)
478
478
  end
479
479
 
480
- def validate_function_extension_signature(token, args) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
480
+ def validate_function_extension_signature(token, args) # rubocop:disable Metrics/CyclomaticComplexity
481
481
  func = @env.function_extensions.fetch(token.value)
482
482
  count = func.class::ARG_TYPES.length
483
483
 
@@ -491,18 +491,18 @@ module JSONP3
491
491
  func.class::ARG_TYPES.each_with_index do |t, i|
492
492
  arg = args[i]
493
493
  case t
494
- when ExpressionType::VALUE
494
+ when :value_expression
495
495
  unless arg.is_a?(FilterExpressionLiteral) ||
496
496
  (arg.is_a?(QueryExpression) && arg.query.singular?) ||
497
- (function_return_type(arg) == ExpressionType::VALUE)
497
+ (function_return_type(arg) == :value_expression)
498
498
  raise JSONPathTypeError.new("#{token.value}() argument #{i} must be of ValueType", arg.token)
499
499
  end
500
- when ExpressionType::LOGICAL
500
+ when :logical_expression
501
501
  unless arg.is_a?(QueryExpression) || arg.is_a?(InfixExpression)
502
502
  raise JSONPathTypeError.new("#{token.value}() argument #{i} must be of LogicalType", arg.token)
503
503
  end
504
- when ExpressionType::NODES
505
- unless arg.is_a?(QueryExpression) || function_return_type(arg) == ExpressionType::NODES
504
+ when :nodes_expression
505
+ unless arg.is_a?(QueryExpression) || function_return_type(arg) == :nodes_expression
506
506
  raise JSONPathTypeError.new("#{token.value}() argument #{i} must be of NodesType", arg.token)
507
507
  end
508
508
  end
@@ -518,27 +518,27 @@ module JSONP3
518
518
  end
519
519
 
520
520
  PRECEDENCES = {
521
- Token::AND => Precedence::LOGICAL_AND,
522
- Token::OR => Precedence::LOGICAL_OR,
523
- Token::NOT => Precedence::PREFIX,
524
- Token::EQ => Precedence::RELATIONAL,
525
- Token::GE => Precedence::RELATIONAL,
526
- Token::GT => Precedence::RELATIONAL,
527
- Token::LE => Precedence::RELATIONAL,
528
- Token::LT => Precedence::RELATIONAL,
529
- Token::NE => Precedence::RELATIONAL,
530
- Token::RPAREN => Precedence::LOWEST
521
+ token_and: Precedence::LOGICAL_AND,
522
+ token_or: Precedence::LOGICAL_OR,
523
+ token_not: Precedence::PREFIX,
524
+ token_eq: Precedence::RELATIONAL,
525
+ token_ge: Precedence::RELATIONAL,
526
+ token_gt: Precedence::RELATIONAL,
527
+ token_le: Precedence::RELATIONAL,
528
+ token_lt: Precedence::RELATIONAL,
529
+ token_ne: Precedence::RELATIONAL,
530
+ token_rparen: Precedence::LOWEST
531
531
  }.freeze
532
532
 
533
533
  BINARY_OPERATORS = {
534
- Token::AND => "&&",
535
- Token::OR => "||",
536
- Token::EQ => "==",
537
- Token::GE => ">=",
538
- Token::GT => ">",
539
- Token::LE => "<=",
540
- Token::LT => "<",
541
- Token::NE => "!="
534
+ token_and: "&&",
535
+ token_or: "||",
536
+ token_eq: "==",
537
+ token_ge: ">=",
538
+ token_gt: ">",
539
+ token_le: "<=",
540
+ token_lt: "<",
541
+ token_ne: "!="
542
542
  }.freeze
543
543
 
544
544
  COMPARISON_OPERATORS = Set[