cddlc 0.1.1 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|