cddl 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. checksums.yaml +4 -4
  2. data/bin/cddl +9 -1
  3. data/cddl.gemspec +1 -1
  4. data/lib/cddl.rb +50 -26
  5. data/test/test-cddl.rb +76 -24
  6. metadata +3 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 14938c337d552f720d587e2b46be2c4738e48f8b
4
- data.tar.gz: 9a2b6a95471d6d29b6acd051d3c838d30f1724c0
3
+ metadata.gz: ae990c0c1e630a5f206d115bc5ae8cbc2e5612cd
4
+ data.tar.gz: 7ff78e8928e1cd3e7f60fa1086e6b055b23e39d7
5
5
  SHA512:
6
- metadata.gz: 557ce79dad209f8577c361effcb3aea96ee43be2b4dba7914fa34fdb9f7bca9d5e5adfe079dcdadce42062f07f1eb55c2e825ec1c30833f9d23d5ffb118ecaf1
7
- data.tar.gz: a1d8f53c4baf9d5c50c65a7daf3a91d40a1c5c43616978f3fedcb0c84493012906335712003c90b73d04b0f2800d9e89d081200036e5506f99b20db8a95b23d6
6
+ metadata.gz: 25cb1b61914141616819edfbcfa2a7de955295a1c1863f22ed6af85700f5cc1fa9897c6cbf51a9bcd65814f927f026e389fd80c916713e07a195a2b42dbb5136
7
+ data.tar.gz: 042f0f7497d609872bfce8b95da45d98a273a06092c67d2816704618497067910add06f4bf88abfa7d066cc90dff30f19ead71f43dc2ddcceb10e61b57866a23
data/bin/cddl CHANGED
@@ -15,8 +15,16 @@ def usage
15
15
  exit 1
16
16
  end
17
17
 
18
+ def read_arg(arg)
19
+ if arg == "-"
20
+ STDIN.read
21
+ else
22
+ File.read(arg)
23
+ end
24
+ end
25
+
18
26
  def parser
19
- @parser ||= CDDL::Parser.new(File.read(ARGV[0]))
27
+ @parser ||= CDDL::Parser.new(read_arg(ARGV[0]))
20
28
  end
21
29
 
22
30
  case ARGV[1]
@@ -1,6 +1,6 @@
1
1
  spec = Gem::Specification.new do |s|
2
2
  s.name = 'cddl'
3
- s.version = '0.1.4'
3
+ s.version = '0.1.5'
4
4
  s.summary = "CDDL generator and validator."
5
5
  s.description = %{A parser, generator, and validator for CDDL}
6
6
  s.add_dependency('cbor-diag')
@@ -10,6 +10,8 @@ module CDDL
10
10
  PRELUDE = File.read("#{DATA_DIR}/prelude.cddl")
11
11
  ABNF_SPEC = File.read("#{DATA_DIR}/cddl.abnf")
12
12
 
13
+ MANY = Float::INFINITY
14
+
13
15
  class Parser
14
16
  def initialize(source_text)
15
17
  @abnf = Peggy::ABNF.new
@@ -27,6 +29,8 @@ module CDDL
27
29
  end
28
30
  puts @abnf.ast? if $debug_ast
29
31
  @ast = @abnf.ast?
32
+ # our little argument stack for rule processing
33
+ @insides = []
30
34
  end
31
35
 
32
36
  def apr # for debugging
@@ -72,12 +76,11 @@ module CDDL
72
76
  generate(where[rand(where.size-1)+1])
73
77
  when :map
74
78
  Hash[where[1..-1].flat_map {|m| generate(m, true)}]
75
- when :array
79
+ when :array, :grpent
76
80
  where[1..-1].flat_map {|m| generate(m).map{|e| e[1]}}
77
81
  when :member
78
82
  s = where[1]
79
- e = where[2]
80
- e = 4 if e == -1
83
+ e = [where[2], [s, 4].max].min # truncate to 4 unless must be more
81
84
  s += rand(e + 1 - s) if e != s
82
85
  kr = where[3]
83
86
  vr = where[4]
@@ -164,6 +167,36 @@ module CDDL
164
167
  )
165
168
  end
166
169
 
170
+ def validate_forward(d, start, where)
171
+ i = 0
172
+ where[1..-1].each { |r|
173
+ t, s, e, _k, v = r # XXX
174
+ fail unless t == :member
175
+ occ = 0
176
+ while ((occ < e) && i != d.size && (n = validate_linear(d, start+i, v)))
177
+ i += n
178
+ occ += 1
179
+ end
180
+ if occ < s
181
+ @last_message = "occur not reached in array #{d} for #{where}"
182
+ return false
183
+ end
184
+ }
185
+ i
186
+ end
187
+
188
+ # returns number of matches or false for breakage
189
+ def validate_linear(d, start, where)
190
+ fail unless Array === d
191
+ case where[0]
192
+ when :grpent
193
+ # must be inside an array with nested occurrences
194
+ validate_forward(d, start, where)
195
+ else
196
+ validate1(d[start], where) ? 1 : false
197
+ end
198
+ end
199
+
167
200
  def validate1(d, where=rules)
