jcrvalidator 0.6.5 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e456ba6147ad0fa9bd8f9e38e8c042816f501d4f
4
- data.tar.gz: 8114d7992f86d0396e0508121f8a07e62c712f15
3
+ metadata.gz: 1092c1613500ed477ee3eb26367ed73fee3a940f
4
+ data.tar.gz: 824cdfcc22c6dc6a03d55bc10ad75857c881c627
5
5
  SHA512:
6
- metadata.gz: 25f08291b2a347a7d22f50de3ae182cc395b56a235004bfb454bcca7a8d1ebe43297aaba7573bee57491103378cc52119142fcf5cc4fc780ae31dbfd7561d623
7
- data.tar.gz: 7c002e9126134b957ec032a06ec98e547ae59cb097be17142e75aba8582ad59bbb7c5986261c6d4a9eb1319194ef9f0c7add95986bba9547fdea296652a635e3
6
+ metadata.gz: 6f6f55143125ef7cf87457a53bb66edb4c3b353fb710e8513cf85e893f969d7cb3b95a78d98429fef5c55b8b25fb4306455ecb1cf9c77c449c71d1ad2dedba84
7
+ data.tar.gz: 9539a3d5ad7577a119f30bb69596c8cb279d1d45818574b26f22c1f71613cac0ba785268a56797f57266b5533de8cc159fa42f9055643d8272a141642b024813
@@ -289,6 +289,6 @@ module JCR
289
289
 
290
290
  def self.array_to_s( jcr, shallow=true )
291
291
  rules, annotations = get_rules_and_annotations( jcr )
292
- return "#{annotations_to_s( annotations)} [ #{rules_to_s( rules, shallow )} ]"
292
+ return "#{annotations_to_s( annotations)}[ #{rules_to_s( rules, shallow )} ]"
293
293
  end
294
294
  end
@@ -58,7 +58,7 @@ module JCR
58
58
 
59
59
  def self.group_to_s( jcr, shallow=true)
60
60
  rules, annotations = get_rules_and_annotations( jcr )
61
- return "#{annotations_to_s( annotations)} ( #{rules_to_s(rules,shallow)} )"
61
+ return "#{annotations_to_s( annotations)}( #{rules_to_s(rules,shallow)} )"
62
62
  end
63
63
 
64
64
  end
@@ -174,6 +174,6 @@ module JCR
174
174
 
175
175
  def self.object_to_s( jcr, shallow=true )
176
176
  rules, annotations = get_rules_and_annotations( jcr )
177
- return "#{annotations_to_s( annotations)} { #{rules_to_s(rules,shallow)} }"
177
+ return "#{annotations_to_s( annotations)}{ #{rules_to_s(rules,shallow)} }"
178
178
  end
179
179
  end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2015-2016 American Registry for Internet Numbers
1
+ # Copyright (c) 2015-2017 American Registry for Internet Numbers
2
2
  #
3
3
  # Permission to use, copy, modify, and/or distribute this software for any
4
4
  # purpose with or without fee is hereby granted, provided that the above
@@ -54,9 +54,9 @@ module JCR
54
54
  end
55
55
 
56
56
  class EvalConditions
57
- attr_accessor :mapping, :callbacks, :trace, :trace_stack, :first_failure
57
+ attr_accessor :mapping, :callbacks, :trace, :trace_stack, :failures
58
58
  def initialize mapping, callbacks, trace = false
59
- @first_failure = nil
59
+ @failures = {}
60
60
  @mapping = mapping
61
61
  @trace = trace
62
62
  @trace_stack = []
@@ -66,6 +66,29 @@ module JCR
66
66
  @callbacks = {}
67
67
  end
68
68
  end
69
+
70
+ def report_failure failure
71
+ @failures[ failure.stack_level ] = Array.new unless @failures[ failure.stack_level ]
72
+ @failures[ failure.stack_level ] << failure
73
+ end
74
+ end
75
+
76
+ class Failure
77
+ attr_accessor :data, :json, :json_elided, :evaluation, :rule, :pos, :offset, :type, :definition, :stack_level, :reason_elided
78
+ def initialize data, jcr, type, evaluation, stack_level
79
+ @json = data.to_json
80
+ @json_elided = JCR::elide(@json)
81
+ @data = JCR::rule_data( data )
82
+ @rule = JCR::find_first_slice( jcr )
83
+ @pos = @rule.line_and_column
84
+ @offset = @rule.offset
85
+ @type = type
86
+ @evaluation = evaluation
87
+ @reason_elided = "unknown reason"
88
+ @reason_elided = JCR::elide( @evaluation.reason ) if @evaluation.reason
89
+ @definition = JCR::rule_def( type, jcr )
90
+ @stack_level = stack_level
91
+ end
69
92
  end
