cddlc 0.1.0 → 0.1.2

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.
data/lib/cddlc.rb CHANGED
@@ -3,6 +3,14 @@ require_relative "parser/cddl-util.rb"
3
3
  class CDDL
4
4
  @@parser = CDDLGRAMMARParser.new
5
5
 
6
+ DATA_DIR = Pathname.new(__FILE__) + "../../data/"
7
+ # empty string is for CDDL::DATA_DIR
8
+ CDDL_INCLUDE_PATH = ENV["CDDL_INCLUDE_PATH"] || ".:"
9
+
10
+ def self.cddl_include_path
11
+ CDDL_INCLUDE_PATH.split(":", -1).map {_1 == "" ? CDDL::DATA_DIR : Pathname.new(_1)}
12
+ end
13
+
6
14
  def self.reason(parser, s)
7
15
  reason = [parser.failure_reason]
8
16
  parser.failure_reason =~ /^(Expected .+) after/m
@@ -14,21 +22,105 @@ class CDDL
14
22
  reason.join("\n")
15
23
  end
16
24
 
25
+ SAFE_FN = /\A[-._a-zA-Z0-9]+\z/
26
+
17
27
  def self.from_cddl(s)
18
28
  ast = @@parser.parse s
19
29
  if !ast
20
30
  fail self.reason(@@parser, s)
21
31
  end
