cddlc 0.1.1 → 0.1.3
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 +4 -4
- data/bin/cddlc +1 -44
- data/cddlc.gemspec +1 -1
- data/data/rfc8727.cddl +946 -0
- data/data/rfc8927.cddl +96 -0
- data/data/rfc8990.cddl +213 -0
- data/data/rfc9053.cddl +21 -0
- data/data/rfc9054.cddl +13 -0
- data/data/rfc9090.cddl +14 -0
- data/data/rfc9115.cddl +99 -0
- data/data/rfc9164.cddl +32 -0
- data/data/rfc9165.cddl +35 -0
- data/data/rfc9171.cddl +334 -0
- data/data/rfc9173.cddl +36 -0
- data/data/rfc9177.cddl +6 -0
- data/data/rfc9202.cddl +6 -0
- data/data/rfc9203.cddl +11 -0
- data/data/rfc9237.cddl +27 -0
- data/data/rfc9277.cddl +11 -0
- data/data/rfc9290.cddl +37 -0
- data/data/rfc9321.cddl +67 -0
- data/data/rfc9338.cddl +34 -0
- data/lib/cddlc.rb +138 -6
- data/lib/parser/cddl-util.rb +1 -1
- data/lib/processor/cddl-expander.rb +13 -10
- data/lib/processor/cddl-undefined.rb +25 -16
- data/lib/processor/cddl-visitor.rb +2 -0
- data/lib/writer/cddl-writer.rb +38 -25
- metadata +21 -2
data/lib/cddlc.rb
CHANGED
@@ -1,8 +1,18 @@
|
|
1
1
|
require_relative "parser/cddl-util.rb"
|
2
|
+
require_relative "processor/cddl-visitor.rb"
|
3
|
+
require_relative 'processor/cddl-undefined.rb'
|
2
4
|
|
3
5
|
class CDDL
|
4
6
|
@@parser = CDDLGRAMMARParser.new
|
5
7
|
|
8
|
+
DATA_DIR = Pathname.new(__FILE__) + "../../data/"
|
9
|
+
# empty string is for CDDL::DATA_DIR
|
10
|
+
CDDL_INCLUDE_PATH = ENV["CDDL_INCLUDE_PATH"] || ".:"
|
11
|
+
|
12
|
+
def self.cddl_include_path
|
13
|
+
CDDL_INCLUDE_PATH.split(":", -1).map {_1 == "" ? CDDL::DATA_DIR : Pathname.new(_1)}
|
14
|
+
end
|
15
|
+
|
6
16
|
def self.reason(parser, s)
|
7
17
|
reason = [parser.failure_reason]
|
8
18
|
parser.failure_reason =~ /^(Expected .+) after/m
|
@@ -14,21 +24,133 @@ class CDDL
|
|
14
24
|
reason.join("\n")
|
15
25
|
end
|
16
26
|
|
27
|
+
# (keeps only renamed rules)
|
28
|
+
def rename(rename_map)
|
29
|
+
rules.replace(
|
30
|
+
Hash[rename_map.map do |o, n|
|
31
|
+
[n, visit(rules[o]) do |prod|
|
32
|
+
case prod
|
33
|
+
in ["name", *] | ["gen", *]
|
34
|
+
prod[1] = rename_map[prod[1]] || prod[1]
|
35
|
+
else
|
36
|
+
end
|
37
|
+
false
|
38
|
+
end]
|
39
|
+
end])
|
40
|
+
end
|
41
|
+
|
42
|
+
SAFE_FN = /\A[-._a-zA-Z0-9]+\z/
|
43
|
+
|
17
44
|
def self.from_cddl(s)
|
18
45
|
ast = @@parser.parse s
|
19
46
|
if !ast
|
20
47
|
fail self.reason(@@parser, s)
|
21
48
|
end
|
22
|
-
|
49
|
+
if $options.cddl2
|
50
|
+
directives = s.lines.grep(/^;# /).map(&:chomp).map{|l| l.sub(/^;#\s+/, '').split(/\s+/)}
|
51
|
+
# puts directives.to_yaml
|
52
|
+
end
|
53
|
+
ret = CDDL.new(ast, directives)
|
54
|
+
|
55
|
+
if $options.cddl2
|
56
|
+
ret.directives.each do |di|
|
57
|
+
preferred_tag = nil
|
58
|
+
case di
|
59
|
+
in ["include" => dir, docref]
|
60
|
+
in ["include" => dir, docref, "as", preferred_tag]
|
61
|
+
in ["import" => dir, docref]
|
62
|
+
in ["import" => dir, docref, "as", preferred_tag]
|
63
|
+
else
|
64
|
+
warn "** Can't parse include directive #{di.inspect}"
|
65
|
+
next
|
66
|
+
end
|
67
|
+
unless docref =~ SAFE_FN
|
68
|
+
warn "** skipping unsafe filename #{docref}"
|
69
|
+
next
|
70
|
+
end
|
71
|
+
puts "PREFERRED_TAG #{preferred_tag}" if $options.verbose
|
72
|
+
puts "DOCREF #{docref}" if $options.verbose
|
73
|
+
fn = docref.downcase << ".cddl"
|
74
|
+
|
75
|
+
io = nil
|
76
|
+
CDDL::cddl_include_path.each do |path|
|
77
|
+
begin
|
78
|
+
io = (path + fn).open
|
79
|
+
break
|
80
|
+
rescue Errno::ENOENT
|
81
|
+
next
|
82
|
+
end
|
83
|
+
end
|
84
|
+
unless io
|
85
|
+
warn "** include file #{fn} not found in #{CDDL::cddl_include_path.map(&:to_s)}"
|
86
|
+
next
|
87
|
+
end
|
88
|
+
|
89
|
+
include_file = io.read
|
90
|
+
included_cddl = CDDL.from_cddl(include_file)
|
91
|
+
if preferred_tag
|
92
|
+
included_cddl = included_cddl.deep_clone # needed?
|
93
|
+
renamed_names = included_cddl.rules.keys
|
94
|
+
name_rename = Hash[
|
95
|
+
renamed_names.map { |o|
|
96
|
+
n = "#{preferred_tag}.#{o}"
|
97
|
+
warn "** Warning: renamed name #{n} already in #{fn}" if included_cddl.rules[n]
|
98
|
+
[o, n]}]
|
99
|
+
included_cddl.rename(name_rename)
|
100
|
+
end
|
101
|
+
|
102
|
+
case dir
|
103
|
+
in "import"
|
104
|
+
warn "** IMPORTING #{fn}" if $options.verbose
|
105
|
+
undef_rule = nil
|
106
|
+
loop do
|
107
|
+
undef_rule = ret.cddl_undefined # XXX square...
|
108
|
+
# p undef_rule
|
109
|
+
got_more = false
|
110
|
+
undef_rule.each do |name|
|
111
|
+
if rule = included_cddl.rules[name]
|
112
|
+
ret.rules[name] = rule
|
113
|
+
warn "IMPORTED #{name} from #{fn}" if $options.verbose
|
114
|
+
got_more = true
|
115
|
+
end
|
116
|
+
end
|
117
|
+
break unless got_more
|
118
|
+
end
|
119
|
+
if preferred_tag
|
120
|
+
undef_rule.each do |name|
|
121
|
+
warn "** Warning: undefined reference #{name} without namespace prefix is defined in namespaced imported module #{fn}" if name_rename[name]
|
122
|
+
end
|
123
|
+
end
|
124
|
+
in "include"
|
125
|
+
warn "** INCLUDING #{fn}" if $options.verbose
|
126
|
+
included_cddl.rules.each do |k, v|
|
127
|
+
if old = ret.rules[k]
|
128
|
+
if old != v
|
129
|
+
warn "** included rule #{k} = #{v} would overwrite #{old}"
|
130
|
+
end
|
131
|
+
else
|
132
|
+
ret.rules[k] = v
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
ret
|
23
139
|
end
|
24
140
|
|
25
|
-
attr_accessor :ast, :tree
|
26
|
-
def initialize(ast_)
|
141
|
+
attr_accessor :ast, :tree, :directives
|
142
|
+
def initialize(ast_, directives_ = [])
|
27
143
|
@ast = ast_
|
28
144
|
@tree = ast.ast
|
29
145
|
@rules = nil # only fill in if needed
|
146
|
+
@directives = directives_
|
147
|
+
end
|
148
|
+
|
149
|
+
def deep_clone
|
150
|
+
Marshal.load(Marshal.dump(self))
|
30
151
|
end
|
31
152
|
|
153
|
+
|
32
154
|
RULE_OP_TO_CHOICE = {"/=" => "tcho", "//=" => "gcho"}
|
33
155
|
|
34
156
|
def rules
|
@@ -45,7 +167,19 @@ class CDDL
|
|
45
167
|
fail unless name.size == 2
|
46
168
|
name = name[1]
|
47
169
|
when "gen"
|
48
|
-
|
170
|
+
parmnames = name[2..-1]
|
171
|
+
name = name[1] # XXX update val with parm/arg
|
172
|
+
val = ["parm", parmnames,
|
173
|
+
visit(val) do |p|
|
174
|
+
case p
|
175
|
+
in ["name", nm]
|
176
|
+
if ix = parmnames.index(nm)
|
177
|
+
[true, ["arg", ix]]
|
178
|
+
end
|
179
|
+
else
|
180
|
+
false
|
181
|
+
end
|
182
|
+
end]
|
49
183
|
else
|
50
184
|
fail name
|
51
185
|
end
|
@@ -66,8 +200,6 @@ class CDDL
|
|
66
200
|
@rules
|
67
201
|
end
|
68
202
|
|
69
|
-
DATA_DIR = Pathname.new(__FILE__) + "../../data/"
|
70
|
-
|
71
203
|
def prelude
|
72
204
|
if @prelude.nil?
|
73
205
|
@prelude = CDDL.from_cddl(File.read(DATA_DIR + "prelude.cddl"))
|
data/lib/parser/cddl-util.rb
CHANGED
@@ -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,
|
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 ["
|
12
|
-
if replacement = subs[
|
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
|
-
|
39
|
-
|
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
|
-
|
45
|
-
fail unless rules[
|
46
|
-
rules.delete(
|
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
|
7
|
-
|
8
|
-
|
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
|
-
|
10
|
+
name_used.call(name)
|
11
|
+
false
|
19
12
|
in ["name", name]
|
20
|
-
|
13
|
+
name_used.call(name)
|
14
|
+
false
|
21
15
|
else
|
22
16
|
false
|
23
|
-
end
|
24
17
|
end
|
25
18
|
end
|
26
|
-
|
27
|
-
|
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
|
data/lib/writer/cddl-writer.rb
CHANGED
@@ -2,11 +2,10 @@ require_relative "../cddlc.rb"
|
|
2
2
|
|
3
3
|
class CDDL
|
4
4
|
|
5
|
-
def write_lhs(k)
|
6
|
-
|
7
|
-
|
8
|
-
|
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,
|
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
|
-
[
|
52
|
+
[3, "{#{write_rhs(group, 0, indent, pn)}}"] # 4->3: work around cddl tool limitation
|
48
53
|
in ["ary", group]
|
49
|
-
[
|
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,
|
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}\""]
|
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
|
-
|
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.
|
4
|
+
version: 0.1.3
|
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-
|
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
|