70
93
 
71
94
  def self.evaluate_rule jcr, rule_atom, data, econs, behavior = nil
@@ -271,22 +294,30 @@ module JCR
271
294
  end
272
295
 
273
296
  def self.elide s
274
- if s.length > 60
275
- s = s[0..56]
297
+ if s.length > 45
298
+ s = s[0..41]
276
299
  s = s + " ..."
277
300
  end
278
301
  return s
279
302
  end
280
303
 
304
+ def self.rule_data data=nil
305
+ if data
306
+ if data.is_a? String
307
+ s = '"' + data + '"'
308
+ else
309
+ s = data.pretty_print_inspect
310
+ end
311
+ return elide(s)
312
+ end
313
+ #else
314
+ return nil
315
+ end
316
+
281
317
  def self.trace econs, message, data = nil
282
318
  if econs.trace
283
319
  if data
284
- if data.is_a? String
285
- s = '"' + data + '"'
286
- else
287
- s = data.pretty_print_inspect
288
- end
289
- message = "#{message} data: #{elide(s)}"
320
+ message = "#{message} data: #{rule_data( data )}"
290
321
  end
291
322
  last = econs.trace_stack.last
292
323
  pos = "#{last.line_and_column}@#{last.offset}" if last
@@ -294,6 +325,25 @@ module JCR
294
325
  end
295
326
  end
296
327
 
328
+ def self.rule_def type, jcr
329
+ s = ""
330
+ case type
331
+ when "value"
332
+ s = elide(value_to_s(jcr))
333
+ when "member"
334
+ s = elide(member_to_s(jcr))
335
+ when "object"
336
+ s = elide(object_to_s(jcr))
337
+ when "array"
338
+ s = elide(array_to_s(jcr))
339
+ when "group"
340
+ s = elide(group_to_s(jcr))
341
+ else
342
+ s = "** unknown rule **"
343
+ end
344
+ return "#{type} definition: #{s}"
345
+ end
346
+
297
347
  def self.trace_def econs, type, jcr, data
298
348
  if econs.trace
299
349
  s = ""
@@ -311,7 +361,7 @@ module JCR
311
361
  else
312
362
  s = "** unknown rule **"
313
363
  end
314
- trace( econs, "#{type} definition: #{s}", data)
364
+ trace( econs, rule_def( type, jcr ) )
315
365
  end
316
366
  end
317
367
 
@@ -319,19 +369,9 @@ module JCR
319
369
  if evaluation.success
320
370
  trace( econs, "#{message} evaluation is true" )
321
371
  else
372
+ failure = Failure.new( data, jcr, type, evaluation, econs.trace_stack.length )
373
+ econs.report_failure( failure )
322
374
  trace( econs, "#{message} evaluation failed: #{evaluation.reason}")
323
- unless econs.first_failure
324
- econs.first_failure = evaluation
325
- trace( econs, "** LIKELY ROOT CAUSE FOR FAILURE **" )
326
- trace( econs, "***********************************" )
327
- rule = find_first_slice( jcr )
328
- pos = "Failed rule at line,column: #{rule.line_and_column} file position offset: #{rule.offset}"
329
- trace( econs, pos )
330
- trace_def( econs, type, jcr, data )
331
- data_s = "JSON that failed to validate: #{data.to_json}"
332
- trace( econs, data_s )
333
- trace( econs, "***********************************" )
334
- end
335
375
  end
336
376
  end
337
377
 
@@ -373,6 +413,20 @@ module JCR
373
413
  end
374
414
 
375
415
  def self.rule_to_s( rule, shallow=true)
416
+ if rule[:rule_name]
417
+ if rule[:primitive_rule]
418
+ retval = "$#{rule[:rule_name].to_s} =: #{ruletype_to_s( rule, shallow )}"
419
+ else
420
+ retval = "$#{rule[:rule_name].to_s} = #{ruletype_to_s( rule, shallow )}"
421
+ end
422
+ else
423
+ retval = ruletype_to_s( rule, shallow )
424
+ end
425
+ return retval
426
+ end
427
+
428
+ def self.ruletype_to_s( rule, shallow=true )
429
+
376
430
  if rule[:primitive_rule]
377
431
  retval = value_to_s( rule[:primitive_rule] )
378
432
  elsif rule[:member_rule]
@@ -393,6 +447,7 @@ module JCR
393
447
  retval = "** unknown rule definition ** #{rule}"
394
448
  end
395
449
  return retval
450
+
396
451
  end
397
452
 
398
453
  def self.rules_to_s( rules, shallow=true)
@@ -405,7 +460,7 @@ module JCR
405
460
  elsif rule[:sequence_combiner]
406
461
  retval = retval + " , "
407
462
  end
408
- retval = retval + rule_to_s( rule, shallow )
463
+ retval = retval + rule_to_s( rule, shallow ) + repetitions_to_s( rule )
409
464
  end
410
465
  return retval
411
466
  end
@@ -415,13 +470,13 @@ module JCR
415
470
  annotations.each do |a|
416
471
  case
417
472
  when a[:unordered_annotation]
418
- retval = retval + " @{unordered}"
473
+ retval = retval + "@{unordered}"
419
474
  when a[:not_annotation]
420
- retval = retval + " @{not}"
475
+ retval = retval + "@{not}"
421
476
  when a[:root_annotation]
422
- retval = retval + " @{root}"
477
+ retval = retval + "@{root}"
423
478
  else
424
- retval = retval + " @{ ** unknown annotation ** }"
479
+ retval = retval + "@{ ** unknown annotation ** }"
425
480
  end
426
481
  end if annotations
427
482
  retval = retval + " " if retval.length != 0
@@ -429,7 +484,50 @@ module JCR
429
484
  end
430
485
 
431
486
  def self.target_to_s( jcr )
432
- return annotations_to_s( jcr[:annotations] ) + " target: " + jcr[:rule_name].to_s
487
+ return annotations_to_s( jcr[:annotations] ) + "$" + jcr[:rule_name].to_s
488
+ end
489
+
490
+ def self.repetitions_to_s rule
491
+ retval = ""
492
+ if rule[:optional]
493
+ retval = "?"
494
+ elsif rule[:one_or_more]
495
+ retval = "+"
496
+ if rule[:repetition_step]
497
+ retval = "%" + rule[:repetition_step].to_s
498
+ end
499
+ elsif rule[:zero_or_more]
500
+ retval = "*"
501
+ retval = retval + "%" + rule[:repetition_step].to_s if rule[:repetition_step]
502
+ elsif rule[:specific_repetition] && rule[:specific_repetition].is_a?( Parslet::Slice )
503
+ retval = "*" + rule[:specific_repetition].to_s
504
+ else
505
+ if rule[:repetition_interval]
506
+ min = "0"
507
+ max = "INF"
508
+ o = rule[:repetition_min]
509
+ if o
510
+ if o.is_a?(Parslet::Slice)
511
+ min = o.to_s
512
+ end
513
+ end
514
+ o = rule[:repetition_max]
515
+ if o
516
+ if o.is_a?(Parslet::Slice)
517
+ max = o.to_s
518
+ end
519
+ end
520
+ retval = "*"+min+".."+max
521
+ end
522
+ o = rule[:repetition_step]
523
+ if o
524
+ if o.is_a?( Parslet::Slice )
525
+ retval = retval + "%" + o.to_s
526
+ end
527
+ end
528
+ end
529
+ retval = " " + retval if retval.length != 0
530
+ return retval
433
531
  end
434
532
 
435
533
  end
@@ -55,35 +55,35 @@ module JCR
55
55
  when jcr[:integer_v]
56
56
  si = jcr[:integer_v].to_s
57
57
  if si == "integer"
58
- return bad_value( jcr, rule_atom, "integer", data ) unless data.is_a?( Fixnum )
58
+ return bad_value( jcr, rule_atom, "integer", data ) unless data.is_a?( Integer )
59
59
  end
60
60
  when jcr[:integer]
61
61
  i = jcr[:integer].to_s.to_i
62
62
  return bad_value( jcr, rule_atom, i, data ) unless data == i
63
63
  when jcr[:integer_min] != nil && jcr[:integer_max] == nil
64
- return bad_value( jcr, rule_atom, "integer", data ) unless data.is_a?( Fixnum )
64
+ return bad_value( jcr, rule_atom, "integer", data ) unless data.is_a?( Integer )
65
65
  min = jcr[:integer_min].to_s.to_i
66
66
  return bad_value( jcr, rule_atom, min, data ) unless data >= min
67
67
  when jcr[:integer_min] == nil && jcr[:integer_max] != nil
68
- return bad_value( jcr, rule_atom, "integer", data ) unless data.is_a?( Fixnum )
68
+ return bad_value( jcr, rule_atom, "integer", data ) unless data.is_a?( Integer )
69
69
  max = jcr[:integer_max].to_s.to_i
70
70
  return bad_value( jcr, rule_atom, max, data ) unless data <= max
71
71
  when jcr[:integer_min],jcr[:integer_max]
72
- return bad_value( jcr, rule_atom, "integer", data ) unless data.is_a?( Fixnum )
72
+ return bad_value( jcr, rule_atom, "integer", data ) unless data.is_a?( Integer )
73
73
  min = jcr[:integer_min].to_s.to_i