22
- CDDL.new(ast)
32
+ if $options.cddl2
33
+ directives = s.lines.grep(/^;# /).map(&:chomp).map{|l| l.sub(/^;#\s+/, '').split(/\s+/)}
34
+ # puts directives.to_yaml
35
+ end
36
+ ret = CDDL.new(ast, directives)
37
+
38
+ if $options.cddl2
39
+ ret.directives.each do |di|
40
+ preferred_tag = nil
41
+ case di
42
+ in ["include" => dir, docref]
43
+ in ["include" => dir, docref, "as", preferred_tag]
44
+ warn "** Ignoring namespace tag #{preferred_tag} for now"
45
+ in ["import" => dir, docref]
46
+ else
47
+ warn "** Can't parse include directive #{di.inspect}"
48
+ next
49
+ end
50
+ unless docref =~ SAFE_FN
51
+ warn "** skipping unsafe filename #{docref}"
52
+ next
53
+ end
54
+ puts "PREFERRED_TAG #{preferred_tag}" if $options.verbose
55
+ puts "DOCREF #{docref}" if $options.verbose
56
+ fn = docref.downcase << ".cddl"
57
+
58
+ io = nil
59
+ CDDL::cddl_include_path.each do |path|
60
+ begin
61
+ io = (path + fn).open
62
+ break
63
+ rescue Errno::ENOENT
64
+ next
65
+ end
66
+ end
67
+ unless io
68
+ warn "** include file #{fn} not found in #{CDDL::cddl_include_path.map(&:to_s)}"
69
+ next
70
+ end
71
+
72
+ include_file = io.read
73
+ included_cddl = CDDL.from_cddl(include_file)
74
+ # XXX: Should namespace that thing now! all names -> preferred_tag.name
75
+ # p included_cddl.rules.keys
76
+ # XXX: do once, first, to rename COSE_Key to RFC9052.COSE_Key
77
+ case dir
78
+ in "import"
79
+ warn "** IMPORTING #{fn}" if $options.verbose
80
+ require_relative '../lib/processor/cddl-undefined.rb'
81
+ loop do
82
+ undef_rule = ret.cddl_undefined # XXX square...
83
+ # p undef_rule
84
+ got_more = false
85
+ undef_rule.each do |name|
86
+ if rule = included_cddl.rules[name]
87
+ ret.rules[name] = rule # XXX must be namespaced!
88
+ warn "IMPORTED #{name} from #{fn}" if $options.verbose # ...: #{rule}...
89
+ got_more = true
90
+ end
91
+ end
92
+ break unless got_more
93
+ end
94
+ in "include"
95
+ warn "** INCLUDING #{fn}" if $options.verbose
96
+ included_cddl.rules.each do |k, v|
97
+ if old = ret.rules[k]
98
+ if old != v
99
+ warn "** included rule #{k} = #{v} would overwrite #{old}"
100
+ end
101
+ else
102
+ ret.rules[k] = v
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
108
+ ret
23
109
  end
24
110
 
25
- attr_accessor :ast, :tree
26
- def initialize(ast_)
111
+ attr_accessor :ast, :tree, :directives
112
+ def initialize(ast_, directives_ = [])
27
113
  @ast = ast_
28
114
  @tree = ast.ast
29
115
  @rules = nil # only fill in if needed
116
+ @directives = directives_
117
+ end
118
+
119
+ def deep_clone
120
+ Marshal.load(Marshal.dump(self))
30
121
  end
31
122
 
123
+
32
124
  RULE_OP_TO_CHOICE = {"/=" => "tcho", "//=" => "gcho"}
33
125
 
34
126
  def rules
@@ -45,7 +137,20 @@ class CDDL
45
137
  fail unless name.size == 2
46
138
  name = name[1]
47
139
  when "gen"
48
- name = name[1..-1]
140
+ require_relative "processor/cddl-visitor.rb"
141
+ parmnames = name[2..-1]
142
+ name = name[1] # XXX update val with parm/arg
143
+ val = ["parm", parmnames,
144
+ visit(val) do |p|
145
+ case p
146
+ in ["name", nm]
147
+ if ix = parmnames.index(nm)
148
+ [true, ["arg", ix]]
149
+ end
150
+ else
151
+ false
152
+ end
153
+ end]
49
154
  else
50
155
  fail name
51
156
  end
@@ -68,7 +173,8 @@ class CDDL
68
173
 
69
174
  def prelude
70
175
  if @prelude.nil?
71
- @prelude = CDDL.from_cddl(File.read(Pathname.new(__FILE__) + "../../data/prelude.cddl"))
176
+ @prelude = CDDL.from_cddl(File.read(DATA_DIR + "prelude.cddl"))
177
+
72
178
  end
73
179
  @prelude
74
180
  end
@@ -1,4 +1,4 @@
1
-
1
+ require 'treetop'
2
2
  require_relative './cddlgrammar'
3
3
 
4
4
  class Treetop::Runtime::SyntaxNode
@@ -2,14 +2,13 @@ require_relative "../cddlc.rb"
2
2
  require_relative "./cddl-visitor.rb"
3
3
 
4
4
  class CDDL
5
- def substitute(prod, parms, args, &block)
6
- subs = Hash[parms.zip(args)]
5
+ def substitute(prod, parms, subs, &block)
7
6
  visit(prod) do |p, &block1|
8
7
  case p
9
- in ["gen", name, *gen_args]
8
+ in ["gen", name, *gen_args] # XXX
10
9
  [true, gen_apply(name, gen_args, &block1)]
11
- in ["name", name]
12
- if replacement = subs[name]
10
+ in ["arg", num]
11
+ if replacement = subs[num]
13
12
  [true, visit(expand_prod(replacement), &block)]
14
13
  end
15
14
  else
@@ -35,15 +34,19 @@ class CDDL
35
34
  def expand_generics
36
35
  @gen = {}
37
36
  rules.each do |name, prod|
38
- if Array === name
39
- @gen[name[0]] = [name[1..-1], prod]
37
+ case prod
38
+ in ["parm", parmnames, type]
39
+ if prod[0] == "parm"
40
+ @gen[name] = [parmnames, type]
41
+ end
42
+ else
40
43
  end
41
44
  end
42
45
  p @gen if $options.verbose
43
46
  @gen.each do |k, v|
44
- namep = v[0]
45
- fail unless rules[[k, *namep]] == v[1]
46
- rules.delete([k, *namep])
47
+ parmnames = v[0]
48
+ fail unless rules[k] == ["parm", parmnames, v[1]]
49
+ rules.delete(k)
47
50
  end
48
51
  @new_rules = {}
49
52
  rules.each do |name, prod|
@@ -0,0 +1,38 @@
1
+ require_relative "../cddlc.rb"
2
+ require_relative "./cddl-visitor.rb"
3
+ require_relative "./cddl-expander.rb"
4
+
5
+ class CDDL
6
+ def cddl_extract_names(prod, &name_used)
7
+ visit(prod) do |p|
8
+ case p
9
+ in ["gen", name, *_gen_args]
10
+ name_used.call(name)
11
+ false
12
+ in ["name", name]
13
+ name_used.call(name)
14
+ false
15
+ else
16
+ false
17
+ end
18
+ end
19
+ end
20
+
21
+ def cddl_add_used_by(prod, used)
22
+ cddl_extract_names(prod) do |name|
23
+ used[name] = true
24
+ end
25
+ end
26
+
27
+ def cddl_undefined
28
+ # currently only works on expanded...
29
+ cddl2 = self.deep_clone # needs deep-clone
30
+ cddl2.expand_generics
31
+ used = {}
32
+ cddl2.rules.each do |k, v|
33
+ fail unless String === k
34
+ cddl2.cddl_add_used_by(v, used)
35
+ end
36
+ used.keys.reject {|name| cddl2.rules[name] || prelude.rules[name]}
37
+ end
38
+ end
@@ -11,6 +11,8 @@ class CDDL
11
11
  end
12
12
 
13
13
  case prod
14
+ in ["parm", parmnames, prod]
15
+ ["parm", parmnames, visit(prod, &block)]
14
16
  in ["gen", name, *types]
15
17
  ["gen", name, *visit_all(types, &block)]
16
18
  in ["op", op, *prods]
@@ -2,11 +2,10 @@ require_relative "../cddlc.rb"
2
2
 
3
3
  class CDDL
4
4
 
5
- def write_lhs(k)
6
- case k
7
- in [id, *parms]
8
- "#{id}<#{parms.join(", ")}>"
9
- in String
5
+ def write_lhs(k, parmnames)
6
+ if parmnames
7
+ "#{k}<#{parmnames.join(", ")}>"
8
+ else
10
9
  k
11
10
  end
12
11
  end
@@ -26,35 +25,41 @@ class CDDL
26
25
  end
27
26
  end
28
27
 
29
- def write_rhs(v, targetprec = 0, indent = 0)
28
+ def write_rhs(v, targetprec = 0, indent = 0, pn = [])
29
+ # pn = parmnames
30
30
  # warn "** #{v.inspect}"
31
31
  indent_p = " " * indent
32
32
  indent += 1
33
33
  indent_s = " " * indent
34
34
  prec, ret =
35
35
  case v
36
+ in ["parm", parmnames, type]
37
+ [4, write_rhs(type, 2, indent, parmnames)]
38
+ in ["arg", Integer => num]
39
+ [4, pn[num] || "id$#{num}"]
36
40
  in ["name", id]
37
41
  [4, id]
38
42
  in ["gen", id, *parms] # oops -- namep vs. namea; ouch
39
- [4, "#{id}<#{parms.map{write_rhs(_1, 2, indent)}.join(", ")}>"]
43
+ [4, "#{id}<#{parms.map{write_rhs(_1, 2, indent, pn)}.join(", ")}>"]
40
44
  in ["tcho", *types]
41
- [2, types.map{write_rhs(_1, 3, indent)}.join(" / ")]
45
+ [2, types.map{write_rhs(_1, 3, indent, pn)}.join(" / ")]
42
46
  in ["gcho", *groups]
43
- [0, groups.map{write_rhs(_1, 2, indent)}.join(" // ")]
47
+ [0, groups.map{write_rhs(_1, 2, indent, pn)}.join(" // ")]
44
48
  in ["op", op, l, r]
45
- [3, "#{write_rhs(l, 3, indent)} #{op} #{write_rhs(r, 3, indent)}"]
49
+ [3, "#{write_rhs(l, 4, indent, pn)} #{op} #{write_rhs(r, 4, indent, pn)}"]
50
+ # 3->4: work around cddl tool limitation
46
51
  in ["map", group]
47
- [4, "{#{write_rhs(group, 0, indent)}}"]
52
+ [3, "{#{write_rhs(group, 0, indent, pn)}}"] # 4->3: work around cddl tool limitation
48
53
  in ["ary", group]
49
- [4, "[#{write_rhs(group, 0, indent)}]"]
54
+ [3, "[#{write_rhs(group, 0, indent, pn)}]"] # 4->3: work around cddl tool limitation
50
55
  in ["unwrap", namep]
51
- [4, "~#{write_rhs(namep, 4, indent)}"]
56
+ [4, "~#{write_rhs(namep, 4, indent, pn)}"]
52
57
  in ["enum", ["name", _name] => namep]
53
- [4, "&#{write_rhs(namep, 4, indent)}"]
58
+ [4, "&#{write_rhs(namep, 4, indent, pn)}"]
54
59
  in ["enum", ["gen", _name, *types] => namep]
55
- [4, "&#{write_rhs(namep, 4, indent)})"]
60
+ [4, "&#{write_rhs(namep, 4, indent, pn)})"]
56
61
  in ["enum", group]
57
- [4, "&(#{write_rhs(group, 0, indent)})"]
62
+ [4, "&(#{write_rhs(group, 0, indent, pn)})"]
58
63
  in ["prim"]
59
64
  [4, "#"]
60
65
  in ["prim", maj]
@@ -62,16 +67,16 @@ class CDDL
62
67
  in ["prim", maj, min]
63
68
  [4, "##{maj}.#{min}"]
64
69
  in ["prim", 6, Integer => tag, type]
65
- [4, "#6.#{tag}(#{write_rhs(type, 0, indent)})"]
70
+ [4, "#6.#{tag}(#{write_rhs(type, 0, indent, pn)})"]
66
71
  in ["prim", 6, nil, type]
67
- [4, "#6(#{write_rhs(type, 0, indent)})"]
72
+ [4, "#6(#{write_rhs(type, 0, indent, pn)})"]
68
73
  # prim: extension for #6.<i>(t)
69
74
  in ["seq", *groups]
70
75
  case groups.size
71
76
  when 0; [4, ""]
72
- # when 1; "#{write_rhs(g[0], targetprec, indent)}"
77
+ # when 1; "#{write_rhs(g[0], targetprec, indent, pn)}"
73
78
  else
74
- [1, "\n#{indent_p}#{groups.map{write_rhs(_1, 1, indent)}.join(",\n#{indent_p}")},\n"]
79
+ [1, "\n#{indent_p}#{groups.map{write_rhs(_1, 1, indent, pn)}.join(",\n#{indent_p}")},\n"]
75
80
  end
76
81
  in ["rep", s, e, group]
77
82
  occur = case [s, e]
@@ -82,13 +87,16 @@ class CDDL
82
87
  else
83
88
  "#{s}*#{e || ""}"
84
89
  end
85
- [1, "#{occur}#{write_rhs(group, 2, indent)}"]
90
+ [1, "#{occur}#{write_rhs(group, 2, indent, pn)}"]
86
91
  in ["mem", nil, t2]
87
- [2, write_rhs(t2, 2, indent)]
92
+ [2, write_rhs(t2, 2, indent, pn)]
88
93
  in ["mem", t1, t2]
89
- [2, "#{write_rhs(t1, 2, indent)} => #{write_rhs(t2, 2, indent)}"]
94
+ [2, "#{write_rhs(t1, 3, indent, pn)} => #{write_rhs(t2, 2, indent, pn)}"]
95
+ # 2->3: work around cddl tool limitation
96
+ in ["bytes", t]
97
+ [4, t] # XXX not very clean
90
98
  in ["text", t]
91
- [4, "\"#{t}\""] # XXX escape
99
+ [4, "\"#{t}\""] # XXX escape
92
100
  in ["number", t]
93
101
  [4, t.to_s]
94
102
  end
@@ -97,7 +105,12 @@ class CDDL
97
105
 
98
106
  def to_s
99
107
  rules.map {|k, v|
100
- "#{write_lhs(k)} = #{write_rhs(v, 2)}" # 2: parenthesize groups
108
+ parmnames = false
109
+ case v
110
+ in ["parm", parmnames, _type]
111
+ else
112
+ end
113
+ "#{write_lhs(k, parmnames)} = #{write_rhs(v, 2)}" # 2: parenthesize groups
101
114
  }.join("\n")
102
115
  end
103
116
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cddlc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carsten Bormann
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-25 00:00:00.000000000 Z
11
+ date: 2023-02-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -76,10 +76,31 @@ files:
76
76
  - bin/cddlc
77
77
  - cddlc.gemspec
78
78
  - data/prelude.cddl
79
+ - data/rfc8727.cddl
80
+ - data/rfc8927.cddl
81
+ - data/rfc8990.cddl
82
+ - data/rfc9052.cddl
83
+ - data/rfc9053.cddl
84
+ - data/rfc9054.cddl
85
+ - data/rfc9090.cddl
86
+ - data/rfc9115.cddl
87
+ - data/rfc9164.cddl
88
+ - data/rfc9165.cddl
89
+ - data/rfc9171.cddl
90
+ - data/rfc9173.cddl
91
+ - data/rfc9177.cddl
92
+ - data/rfc9202.cddl
93
+ - data/rfc9203.cddl
94
+ - data/rfc9237.cddl
95
+ - data/rfc9277.cddl
96
+ - data/rfc9290.cddl
97
+ - data/rfc9321.cddl
98
+ - data/rfc9338.cddl
79
99
  - lib/cddlc.rb
80
100
  - lib/parser/cddl-util.rb
81
101
  - lib/parser/cddlgrammar.rb
82
102
  - lib/processor/cddl-expander.rb
103
+ - lib/processor/cddl-undefined.rb
83
104
  - lib/processor/cddl-visitor.rb
84
105
  - lib/writer/cddl-writer.rb
85
106
  homepage: http://github.com/cabo/cddlc