168
201
  # puts "DATA: #{d.inspect}"
169
202
  # puts "RULE: #{where.inspect}"
@@ -205,21 +238,7 @@ module CDDL
205
238
  when :array
206
239
  if Array === d
207
240
  # validate1 against the record
208
- # XXX do that in some recursive descent fashion
209
- i = 0
210
- where[1..-1].each { |r|
211
- t, s, e, _k, v = r # XXX
212
- fail unless t == :member
213
- occ = 0
214
- while ((e == -1 || occ < e) && i != d.size && validate1(d[i], v))
215
- i += 1
216
- occ += 1
217
- end
218
- if occ < s
219
- @last_message = "occur not reached in array #{d} for #{where}"
220
- return false
221
- end
222
- }
241
+ i = validate_forward(d, 0, where)
223
242
  validate_result(i == d.size) { "cannot complete array #{d} for #{where}" }
224
243
  end
225
244
  when :string, :int, :float
@@ -310,25 +329,27 @@ module CDDL
310
329
  else
311
330
  type1(n.type1, true) # type1 can be a group here!
312
331
  end
313
- if t[0] == :grpent
332
+ if t[0] == :grpent && (@insides.last == :map || occ == [1, 1])
314
333
  # go through the members here and multiply the occs
315
- # XXX only do this for maps. Keep the structure up for the arrays!
316
334
  t1 = t[1..-1].flatten(1)
317
335
  t1.flat_map {|t2|
318
336
  if t2[0] == :member
319
337
  [t2]
320
338
  else
321
- fail unless t2[0] == :grpent
339
+ fail unless t2[0] == :grpent # XXX Where is the nested multiplication here?
322
340
  t2[1..-1]
323
341
  end
324
342
  }.map {|mem|
325
343
  # p mem
326
344
  mem[1] *= occ[0]
327
- mem[2] *= [occ[1], -1].max
345
+ mem[2] *= occ[1] # Does all the infinity magic
328
346
  # p mem
329
347
  mem
330
348
  }
331
349
  else
350
+ if t[0] == :grpent
351
+ t = [t[0], *t[1..-1].flatten(1)]
352
+ end
332
353
  [[:member, *occ, nil, t]]
333
354
  end
334
355
  end
@@ -407,15 +428,18 @@ module CDDL
407
428
  when /\A\(/
408
429
  type(n.type)
409
430
  when /\A[\[{]/
410
- s = n.children(:group).flat_map {|ch| group(ch)}
411
431
  type = BRACE[str[0]]
432
+ @insides << type
433
+ s = n.children(:group).flat_map {|ch| group(ch)}
434
+ @insides.pop
412
435
  if type == :map
413
436
  s.each do |member|
414
437
  fail unless member[0] == :member
415
438
  fail "map entry without member key given: #{member}" unless member[3]
416
439
  end
417
- # XXX do the occurrence multiplier here
440
+ # XXX could do the occurrence multiplier here
418
441
  end
442
+ # warn s.inspect
419
443
  [type, *s]
420
444
  else
421
445
  "unimplemented #{n}"
@@ -441,7 +465,7 @@ module CDDL
441
465
  when ""
442
466
  [1, 1]
443
467
  when "+"
444
- [1, -1]
468
+ [1, MANY]
445
469
  when "?"
446
470
  [0, 1]
447
471
  when /\A(\d*)\*(\d*)\z/
@@ -451,7 +475,7 @@ module CDDL
451
475
  s = s.to_i
452
476
  end
453
477
  if (e = $2) == ""
454
- e = -1
478
+ e = MANY
455
479
  else
456
480
  e = e.to_i
457
481
  end
@@ -21,7 +21,7 @@ class TestABNF < Test::Unit::TestCase
21
21
  [:array,
22
22
  [:member,
23
23
  0,
24
- -1,
24
+ CDDL::MANY,
25
25
  nil,
26
26
  [:map,
27
27
  [:member, 1, 1, [:string, "rater"], [:prim, 3]],
@@ -33,7 +33,7 @@ class TestABNF < Test::Unit::TestCase
33
33
  [:member, 0, 1, [:string, "sample-size"], [:prim, 0]],
34
34
  [:member, 0, 1, [:string, "generated"], [:prim, 0]],
35
35
  [:member, 0, 1, [:string, "expires"], [:prim, 0]],
36
- [:member, 0, -1, [:type1, [:prim]], [:prim]]]]]]]]
36
+ [:member, 0, CDDL::MANY, [:type1, [:prim]], [:prim]]]]]]]]
37
37
 