74
74
  return bad_value( jcr, rule_atom, min, data ) unless data >= min
75
75
  max = jcr[:integer_max].to_s.to_i
76
76
  return bad_value( jcr, rule_atom, max, data ) unless data <= max
77
77
  when jcr[:sized_int_v]
78
78
  bits = jcr[:sized_int_v][:bits].to_i
79
- return bad_value( jcr, rule_atom, "int" + bits.to_s, data ) unless data.is_a?( Fixnum )
79
+ return bad_value( jcr, rule_atom, "int" + bits.to_s, data ) unless data.is_a?( Integer )
80
80
  min = -(2**(bits-1))
81
81
  return bad_value( jcr, rule_atom, min, data ) unless data >= min
82
82
  max = 2**(bits-1)-1
83
83
  return bad_value( jcr, rule_atom, max, data ) unless data <= max
84
84
  when jcr[:sized_uint_v]
85
85
  bits = jcr[:sized_uint_v][:bits].to_i
86
- return bad_value( jcr, rule_atom, "int" + bits.to_s, data ) unless data.is_a?( Fixnum )
86
+ return bad_value( jcr, rule_atom, "int" + bits.to_s, data ) unless data.is_a?( Integer )
87
87
  min = 0
88
88
  return bad_value( jcr, rule_atom, min, data ) unless data >= min
89
89
  max = 2**bits-1
@@ -470,9 +470,9 @@ module JCR
470
470
 
471
471
  when rule[:uri]
472
472
  if rule[:uri].is_a? Hash
473
- retval = "URI with specific scheme #{rule[:uri][:uri_scheme].to_s}"
473
+ retval = "uri..#{rule[:uri][:uri_scheme].to_s}"
474
474
  else
475
- retval = "URI"
475
+ retval = "uri"
476
476
  end
477
477
 
478
478
  when rule[:email]
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2015-2016 American Registry for Internet Numbers
1
+ # Copyright (c) 2015-2017 American Registry for Internet Numbers
2
2
  #
3
3
  # Permission to use, copy, modify, and/or distribute this software for any
4
4
  # purpose with or without fee is hereby granted, provided that the above
@@ -18,7 +18,7 @@ require 'jcr/evaluate_rules'
18
18
  module JCR
19
19
 
20
20
  class Root
21
- attr_accessor :nameless, :name, :rule, :default
21
+ attr_accessor :nameless, :name, :rule, :default, :slice, :pos, :offset, :failures
22
22
 
23
23
  def initialize rule, name = nil, nameless = true, default = false
24
24
  @rule = rule
@@ -28,6 +28,9 @@ module JCR
28
28
  @nameless = false
29
29
  end
30
30
  @default = default
31
+ @slice = JCR::find_first_slice( rule )
32
+ @pos = @slice.line_and_column
33
+ @offset = @slice.offset
31
34
  end
32
35
  end
33
36
 
@@ -52,18 +55,41 @@ module JCR
52
55
  rn = node[:rule][:rule_name].to_str
53
56
  rule = node[:rule]
54
57
  ruledef = get_rule_by_type( rule )
55
- if ruledef
58
+ new_root = nil
59
+ # look to see if the root_annotation is in the name before assignment ( @{root} $r = ... )
60
+ if rule[:annotations]
61
+ if rule[:annotations].is_a? Array
62
+ rule[:annotations].each do |annotation|
63
+ if annotation[:root_annotation]
64
+ new_root = Root.new(node, rn)
65
+ roots << new_root
66
+ # root is found, now look into subrule for unnamed roots
67
+ subrule = get_rule_by_type( ruledef )
68
+ roots.concat( find_roots_in_unnamed( subrule ) ) if subrule
69
+ end
70
+ end
71
+ elsif rule[:annotations][:root_annotation]
72
+ new_root = Root.new(node, rn)
73
+ roots << new_root
74
+ # root is found, now look into subrule for unnamed roots
75
+ subrule = get_rule_by_type( ruledef )
76
+ roots.concat( find_roots_in_unnamed( subrule ) ) if subrule
77
+ end
78
+ end
79
+ if ruledef && !new_root
56
80
  if ruledef.is_a? Array
57
81
  ruledef.each do |rdi|
82
+ # if it has a @{root} annotation in the rule definition
58
83
  if rdi[:root_annotation]
59
- roots << Root.new( node, rn )
60
- elsif (subrule = get_rule_by_type( rdi ))
61
- roots.concat( find_roots_in_unnamed( subrule ) )
84
+ roots << Root.new(node, rn)
85
+ # else look into the definition further and examine subrules
86
+ elsif (subrule = get_rule_by_type(rdi))
87
+ roots.concat(find_roots_in_unnamed(subrule))
62
88
  end
63
89
  end
64
90
  elsif ruledef.is_a? Hash
65
- subrule = get_rule_by_type( ruledef )
66
- roots.concat( find_roots_in_unnamed( subrule ) ) if subrule
91
+ subrule = get_rule_by_type(ruledef)
92
+ roots.concat(find_roots_in_unnamed(subrule)) if subrule
67
93
  end
68
94
  end
69
95
  return roots
data/lib/jcr/jcr.rb CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2015-2016 American Registry for Internet Numbers
1
+ # Copyright (c) 2015-2017 American Registry for Internet Numbers
2
2
  #
3
3
  # Permission to use, copy, modify, and/or distribute this software for any
4
4
  # purpose with or without fee is hereby granted, provided that the above
@@ -28,7 +28,7 @@ require 'jcr/version'
28
28
  module JCR
29
29
 
30
30
  class Context
31
- attr_accessor :mapping, :callbacks, :id, :tree, :roots, :catalog, :trace
31
+ attr_accessor :mapping, :callbacks, :id, :tree, :roots, :catalog, :trace, :failed_roots, :failure_report
32
32
 
33
33
  def add_ruleset_alias( ruleset_alias, alias_uri )
34
34
  unless @catalog
@@ -60,6 +60,7 @@ module JCR
60
60
 
61
61
  def initialize( ruleset = nil, trace = false )
62
62
  @trace = trace
63
+ @failed_roots = []
63
64
  if ruleset
64
65
  ingested = JCR.ingest_ruleset( ruleset, false, nil )
65
66
  @mapping = ingested.mapping
@@ -109,30 +110,56 @@ module JCR
109
110
  end
110
111
 
111
112
  def self.evaluate_ruleset( data, ctx, root_name = nil )
112
- root_rules = []
113
+ roots = []
113
114
  if root_name
114
115
  root_rule = ctx.mapping[root_name]
115
116
  raise "No rule by the name of #{root_name} for a root rule has been found" unless root_rule
116
- root_rules << root_rule
117
+ root = JCR::Root.new( root_rule, root_name )
118
+ roots << root
117
119
  else
118
- ctx.roots.each do |r|
119
- root_rules << r.rule
120
- end
120
+ roots = ctx.roots
121
121
  end
122
122
 
123
- raise "No root rule defined. Specify a root rule name" if root_rules.empty?
123
+ raise "No root rule defined. Specify a root rule name" if roots.empty?
124
124
 
125
125
  retval = nil
126
- root_rules.each do |r|
127
- pp "Evaluating Root:", rule_to_s( r, false ) if ctx.trace
128
- raise "Root rules cannot be member rules" if r[:member_rule]
129
- retval = JCR.evaluate_rule( r, r, data, EvalConditions.new( ctx.mapping, ctx.callbacks, ctx.trace ) )
126
+ roots.each do |r|
127
+ pp "Evaluating Root:", rule_to_s( r.rule, false ) if ctx.trace
128
+ raise "Root rules cannot be member rules" if r.rule[:member_rule]
129
+ econs = EvalConditions.new( ctx.mapping, ctx.callbacks, ctx.trace )
130
+ retval = JCR.evaluate_rule( r.rule, r.rule, data, econs )
130
131
  break if retval.success
132
+ # else
133
+ r.failures = econs.failures
134
+ ctx.failed_roots << r
131
135
  end
132
136
 
137
+ ctx.failure_report = failure_report( ctx )
133
138
  return retval
134
139
  end
135
140
 
141
+ def self.failure_report ctx
142
+ report = []
143
+ ctx.failed_roots.each do |failed_root|
144
+ if failed_root.name
145
+ report << "- ** Failures for root rule named '#{failed_root.name}'"
146
+ else
147
+ report << "- ** Failures for root rule at line #{failed_root.pos[0]}"
148
+ end
149
+ failed_root.failures.sort.map do |stack_level, failures|
150
+ if failures.length > 1
151
+ report << " - failure at rule depth #{stack_level} caused by one of the following #{failures.length} reasons"
152
+ else
153
+ report << " - failure at rule depth #{stack_level} caused by"
154
+ end
155
+ failures.each_with_index do |failure, index|
156
+ report << " - #{failure.json_elided} failed rule #{failure.definition} at #{failure.pos} because #{failure.reason_elided}"
157
+ end
158
+ end
159
+ end
160
+ return report
161
+ end
162
+
136
163
  def self.main my_argv=nil
137
164
 
138
165
  my_argv = ARGV unless my_argv
@@ -205,6 +232,10 @@ module JCR
205
232
  options[:verbose] = true
206
233
  end
207
234
 
235
+ opt.on("-q","quiet") do |quiet|
236
+ options[:quiet] = true
237
+ end
238
+
208
239
  opt.on("-h","display help") do |help|
209
240
  options[:help] = true
210
241
  end
@@ -243,7 +274,7 @@ module JCR
243
274
 
244
275
  if options[:verbose]
245
276
  pp "Ruleset Parse Tree", ctx.tree
246
- pp "Ruleset Map"
277
+ puts "Ruleset Map"
247
278
  ctx.mapping.each do |name,rule|
248
279
  puts "Parsed Rule: #{name}"
249
280
  puts rule_to_s( rule, false )
@@ -258,7 +289,7 @@ module JCR
258
289
  return 0
259
290
  elsif options[:json]
260
291
  data = JSON.parse( options[:json] )
261
- ec = cli_eval( ctx, data, options[:root_name], options[:verbose] )
292
+ ec = cli_eval( ctx, data, options[:root_name], options[:quiet] )
262
293
  return ec
263
294
  elsif $stdin.tty?
264
295
  ec = 0
@@ -267,35 +298,55 @@ module JCR
267
298
  else
268
299
  my_argv.each do |fn|
269
300
  data = JSON.parse( File.open( fn ).read )
270
- tec = cli_eval( ctx, data, options[:root_name], options[:verbose] )
301
+ tec = cli_eval( ctx, data, options[:root_name], options[:quiet] )
271
302
  ec = tec if tec != 0 #record error but don't let non-error overwrite error
272
303
  end
273
304
  end
274
305
  return ec
275
306
  else
276
- data = JSON.parse( ARGF.read )
277
- ec = cli_eval( ctx, data, options[:root_name], options[:verbose] )
307
+ lines = ""
308
+ ec = 0
309
+ ARGF.each do |line|
310
+ lines = lines + line
311
+ if ARGF.eof?
312
+ data = JSON.parse( lines )
313
+ tec = cli_eval( ctx, data, options[:root_name], options[:quiet] )
314
+ ec = tec if tec != 0 #record error but don't let non-error overwrite error
315
+ lines = ""
316
+ end
317
+ end
278
318
  return ec
279
319
  end
280
320
 
281
321
  rescue Parslet::ParseFailed => failure
282
- puts failure.cause.ascii_tree
322
+ puts failure.parse_failure_cause.ascii_tree unless options[:quiet]
323
+ return 1
324
+ rescue JSON::ParserError => parser_error
325
+ unless options[:quiet]
326
+ puts "Unable to parse JSON"
327
+ puts parser_error.message.inspect
328
+ end
329
+ return 3
283
330
  end
331
+
284
332
  end
285
333
 
286
334
  end
287
335
 
288
- def self.cli_eval ctx, data, root_name, verbose
336
+ def self.cli_eval ctx, data, root_name, quiet
289
337
  ec = 2
290
338
  e = ctx.evaluate( data, root_name )
291
339
  if e.success
292
- if verbose
340
+ unless quiet
293
341
  puts "Success!"
294
342
  end
295
343
  ec = 0
296
344
  else
297
- if verbose
298
- puts "Failure: #{e.reason}"
345
+ unless quiet
346
+ puts "Failure! Use -v for more information."
347
+ ctx.failure_report.each do |line|
348
+ puts line
349
+ end
299
350
  end
300
351
  ec = 3
301
352
  end
data/lib/jcr/parser.rb CHANGED
@@ -72,8 +72,12 @@ module JCR
72
72
  #> jcr-version-kw = "jcr-version"
73
73
  #! major_version = non_neg_integer
74
74
  #! minor_version = non_neg_integer
75
- rule(:extension_id) { match('[a-zA-Z]') >> match('[\S]').repeat }
76
- #! extension_id = ALPHA *not-space
75
+ rule(:extension_id) { id }
76
+ #! extension_id = id
77
+ rule(:id) { match('[a-zA-Z]') >> id_tail.repeat }
78
+ #! id = ALPHA *id-tail
79
+ rule(:id_tail) { match('[^\s}]') }
80
+ #! id-tail = %x21-7C / %x7E-10FFFF ; not spaces, not }
77
81
  rule(:ruleset_id_d) { (str('ruleset-id') >> dsps >> ruleset_id.as(:ruleset_id)).as(:ruleset_id_d) }
78
82
  #! ruleset_id_d = ruleset-id-kw DSPs ruleset_id
79
83
  #> ruleset-id-kw = "ruleset-id"
@@ -82,9 +86,8 @@ module JCR
82
86
  #! [ DSPs as_kw DSPs ruleset_id_alias ]
83
87
  #> import-kw = "import"
84
88
  #> as-kw = "as"
85
- rule(:ruleset_id) { match('[a-zA-Z]') >> match('[\S]').repeat }
86
- #! ruleset_id = ALPHA *not-space
87
- #! not-space = %x21-10FFFF
89
+ rule(:ruleset_id) { id }
90
+ #! ruleset_id = id
88
91
  rule(:ruleset_id_alias) { name.as(:ruleset_id_alias) }
89
92
  #! ruleset_id_alias = name
90
93
  rule(:one_line_tbd_directive_d) { name.as(:directive_name) >> ( wsp >> match('[^\r\n]').repeat.as(:directive_parameters) ).maybe }
@@ -309,41 +312,41 @@ module JCR
309
312
  str('{') >> spcCmnt? >> object_items.maybe >> spcCmnt? >> str('}') ).as(:object_rule) }
310
313
  #! object_rule = annotations "{" spcCmnt?
311
314
  #! [ object_items spcCmnt? ] "}"
312
- rule(:object_items) { object_item >> (( spcCmnt? >> sequence_combiner >> spcCmnt? >> object_item ).repeat(1) |
313
- ( spcCmnt? >> choice_combiner >> spcCmnt? >> object_item ).repeat(1) ).maybe }
314
- #! object_items = object_item (*( sequence_combiner object_item ) /
315
- #! *( choice_combiner object_item ) )
316
- rule(:object_item ) { object_item_types >> spcCmnt? >> repetition.maybe }
317
- #! object_item = object_item_types spcCmnt? [ repetition ]
315
+ rule(:object_items) { object_item >> (( sequence_combiner >> object_item ).repeat(1) |
316
+ ( choice_combiner >> object_item ).repeat(1) ).maybe }
317
+ #! object_items = object_item [ 1*( sequence_combiner object_item ) /
318
+ #! 1*( choice_combiner object_item ) ]
319
+ rule(:object_item ) { object_item_types >> spcCmnt? >> ( repetition >> spcCmnt? ).maybe }
320
+ #! object_item = object_item_types spcCmnt? [ repetition spcCmnt? ]
318
321
  rule(:object_item_types) { object_group | member_rule | target_rule_name }
319
322
  #! object_item_types = object_group / member_rule / target_rule_name
320
- rule(:object_group) { ( str('(') >> spcCmnt? >> object_items.maybe >> spcCmnt? >> str(')') ).as(:group_rule) }
321
- #! object_group = "(" spcCmnt? [ object_items spcCmnt? ] ")"
323
+ rule(:object_group) { ( annotations >> str('(') >> spcCmnt? >> object_items.maybe >> spcCmnt? >> str(')') ).as(:group_rule) }
324
+ #! object_group = annotations "(" spcCmnt? [ object_items spcCmnt? ] ")"
322
325
  #!
323
326
 
324
327
  rule(:array_rule) { ( annotations >>
325
328
  str('[') >> spcCmnt? >> array_items.maybe >> spcCmnt? >> str(']') ).as(:array_rule) }
326
329
  #! array_rule = annotations "[" spcCmnt? [ array_items spcCmnt? ] "]"
327
- rule(:array_items) { array_item >> (( spcCmnt? >> sequence_combiner >> spcCmnt? >> array_item ).repeat(1) |
328
- ( spcCmnt? >> choice_combiner >> spcCmnt? >> array_item ).repeat(1) ).maybe }
329
- #! array_items = array_item (*( sequence_combiner array_item ) /
330
- #! *( choice_combiner array_item ) )
331
- rule(:array_item) { array_item_types >> spcCmnt? >> repetition.maybe }
332
- #! array_item = array_item_types spcCmnt? [ repetition ]
330
+ rule(:array_items) { array_item >> (( sequence_combiner >> array_item ).repeat(1) |
331
+ ( choice_combiner >> array_item ).repeat(1) ).maybe }
332
+ #! array_items = array_item [ 1*( sequence_combiner array_item ) /
333
+ #! 1*( choice_combiner array_item ) ]
334
+ rule(:array_item) { array_item_types >> spcCmnt? >> ( repetition >> spcCmnt? ).maybe }
335
+ #! array_item = array_item_types spcCmnt? [ repetition spcCmnt? ]
333
336
  rule(:array_item_types) { array_group | type_rule | explicit_type_choice }
334
337
  #! array_item_types = array_group / type_rule / explicit_type_choice
335
- rule(:array_group) { ( str('(') >> spcCmnt? >> array_items.maybe >> spcCmnt? >> str(')') ).as(:group_rule) }
336
- #! array_group = "(" spcCmnt? [ array_items spcCmnt? ] ")"
338
+ rule(:array_group) { ( annotations >> str('(') >> spcCmnt? >> array_items.maybe >> spcCmnt? >> str(')') ).as(:group_rule) }
339
+ #! array_group = annotations "(" spcCmnt? [ array_items spcCmnt? ] ")"
337
340
  #!
338
341
 
339
342
  rule(:group_rule) { ( annotations >> str('(') >> spcCmnt? >> group_items.maybe >> spcCmnt? >> str(')') ).as(:group_rule) }
340
343
  #! group_rule = annotations "(" spcCmnt? [ group_items spcCmnt? ] ")"
341
- rule(:group_items) { group_item >> (( spcCmnt? >> sequence_combiner >> spcCmnt? >> group_item ).repeat(1) |
342
- ( spcCmnt? >> choice_combiner >> spcCmnt? >> group_item ).repeat(1) ).maybe }
343
- #! group_items = group_item (*( sequence_combiner group_item ) /
344
- #! *( choice_combiner group_item ) )
345
- rule(:group_item) { group_item_types >> spcCmnt? >> repetition.maybe }
346
- #! group_item = group_item_types spcCmnt? [ repetition ]
344
+ rule(:group_items) { group_item >> (( sequence_combiner >> group_item ).repeat(1) |
345
+ ( choice_combiner >> group_item ).repeat(1) ).maybe }
346
+ #! group_items = group_item [ 1*( sequence_combiner group_item ) /
347
+ #! 1*( choice_combiner group_item ) ]
348
+ rule(:group_item) { group_item_types >> spcCmnt? >> ( repetition >> spcCmnt? ).maybe }
349
+ #! group_item = group_item_types spcCmnt? [ repetition spcCmnt? ]
347
350
  rule(:group_item_types) { group_group | member_rule | type_rule | explicit_type_choice }
348
351
  #! group_item_types = group_group / member_rule /
349
352
  #! type_rule / explicit_type_choice
@@ -351,10 +354,10 @@ module JCR
351
354
  #! group_group = group_rule
352
355
  #!
353
356
 
354
- rule(:sequence_combiner) { str(',').as(:sequence_combiner) }
355
- #! sequence_combiner = spcCmnt? "," spcCmnt?
356
- rule(:choice_combiner) { str('|').as(:choice_combiner) }
357
- #! choice_combiner = spcCmnt? "|" spcCmnt?
357
+ rule(:sequence_combiner) { str(',').as(:sequence_combiner) >> spcCmnt? }
358
+ #! sequence_combiner = "," spcCmnt?
359
+ rule(:choice_combiner) { str('|').as(:choice_combiner) >> spcCmnt? }
360
+ #! choice_combiner = "|" spcCmnt?
358
361
  #!
359
362
 
360
363
  rule(:repetition) { optional | one_or_more |
data/lib/jcr/version.rb CHANGED
@@ -15,6 +15,6 @@
15
15
 
16
16
  module JCR
17
17
 
18
- VERSION = "0.6.5"
18
+ VERSION = "0.7.0"
19
19
 
20
20
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jcrvalidator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.5
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Newton
@@ -9,20 +9,20 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-09-19 00:00:00.000000000 Z
12
+ date: 2017-12-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: parslet
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - ~>
18
+ - - "~>"
19
19
  - !ruby/object:Gem::Version
20
20
  version: '1.7'
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - ~>
25
+ - - "~>"
26
26
  - !ruby/object:Gem::Version
27
27
  version: '1.7'
28
28
  - !ruby/object:Gem::Dependency
@@ -43,14 +43,14 @@ dependencies:
43
43
  name: email_address_validator
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - ~>
46
+ - - "~>"
47
47
  - !ruby/object:Gem::Version
48
48
  version: '2.0'
49
49
  type: :runtime
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
- - - ~>
53
+ - - "~>"
54
54
  - !ruby/object:Gem::Version
55
55
  version: '2.0'
56
56
  - !ruby/object:Gem::Dependency
@@ -100,19 +100,18 @@ require_paths:
100
100
  - lib
101
101
  required_ruby_version: !ruby/object:Gem::Requirement
102
102
  requirements:
103
- - - '>='
103
+ - - ">="
104
104
  - !ruby/object:Gem::Version
105
105
  version: '0'
106
106
  required_rubygems_version: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - '>='
108
+ - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  requirements: []
112
112
  rubyforge_project:
113
- rubygems_version: 2.4.5
113
+ rubygems_version: 2.5.2
114
114
  signing_key:
115
115
  specification_version: 4
116
116
  summary: JCR Validator
117
117
  test_files: []
118
- has_rdoc: