cddl 0.3.3 → 0.4.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c679a7c46cf375f7ebefc86fb2846f4c482fb67e
4
- data.tar.gz: b1b1b2968c8ba46bf573074827fb818311946334
3
+ metadata.gz: 167e4f338b7d73dd31d38e050c736fe9d8041984
4
+ data.tar.gz: 62c373480ad582423abcf9c5475371a11f08425b
5
5
  SHA512:
6
- metadata.gz: cff8854de5230152b6cb7223bb9078657c4296b359d244a15a5f34e3910296d0da1dead8a06c8a207d359780542cb690a1951034935d76117c7eb95b4c0b311a
7
- data.tar.gz: 339c503e65b5159d14b5fd130528b8c93da567716a746d274558fb353cf72573c205bf535fc7d64b2cc3313ad1dd9ea62b422fea07876b76991f0e4ac5644c3f
6
+ metadata.gz: 6f26f2048e7a77f12175e23430bf1a0c5271deaa4e0d499683f1d25785aec4765b70966af4b7c155469f68a2db7cb9540658909da1764b6f3a221eed4dcfb92d
7
+ data.tar.gz: 7e922d96378421546a660cfda5c1dc3ff54efa5ee218767323e1015570f875e829c196e5a90e4115be42c504c9c7d2f51d73b5a8d05f7e14f7d5946886b97cce
data/cddl.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  spec = Gem::Specification.new do |s|
2
2
  s.name = 'cddl'
3
- s.version = '0.3.3'
3
+ s.version = '0.4.0'
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')
data/data/cddl.abnf CHANGED
@@ -1,10 +1,13 @@
1
1
  cddl = S 1*rule
2
- rule = typename S "=" S type S
3
- / groupname S "=" S group S
2
+ rule = typename [genericparm] S "=" S type S
3
+ / groupname [genericparm] S "=" S group S
4
4
 
5
5
  typename = id
6
6
  groupname = id
7
7
 
8
+ genericparm = "<" S id S *("," S id S ) ">"
9
+ genericarg = "<" S type1 S *("," S type1 S ) ">"
10
+
8
11
  type = type1 S *("/" S type1 S)
9
12
 
10
13
  type1 = type2 [S (rangeop / annotator) S type2]
@@ -14,10 +17,10 @@ type1 = type2 [S (rangeop / annotator) S type2]
14
17
  / "{" S group S "}"
15
18
  / "[" S group S "]"
16
19
  / "&" S "(" S group S ")"
17
- / "&" S groupname
20
+ / "&" S groupname [genericarg]
18
21
 
19
22
  type2 = value
20
- / typename
23
+ / typename [genericarg]
21
24
  / "(" type ")"
22
25
 
23
26
  rangeop = "..." / ".."
@@ -28,7 +31,7 @@ group = "(" S *grpent S ")"
28
31
  / *grpent
29
32
 
30
33
  grpent = [occur S] [memberkey S] type1 optcom
31
- / [occur S] groupname optcom ; always preempted by previous...
34
+ / [occur S] groupname [genericarg] optcom ; always preempted by previous...
32
35
 
33
36
  memberkey = type1 S "=>"
34
37
  / bareword S ":"
data/lib/cddl.rb CHANGED
@@ -63,6 +63,8 @@ module CDDL
63
63
 
64
64
  def rules
65
65
  @rules = {}
66
+ @generics = {}
67
+ @bindings = [{}]
66
68
  ast.each :rule do |rule|
67
69
  rule_ast =
68
70
  if rulename = rule.groupname
@@ -73,19 +75,28 @@ module CDDL
73
75
  fail "Huh?"
74
76
  end
75
77
  n = rulename.to_s
76
- if @rules[n]
77
- a = strip_nodes(rule_ast).inspect
78
- b = strip_nodes(@rules[n]).inspect
79
- if a == b
80
- warn "*** Warning: Identical redefinition of #{n} as #{a}"
81
- else
82
- fail "Duplicate rule definition #{n} as #{b} (was #{a})"
78
+ if g = rule.genericparm
79
+ ids = g.children(:id).map(&:to_s)
80
+ # puts ["ids", ids].inspect
81
+ if b = @generics[n]
82
+ fail "Duplicate generics definition #{n} as #{rule_ast} (was #{b})"
83
+ end
84
+ @generics[n] = [rule_ast, ids]
85
+ else
86
+ if @rules[n]
87
+ a = strip_nodes(rule_ast).inspect
88
+ b = strip_nodes(@rules[n]).inspect
89
+ if a == b
90
+ warn "*** Warning: Identical redefinition of #{n} as #{a}"
91
+ else
92
+ fail "Duplicate rule definition #{n} as #{b} (was #{a})"
93
+ end
83
94
  end
95
+ @rules[n] = rule_ast
84
96
  end
85
- @rules[n] = rule_ast
86
97
  end
87
- # pp @rules
88
- @rootrule = @rules.keys.first
98
+ # pp @generics
99
+ @rootrule = @rules.keys.first # DRAFT: generics are ignored here.
89
100
  # now process the rules...
90
101
  @stage1 = {}
91
102
  result = r_process(@rootrule, @rules[@rootrule])
@@ -428,12 +439,28 @@ module CDDL
428
439
  w
429
440
  end
430
441
 
431
- # XXX needs serious memoizing
442
+ def rule_lookup(name, canbegroup)
443
+ if b = @bindings.last[name]
444
+ b
445
+ else
446
+ r = @rules[name]
447
+ if r
448
+ t = r_process(name, r)
449
+ unless t[0] == :type1
450
+ fail "#{name} not a type #{t}" unless canbegroup && t[0] == :grpent
451
+ end
452
+ t
453
+ end
454
+ end
455
+ end
432
456
 
433
- def r_process(n, r)
457
+ def r_process(n, r, bindings = {})
458
+ @bindings.push(bindings)
434
459
  t = r[0]
435
460
  # puts "Processing rule #{n} = #{t}"
436
- @stage1[n] ||= [t, *r[1..-1].map {|e| send(t, e)}]
461
+ r = @stage1[n] ||= [t, *r[1..-1].map {|e| send(t, e)}]
462
+ @bindings.pop
463
+ r
437
464
  end
438
465
 
439
466
  def value(n)
@@ -482,7 +509,6 @@ module CDDL
482
509
  t2[1..-1]
483
510
  end
484
511
  }.map {|mem|
485
- # p mem
486
512
  mem[1] *= occ[0]
487
513
  mem[2] *= occ[1] # Does all the infinity magic
488
514
  # p mem
@@ -497,35 +523,32 @@ module CDDL
497
523
  end
498
524
  end
499
525
 
500
- def label(n)
501
- # if this is not a rulename, it's a bareword
502
- if n.bareword
503
- name = n.to_s
504
- if r = @rules[name]
505
- r_process(name, r)
506
- else
507
- [:string, name]
508
- end
509
- else
510
- type1(n.type1)
511
- end
526
+ def g_process(name, g, genericargs)
527
+ r, ids = g
528
+ args = genericargs.children(:type1).map {|x| type1(x, true)}
529
+ fail "number of args #{name} #{ids.size} #{args.size}" if ids.size != args.size
530
+ bindings = Hash[ids.zip(args)]
531
+ r_process("#{name}<#{genericargs._strip}>", r, bindings)
512
532
  end
513
533
 
514
- def type_recall(name, canbegroup)
515
- if r = @rules[name]
516
- t = r_process(name, r)
517
- unless t[0] == :type1
518
- fail "#{name} not a type" unless canbegroup && t[0] == :grpent
519
- end
534
+ def type_recall(name, canbegroup, genericargs)
535
+ # p genericargs, "GENERIC"
536
+ if genericargs && (generic = @generics[name])
537
+ t = g_process(name, generic, genericargs)
538
+ t
539
+ elsif !genericargs && (t = rule_lookup(name, canbegroup))
520
540
  t
521
541
  else
522
- fail "Unknown type #{name}"
542
+ fail "Unknown type #{name} #{genericargs.inspect} #{@bindings} #{@abnf.ast?}"
523
543
  end
524
544
  end
525
545
 
526
- def group_recall(name)
527
- if r = @rules[name]
528
- g = r_process(name, r)
546
+ def group_recall(name, genericargs)
547
+ if genericargs && (generic = @generics[name])
548
+ g = g_process(name, generic, genericargs)
549
+ fail "#{name} not a group" unless g[0] == :grpent
550
+ g[1..-1]
551
+ elsif !genericargs && (g = rule_lookup(name, true))
529
552
  fail "#{name} not a group" unless g[0] == :grpent
530
553
  g[1..-1]
531
554
  else
@@ -539,7 +562,8 @@ module CDDL
539
562
  elsif v = n.value
540
563
  value(n)
541
564
  elsif v = n.typename
542
- t = type_recall(v.to_s, canbegroup)
565
+ ga = n.genericarg || (n.s && n.s.genericarg) # workaround
566
+ t = type_recall(v.to_s, canbegroup, ga)
543
567
  if t[0] == :type1
544
568
  if t.size == 2
545
569
  t = t[1]
@@ -614,7 +638,7 @@ module CDDL
614
638
  [type, *s]
615
639
  when /\A&/
616
640
  if gn = n.groupname
617
- s = group_recall(gn.to_s).flatten(1)
641
+ s = group_recall(gn.to_s, n.genericarg).flatten(1)
618
642
  else
619
643
  @insides << :enum
620
644
  s = n.children(:group).flat_map {|ch| group(ch)}
data/test/test-cddl.rb CHANGED
@@ -373,7 +373,7 @@ HERE
373
373
  assert_equal "foo", parser.generate
374
374
  end
375
375
 
376
-
376
+
377
377
  def test_validate_number_key
378
378
  parser = CDDL::Parser.new <<HERE
379
379
  test = [test1, test2, test3]
@@ -718,4 +718,97 @@ HERE
718
718
  pp parser1.generate
719
719
  end
720
720
 
721
+
722
+ def test_generic1
723
+ parser = CDDL::Parser.new <<HERE
724
+ d = a<1>
725
+ a<b> = b
726
+ HERE
727
+ assert_equal 1, parser.generate
728
+ end
729
+
730
+ def test_generic_group
731
+ parser = CDDL::Parser.new <<HERE
732
+ d = a<mygr>
733
+ a<gr> = { gr }
734
+ mygr = (
735
+ 1 => 2
736
+ )
737
+ HERE
738
+ assert_equal({1 => 2}, parser.generate)
739
+ end
740
+
741
+ def test_generic_transitive
742
+ parser = CDDL::Parser.new <<HERE
743
+ d = a<mygr>
744
+ a<gr> = { b<gr> }
745
+ b<foo> = foo
746
+ mygr = (
747
+ 1 => 2
748
+ )
749
+ HERE
750
+ assert_equal({1 => 2}, parser.generate)
751
+ end
752
+
753
+ def test_generic_realistic
754
+ parser = CDDL::Parser.new <<HERE
755
+ start = [request, response]
756
+ request = message<0>
757
+ response = message<1>
758
+ message<code> = {
759
+ code: code
760
+ data: "hallo data"
761
+ }
762
+ HERE
763
+ assert_equal([{"code"=>0, "data"=>"hallo data"},
764
+ {"code"=>1, "data"=>"hallo data"}], parser.generate)
765
+ end
766
+
767
+ def test_generic_enum
768
+ parser = CDDL::Parser.new <<HERE
769
+ color<foo> = &foo
770
+ color = color<colors>
771
+ basecolors = (
772
+ red: 1,
773
+ green: 2,
774
+ blue: 4,
775
+ lila,
776
+ )
777
+ lila = (
778
+ magenta: 5,
779
+ pink: 9,
780
+ purple: 10,
781
+ )
782
+ colors = (
783
+ black: 0,
784
+ basecolors,
785
+ yellow: 3,
786
+ cyan: 6,
787
+ white: 7,
788
+ orange: 8,
789
+ brown: 11,
790
+ grey: 12,
791
+ )
792
+ HERE
793
+ # brittle on type1 nesting optimization
794
+ assert_equal [:type1,
795
+ [:type1,
796
+ [:int, 0],
797
+ [:int, 1],
798
+ [:int, 2],
799
+ [:int, 4],
800
+ [:int, 5],
801
+ [:int, 9],
802
+ [:int, 10],
803
+ [:int, 3],
804
+ [:int, 6],
805
+ [:int, 7],
806
+ [:int, 8],
807
+ [:int, 11],
808
+ [:int, 12]]], parser.rules
809
+ 10.times {
810
+ assert parser.generate.between?(0, 12)
811
+ }
812
+ end
813
+
721
814
  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.3.3
4
+ version: 0.4.0
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-10 00:00:00.000000000 Z
11
+ date: 2015-03-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cbor-diag