cddl 0.3.3 → 0.4.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: 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