cddlc 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -66,8 +171,6 @@ class CDDL
66
171
  @rules
67
172
  end
68
173
 
69
- DATA_DIR = Pathname.new(__FILE__) + "../../data/"
70
-
71
174
  def prelude
72
175
  if @prelude.nil?
73
176
  @prelude = CDDL.from_cddl(File.read(DATA_DIR + "prelude.cddl"))
@@ -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|
@@ -3,27 +3,36 @@ require_relative "./cddl-visitor.rb"
3
3
  require_relative "./cddl-expander.rb"
4
4
 
5
5
  class CDDL
6
- def cddl_undefined
7
- # currently only works on expanded...
8
- cddl2 = self
9
- cddl2.expand_generics
10
- used = {}
11
- gen_used = {}
12
- def_gen = {}
13
- cddl2.rules.each do |k, v|
14
- def_gen[k[0]] = true if Array === k
15
- cddl2.visit(v) do |p, &block|
16
- case p
6
+ def cddl_extract_names(prod, &name_used)
7
+ visit(prod) do |p|
8
+ case p
17
9
  in ["gen", name, *_gen_args]
18
- gen_used[name] = true
10
+ name_used.call(name)
11
+ false
19
12
  in ["name", name]
20
- used[name] = true
13
+ name_used.call(name)
14
+ false
21
15
  else
22
16
  false
23
- end
24
17
  end
25
18
  end
26
- [used.keys.reject {|name| cddl2.rules[name] || prelude.rules[name]},
27
- gen_used.keys.reject {|name| def_gen[name] }]
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]}
28
37
  end
29
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.1
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,7 +76,26 @@ 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
79
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
80
99
  - lib/cddlc.rb
81
100
  - lib/parser/cddl-util.rb
82
101
  - lib/parser/cddlgrammar.rb