38
38
  def test_aa_rfc7071_concise
39
39
  parser1 = CDDL::Parser.new(File.read("#{TEST_DATA_DIR}/7071-concise.cddl"))
@@ -56,7 +56,6 @@ HERE
56
56
  assert_equal [0x4711, 0b1011001110001111000], parser.generate
57
57
  end
58
58
 
59
-
60
59
  def test_validate_person_occurs
61
60
  person = <<HERE
62
61
  person = (
@@ -67,19 +66,25 @@ HERE
67
66
  parser1 = CDDL::Parser.new "unlimitedpersons = [* person ]" + person
68
67
  parser2 = CDDL::Parser.new "oneortwoPerson = [1*2 person ]" + person
69
68
  parser3 = CDDL::Parser.new "min2Person = [2* person ]" + person
70
-
69
+
71
70
  assert parser1.validate([])
72
71
  refute parser2.validate([], false)
73
72
  refute parser3.validate([], false)
74
73
  assert parser1.validate(["Methuselah", 969])
75
74
  assert parser2.validate(["Methuselah", 969])
76
75
  refute parser3.validate(["Methuselah", 969], false)
77
- assert parser1.validate(["Methuselah", "Methuselah", 969, 969]) # XXX Sequence
78
- assert parser2.validate(["Methuselah", "Methuselah", 969, 969])
79
- assert parser3.validate(["Methuselah", "Methuselah", 969, 969])
80
- assert parser1.validate(["Methuselah", "Methuselah", "Methuselah", 969, 969]) # XXX Sequence
76
+ assert parser1.validate(["Methuselah", 969, "Methuselah", 969])
77
+ assert parser2.validate(["Methuselah", 969, "Methuselah", 969])
78
+ assert parser3.validate(["Methuselah", 969, "Methuselah", 969])
79
+ assert parser1.validate(["Methuselah", 969, "Methuselah", 969, "Methuselah", 969])
80
+ refute parser2.validate(["Methuselah", 969, "Methuselah", 969, "Methuselah", 969], false)
81
+ assert parser3.validate(["Methuselah", 969, "Methuselah", 969, "Methuselah", 969])
82
+ refute parser1.validate(["Methuselah", "Methuselah", 969, 969], false)
83
+ refute parser2.validate(["Methuselah", "Methuselah", 969, 969], false)
84
+ refute parser3.validate(["Methuselah", "Methuselah", 969, 969], false)
85
+ refute parser1.validate(["Methuselah", "Methuselah", "Methuselah", 969, 969], false)
81
86
  refute parser2.validate(["Methuselah", "Methuselah", "Methuselah", 969, 969], false)
82
- assert parser3.validate(["Methuselah", "Methuselah", "Methuselah", 969, 969])
87
+ refute parser3.validate(["Methuselah", "Methuselah", "Methuselah", 969, 969], false)
83
88
  end
84
89
 
85
90
  def test_validate
@@ -215,9 +220,9 @@ HERE
215
220
  # pp parser.apr
216
221
  assert parser.validate([])
217
222
  assert parser.validate([1, 2])
218
- assert parser.validate([1, 1, 2, 2]) # XXX: This is probably a BUG
219
- refute parser.validate([1, 2, 1, 2], false) # XXX->assert: major surgery required
220
- assert parser.validate([1]) # XXX -> refute (rules left)
223
+ assert parser.validate([1, 2, 1, 2])
224
+ refute parser.validate([1, 1, 2, 2], false)
225
+ refute parser.validate([1], false)
221
226
  refute parser.validate([1, 2, 1], false)
222
227
  end
223
228
 
@@ -251,7 +256,7 @@ HERE
251
256
  # puts "APR:"
252
257
  # pp parser.apr
253
258
  assert parser.validate([])
254
- assert parser.validate([1])
259
+ refute parser.validate([1], false)
255
260
  assert parser.validate([1, 2])
256
261
  refute parser.validate([2, 1], false)
257
262
  refute parser.validate([1, 1, 2, 2], false)
@@ -273,8 +278,8 @@ HERE
273
278
  refute parser.validate([1], false)
274
279
  assert parser.validate([1, 2])
275
280
  refute parser.validate([2, 1], false)
276
- assert parser.validate([1, 1, 2, 2]) # XXX not sequence preserving
277
- refute parser.validate([1, 2, 1, 2], false)
281
+ refute parser.validate([1, 1, 2, 2], false)
282
+ assert parser.validate([1, 2, 1, 2])
278
283
  refute parser.validate([1, 2, 1], false)
279
284
  end
280
285
 
@@ -289,15 +294,15 @@ HERE
289
294
  # puts "APR:"
290
295
  # pp parser.apr
291
296
  assert parser.validate([])
292
- assert parser.validate([1])
297
+ refute parser.validate([1], false)
293
298
  assert parser.validate([1, 2])
294
299
  refute parser.validate([2, 1], false)
295
- assert parser.validate([1, 1, 2, 2]) # XXX not sequence preserving
296
- refute parser.validate([1, 2, 1, 2], false)
300
+ refute parser.validate([1, 1, 2, 2], false)
301
+ assert parser.validate([1, 2, 1, 2])
297
302
  refute parser.validate([1, 2, 1], false)
298
303
  end
299
304
 
300
-
305
+
301
306
  def test_validate_occur23 # XXX need indirection for now
302
307
  # $debug_ast = true
303
308
  parser = CDDL::Parser.new <<HERE
@@ -313,11 +318,35 @@ HERE
313
318
  refute parser.validate([1], false)
314
319
  refute parser.validate([1, 2], false)
315
320
  refute parser.validate([2, 1], false)
316
- assert parser.validate([1, 1, 2, 2]) # XXX not sequence preserving
317
- assert parser.validate([1, 1, 1, 2, 2]) # XXX not sequence preserving
318
- assert parser.validate([1, 1, 2, 2, 2]) # XXX not sequence preserving
319
- assert parser.validate([1, 1, 1, 2, 2, 2]) # XXX not sequence preserving
320
- refute parser.validate([1, 2, 1, 2], false)
321
+ assert parser.validate([1, 2, 1, 2])
322
+ assert parser.validate([1, 2, 1, 2, 1, 2])
323
+ refute parser.validate([1, 2, 1, 2, 1, 2, 1, 2], false)
324
+ refute parser.validate([1, 1, 2, 2, 2], false)
325
+ refute parser.validate([1, 1, 1, 2, 2, 2], false)
326
+ refute parser.validate([1, 2, 1], false)
327
+ end
328
+
329
+
330
+ def test_validate_occur12plus1 # XXX need indirection for now
331
+ # $debug_ast = true
332
+ parser = CDDL::Parser.new <<HERE
333
+ test = [1*2 test1 1*1 test1]
334
+ test1 = (one: 1, two: 2)
335
+ HERE
336
+ # puts "RULES:"
337
+ # pp parser.rules
338
+ # puts "APR:"
339
+ # pp parser.apr
340
+ pp parser.generate
341
+ refute parser.validate([], false)
342
+ refute parser.validate([1], false)
343
+ refute parser.validate([1, 2], false)
344
+ refute parser.validate([2, 1], false)
345
+ refute parser.validate([1, 2, 1, 2], false) # !!! PEG semantics gets us here
346
+ assert parser.validate([1, 2, 1, 2, 1, 2])
347
+ refute parser.validate([1, 2, 1, 2, 1, 2, 1, 2], false)
348
+ refute parser.validate([1, 1, 2, 2, 2], false)
349
+ refute parser.validate([1, 1, 1, 2, 2, 2], false)
321
350
  refute parser.validate([1, 2, 1], false)
322
351
  end
323
352
 
@@ -363,5 +392,28 @@ HERE
363
392
  refute parser.validate(CBOR::Tagged.new(55799, CBOR::Tagged.new(999, [0, "barley", 1])), false)
364
393
  end
365
394
 
395
+ def test_nested_group_many1
396
+ parser = CDDL::Parser.new <<HERE
397
+ foo = {* bar}
398
+ bar = (* b: 1)
399
+ HERE
400
+ assert_equal [:type1, [:map, [:member, 0, CDDL::MANY, [:string, "b"], [:int, 1]]]], parser.rules
401
+ end
402
+
403
+ def test_nested_group_many2
404
+ parser = CDDL::Parser.new <<HERE
405
+ foo = {* bar}
406
+ bar = (b: 1)
407
+ HERE
408
+ assert_equal [:type1, [:map, [:member, 0, CDDL::MANY, [:string, "b"], [:int, 1]]]], parser.rules
409
+ end
410
+
411
+ def test_nested_group_many3
412
+ parser = CDDL::Parser.new <<HERE
413
+ foo = {* bar}
414
+ bar = (4*6 b: 1)
415
+ HERE
416
+ assert_equal [:type1, [:map, [:member, 0, CDDL::MANY, [:string, "b"], [:int, 1]]]], parser.rules
417
+ end
366
418
 
367
419
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cddl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carsten Bormann
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-02 00:00:00.000000000 Z
11
+ date: 2015-03-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cbor-diag
@@ -92,9 +92,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
92
92
  version: '0'
93
93
  requirements: []
94
94
  rubyforge_project:
95
- rubygems_version: 2.4.5
95
+ rubygems_version: 2.4.6
96
96
  signing_key:
97
97
  specification_version: 4
98
98
  summary: CDDL generator and validator.
99
99
  test_files: []
100
- has_rdoc: