rng 0.3.6 → 0.3.8
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/lib/rng/external_ref_resolver.rb +88 -158
- data/lib/rng/grammar.rb +8 -0
- data/lib/rng/include_processor.rb +64 -90
- data/lib/rng/rnc_builder.rb +3 -14
- data/lib/rng/rnc_parser.rb +39 -17
- data/lib/rng/rnc_to_rng_converter.rb +125 -115
- data/lib/rng/version.rb +1 -1
- data/lib/rng.rb +7 -5
- data/rng.gemspec +1 -1
- data/spec/fixtures/external/order_lib.rng +13 -0
- data/spec/fixtures/external/order_main.rng +3 -0
- data/spec/rng/advanced_rnc_spec.rb +123 -0
- data/spec/rng/external_ref_resolver_spec.rb +23 -0
- data/spec/rng/parse_rnc_spec.rb +75 -0
- data/spec/rng/rnc_parser_spec.rb +145 -0
- data/spec/rng/rnc_roundtrip_spec.rb +77 -0
- data/spec/rng/schema_spec.rb +18 -0
- metadata +7 -5
- data/lib/rng/parse_rnc.rb +0 -26
|
@@ -69,6 +69,22 @@ RSpec.describe Rng::ExternalRefResolver do
|
|
|
69
69
|
end
|
|
70
70
|
end
|
|
71
71
|
|
|
72
|
+
context 'with interleaved children reached through an include' do
|
|
73
|
+
let(:order_main) { File.read('spec/fixtures/external/order_main.rng') }
|
|
74
|
+
|
|
75
|
+
it 'preserves element_order through external ref resolution' do
|
|
76
|
+
grammar = Rng::Grammar.from_xml(order_main)
|
|
77
|
+
resolved = described_class.new(grammar, location: 'spec/fixtures/external/order_main.rng').resolve
|
|
78
|
+
|
|
79
|
+
xml = resolved.to_xml
|
|
80
|
+
expect(xml.index('first')).to be < xml.index('mid')
|
|
81
|
+
expect(xml.index('mid')).to be < xml.index('last')
|
|
82
|
+
|
|
83
|
+
root = resolved.start.first.element
|
|
84
|
+
expect(root.instance_variable_get(:@element_order)).not_to be_nil
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
72
88
|
context 'with non-existent external file' do
|
|
73
89
|
it 'does not raise error but warns when external file not found' do
|
|
74
90
|
# Create a grammar with a non-existent include
|
|
@@ -110,6 +126,13 @@ RSpec.describe Rng::ExternalRefResolver do
|
|
|
110
126
|
# Without resolve_external, the grammar is returned as-is
|
|
111
127
|
expect(grammar).to be_a(Rng::Grammar)
|
|
112
128
|
end
|
|
129
|
+
|
|
130
|
+
it 'warns about unresolved external references when not resolving' do
|
|
131
|
+
main_rng = File.read('spec/fixtures/external/include_main.rng')
|
|
132
|
+
grammar = Rng.parse(main_rng)
|
|
133
|
+
|
|
134
|
+
expect(grammar.warnings).to include(a_string_matching(/include_lib\.rng/))
|
|
135
|
+
end
|
|
113
136
|
end
|
|
114
137
|
|
|
115
138
|
describe Rng::ExternalRefResolver::ExternalRefResolutionError do
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
require 'tmpdir'
|
|
5
|
+
|
|
6
|
+
RSpec.describe 'ParseRncSpec' do
|
|
7
|
+
describe '.parse_rnc' do
|
|
8
|
+
let(:simple_rnc) { 'element foo { text }' }
|
|
9
|
+
|
|
10
|
+
it 'returns a Grammar for include-free RNC without a location' do
|
|
11
|
+
parsed = Rng.parse_rnc(simple_rnc)
|
|
12
|
+
|
|
13
|
+
expect(parsed).to be_a(Rng::Grammar)
|
|
14
|
+
expect(parsed.start.first.element.attr_name).to eq('foo')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'produces equivalent output with and without location for hex-escaped RNC' do
|
|
18
|
+
# \x{72}oot decodes to "root". Hex preprocessing must run on the
|
|
19
|
+
# with-location path or the parse tree differs from the no-location path
|
|
20
|
+
# for the same input — which is the divergence this spec guards against.
|
|
21
|
+
rnc = 'element \\x{72}oot { text }'
|
|
22
|
+
|
|
23
|
+
Dir.mktmpdir do |dir|
|
|
24
|
+
scratch = File.join(dir, 'scratch.rnc')
|
|
25
|
+
|
|
26
|
+
without_location = Rng.parse_rnc(rnc)
|
|
27
|
+
with_location = Rng.parse_rnc(rnc, location: scratch)
|
|
28
|
+
|
|
29
|
+
expect(with_location.to_xml).to be_xml_equivalent_to(without_location.to_xml)
|
|
30
|
+
expect(with_location.start.first.element.attr_name).to eq('root')
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'resolves relative includes when location is the source directory' do
|
|
35
|
+
Dir.mktmpdir do |dir|
|
|
36
|
+
File.write(File.join(dir, 'child.rnc'), <<~RNC)
|
|
37
|
+
ChildPattern = element child { text }
|
|
38
|
+
start = element wrapped { ChildPattern }
|
|
39
|
+
RNC
|
|
40
|
+
|
|
41
|
+
parent_path = File.join(dir, 'parent.rnc')
|
|
42
|
+
File.write(parent_path, <<~RNC)
|
|
43
|
+
include "child.rnc" {
|
|
44
|
+
start = element root { ChildPattern }
|
|
45
|
+
}
|
|
46
|
+
RNC
|
|
47
|
+
|
|
48
|
+
parsed = Rng.parse_rnc(File.read(parent_path), location: dir)
|
|
49
|
+
|
|
50
|
+
expect(parsed.define.map(&:name)).to include('ChildPattern')
|
|
51
|
+
expect(parsed.start.first.element.attr_name).to eq('root')
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it 'also accepts a source file path as location' do
|
|
56
|
+
Dir.mktmpdir do |dir|
|
|
57
|
+
File.write(File.join(dir, 'child.rnc'), <<~RNC)
|
|
58
|
+
ChildPattern = element child { text }
|
|
59
|
+
RNC
|
|
60
|
+
|
|
61
|
+
parent_path = File.join(dir, 'parent.rnc')
|
|
62
|
+
File.write(parent_path, <<~RNC)
|
|
63
|
+
include "child.rnc" {
|
|
64
|
+
start = element root { ChildPattern }
|
|
65
|
+
}
|
|
66
|
+
RNC
|
|
67
|
+
|
|
68
|
+
parsed = Rng.parse_rnc(File.read(parent_path), location: parent_path)
|
|
69
|
+
|
|
70
|
+
expect(parsed.define.map(&:name)).to include('ChildPattern')
|
|
71
|
+
expect(parsed.start.first.element.attr_name).to eq('root')
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
data/spec/rng/rnc_parser_spec.rb
CHANGED
|
@@ -182,6 +182,54 @@ RSpec.describe Rng::RncParser do
|
|
|
182
182
|
end
|
|
183
183
|
end
|
|
184
184
|
|
|
185
|
+
context 'with occurrence markers on leaf patterns' do
|
|
186
|
+
def root_element_for(form, extra = '')
|
|
187
|
+
rnc = "start = element root { #{form} }\n#{extra}"
|
|
188
|
+
described_class.parse(rnc).start.first.element
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# On Element, :ref is a collection slot but :text/:empty/etc. are singular,
|
|
192
|
+
# so "leaf is empty" needs to handle both shapes uniformly.
|
|
193
|
+
def leaf_empty?(container, slot)
|
|
194
|
+
v = container.public_send(slot)
|
|
195
|
+
v.nil? || (v.respond_to?(:empty?) && v.empty?)
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# form => { slot: model accessor on Element/wrapper, extra: extra RNC needed }
|
|
199
|
+
patterns = {
|
|
200
|
+
'item' => { slot: :ref, extra: "item = element item { text }\n" },
|
|
201
|
+
'text' => { slot: :text },
|
|
202
|
+
'empty' => { slot: :empty },
|
|
203
|
+
'notAllowed' => { slot: :notAllowed },
|
|
204
|
+
'"foo"' => { slot: :value },
|
|
205
|
+
'xsd:string' => { slot: :data }
|
|
206
|
+
}
|
|
207
|
+
wrappers = { '*' => :zeroOrMore, '+' => :oneOrMore, '?' => :optional }
|
|
208
|
+
|
|
209
|
+
patterns.each do |form, config|
|
|
210
|
+
slot = config[:slot]
|
|
211
|
+
extra = config[:extra].to_s
|
|
212
|
+
|
|
213
|
+
it "emits a bare <#{slot}> when there is no occurrence marker on #{form}" do
|
|
214
|
+
element = root_element_for(form, extra)
|
|
215
|
+
expect(leaf_empty?(element, slot)).to be(false)
|
|
216
|
+
expect(element.zeroOrMore).to be_empty
|
|
217
|
+
expect(element.oneOrMore).to be_empty
|
|
218
|
+
expect(element.optional).to be_empty
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
wrappers.each do |marker, wrapper|
|
|
222
|
+
it "wraps #{form}#{marker} in <#{wrapper}>" do
|
|
223
|
+
element = root_element_for("#{form}#{marker}", extra)
|
|
224
|
+
wrapper_coll = element.public_send(wrapper)
|
|
225
|
+
expect(wrapper_coll.length).to eq(1)
|
|
226
|
+
expect(wrapper_coll.first.public_send(slot).length).to eq(1)
|
|
227
|
+
expect(leaf_empty?(element, slot)).to be(true)
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
185
233
|
context 'with pattern references in choice' do
|
|
186
234
|
let(:input) do
|
|
187
235
|
<<~RNC
|
|
@@ -415,6 +463,103 @@ RSpec.describe Rng::RncParser do
|
|
|
415
463
|
end
|
|
416
464
|
end
|
|
417
465
|
|
|
466
|
+
context 'with named pattern after ## comment' do
|
|
467
|
+
let(:input) do
|
|
468
|
+
<<~RNC
|
|
469
|
+
document =
|
|
470
|
+
element document {
|
|
471
|
+
## test 1
|
|
472
|
+
test
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
test =
|
|
476
|
+
element sections {
|
|
477
|
+
attribute test { text }?
|
|
478
|
+
}
|
|
479
|
+
RNC
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
let(:grammar) { described_class.parse(input) }
|
|
483
|
+
|
|
484
|
+
it 'parses without error' do
|
|
485
|
+
expect { grammar }.not_to raise_error
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
it 'contains the element document' do
|
|
489
|
+
expect(grammar.define.map(&:name)).to include('document')
|
|
490
|
+
document_def = grammar.define.find { |d| d.name == 'document' }
|
|
491
|
+
expect(document_def.element[0].attr_name).to eq('document')
|
|
492
|
+
end
|
|
493
|
+
|
|
494
|
+
it 'contains the element sections' do
|
|
495
|
+
expect(grammar.define.map(&:name)).to include('test')
|
|
496
|
+
test_def = grammar.define.find { |d| d.name == 'test' }
|
|
497
|
+
expect(test_def.element[0].attr_name).to eq('sections')
|
|
498
|
+
end
|
|
499
|
+
end
|
|
500
|
+
|
|
501
|
+
context 'with escape sequences in string literals' do
|
|
502
|
+
it 'parses known escapes (\\n, \\t, \\r, \\", \\\\)' do
|
|
503
|
+
input = <<~'RNC'
|
|
504
|
+
start = element value {
|
|
505
|
+
xsd:string { pattern = "hello\nworld\ttab\r\n" }
|
|
506
|
+
}
|
|
507
|
+
RNC
|
|
508
|
+
expect { described_class.parse(input) }.not_to raise_error
|
|
509
|
+
end
|
|
510
|
+
|
|
511
|
+
it 'parses RELAX NG class escapes (\\i, \\c, \\d, \\w)' do
|
|
512
|
+
input = <<~'RNC'
|
|
513
|
+
start = element value {
|
|
514
|
+
xsd:string { pattern = "\\i\\c\\d\\w" }
|
|
515
|
+
}
|
|
516
|
+
RNC
|
|
517
|
+
expect { described_class.parse(input) }.not_to raise_error
|
|
518
|
+
end
|
|
519
|
+
|
|
520
|
+
it 'parses unknown escape sequences (\\+, \\-, \\s, \\., \\,) preserving backslash' do
|
|
521
|
+
input = <<~'RNC'
|
|
522
|
+
start = element value {
|
|
523
|
+
xsd:string { pattern = "[\\+\\-]?\\d{4}" }
|
|
524
|
+
}
|
|
525
|
+
RNC
|
|
526
|
+
expect { described_class.parse(input) }.not_to raise_error
|
|
527
|
+
end
|
|
528
|
+
|
|
529
|
+
it 'parses ISO 8601 regex pattern with multiple escape sequences' do
|
|
530
|
+
input = <<~'RNC'
|
|
531
|
+
ISO8601DateTime = xsd:string { pattern = "([\\+\\-]?\\d{4})((-?)((0[1-9]|1[0-2])((-?)([12]\\d|0[1-9]|3[01]))?|W([0-4]\\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\\d|[12]\\d{2}|3([0-5]\\d|6[1-6])))([T\\s]((([01]\\d|2[0-3])((:?)[0-5]\\d)?|24:?00)([\\.,]\\d+)?)?((:?)[0-5]\\d([.,]\\d+)?)?([zZ]|([\\+\\-])([01]\\d|2[0-3]):?([0-5]\\d)?)?)?)?)?)?" }
|
|
532
|
+
elem = element elem { ISO8601DateTime }
|
|
533
|
+
RNC
|
|
534
|
+
expect { described_class.parse(input) }.not_to raise_error
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
it 'rejects invalid hex escape \\x{}' do
|
|
538
|
+
# Single-quoted heredoc: \x{} is literal \x{} (one backslash)
|
|
539
|
+
input = <<~'RNC'
|
|
540
|
+
start = element value {
|
|
541
|
+
xsd:string { pattern = "\x{}" }
|
|
542
|
+
}
|
|
543
|
+
RNC
|
|
544
|
+
expect do
|
|
545
|
+
described_class.parse(input)
|
|
546
|
+
end.to raise_error(Parslet::ParseFailed)
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
it 'round-trips unknown escape sequences preserving backslash' do
|
|
550
|
+
rnc_input = <<~'RNC'
|
|
551
|
+
start = element value {
|
|
552
|
+
xsd:string { pattern = "[\\+\\-]?\\d{4}" }
|
|
553
|
+
}
|
|
554
|
+
RNC
|
|
555
|
+
grammar = described_class.parse(rnc_input)
|
|
556
|
+
rnc_output = described_class.to_rnc(grammar)
|
|
557
|
+
expect(rnc_output).to include('\\+')
|
|
558
|
+
expect(rnc_output).to include('\\-')
|
|
559
|
+
expect(rnc_output).to include('\\d')
|
|
560
|
+
end
|
|
561
|
+
end
|
|
562
|
+
|
|
418
563
|
context 'with except patterns in anyName' do
|
|
419
564
|
let(:input) do
|
|
420
565
|
<<~RNC
|
|
@@ -97,6 +97,83 @@ RSpec.describe 'RNG to RNC Round-trip Tests' do
|
|
|
97
97
|
expect(xml).to include('<choice')
|
|
98
98
|
end
|
|
99
99
|
|
|
100
|
+
it 'preserves a mixed attribute choice of text and value' do
|
|
101
|
+
rnc = <<~RNC
|
|
102
|
+
start = element doc {
|
|
103
|
+
attribute a { text | "x" }
|
|
104
|
+
}
|
|
105
|
+
RNC
|
|
106
|
+
xml = Rng.parse_rnc(rnc).to_xml
|
|
107
|
+
expect(xml).to include('<choice>')
|
|
108
|
+
expect(xml).to include('<text>')
|
|
109
|
+
expect(xml).to include('<value>x</value>')
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it 'preserves a mixed attribute choice of value and ref' do
|
|
113
|
+
rnc = <<~RNC
|
|
114
|
+
start = element doc {
|
|
115
|
+
attribute a { "x" | foo }
|
|
116
|
+
}
|
|
117
|
+
foo = element foo { text }
|
|
118
|
+
RNC
|
|
119
|
+
xml = Rng.parse_rnc(rnc).to_xml
|
|
120
|
+
expect(xml).to include('<choice>')
|
|
121
|
+
expect(xml).to include('<value>x</value>')
|
|
122
|
+
expect(xml).to include('<ref name="foo"/>')
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it 'preserves a mixed attribute choice of text and ref' do
|
|
126
|
+
rnc = <<~RNC
|
|
127
|
+
start = element doc {
|
|
128
|
+
attribute a { text | foo }
|
|
129
|
+
}
|
|
130
|
+
foo = element foo { text }
|
|
131
|
+
RNC
|
|
132
|
+
xml = Rng.parse_rnc(rnc).to_xml
|
|
133
|
+
expect(xml).to include('<choice>')
|
|
134
|
+
expect(xml).to include('<text>')
|
|
135
|
+
expect(xml).to include('<ref name="foo"/>')
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it 'emits a mixed attribute choice of text and value back to RNC' do
|
|
139
|
+
rng = <<~RNG
|
|
140
|
+
<grammar xmlns="http://relaxng.org/ns/structure/1.0">
|
|
141
|
+
<start><element name="doc"><attribute name="indent">
|
|
142
|
+
<choice><text/><value>adaptive</value></choice>
|
|
143
|
+
</attribute></element></start>
|
|
144
|
+
</grammar>
|
|
145
|
+
RNG
|
|
146
|
+
rnc = Rng.to_rnc(Rng.parse(rng))
|
|
147
|
+
expect(rnc).to match(/attribute indent \{[^}]*text[^}]*\}/)
|
|
148
|
+
expect(rnc).to include('"adaptive"')
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
it 'emits a mixed attribute choice of value and ref back to RNC' do
|
|
152
|
+
rng = <<~RNG
|
|
153
|
+
<grammar xmlns="http://relaxng.org/ns/structure/1.0">
|
|
154
|
+
<start><element name="doc"><attribute name="a">
|
|
155
|
+
<choice><value>x</value><ref name="foo"/></choice>
|
|
156
|
+
</attribute></element></start>
|
|
157
|
+
<define name="foo"><text/></define>
|
|
158
|
+
</grammar>
|
|
159
|
+
RNG
|
|
160
|
+
rnc = Rng.to_rnc(Rng.parse(rng))
|
|
161
|
+
expect(rnc).to match(/attribute a \{[^}]*foo[^}]*\}/)
|
|
162
|
+
expect(rnc).to include('"x"')
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
it 'round-trips a mixed attribute choice of text and value through RNC and RNG' do
|
|
166
|
+
rnc = <<~RNC
|
|
167
|
+
start = element doc {
|
|
168
|
+
attribute indent { text | "adaptive" }
|
|
169
|
+
}
|
|
170
|
+
RNC
|
|
171
|
+
regenerated = Rng.to_rnc(Rng.parse(Rng.parse_rnc(rnc).to_xml))
|
|
172
|
+
# Both members of the choice must survive a full RNC -> RNG -> RNC trip
|
|
173
|
+
expect(regenerated).to match(/attribute indent \{[^}]*text[^}]*\}/)
|
|
174
|
+
expect(regenerated).to include('"adaptive"')
|
|
175
|
+
end
|
|
176
|
+
|
|
100
177
|
it 'preserves interleave' do
|
|
101
178
|
rnc = <<~RNC
|
|
102
179
|
start = element foo {
|
data/spec/rng/schema_spec.rb
CHANGED
|
@@ -81,6 +81,24 @@ RSpec.describe Rng::Grammar do
|
|
|
81
81
|
expect(start_element).to be_a(Rng::Element)
|
|
82
82
|
expect(start_element.attr_name).to eq('addressBook')
|
|
83
83
|
end
|
|
84
|
+
|
|
85
|
+
it 'resolves includes for in-memory RNC when location is the source directory' do
|
|
86
|
+
main_path = File.expand_path('spec/fixtures/rnc/main_with_include.rnc')
|
|
87
|
+
parsed = Rng.parse_rnc(File.read(main_path), location: File.dirname(main_path))
|
|
88
|
+
|
|
89
|
+
expect(parsed).to be_a(described_class)
|
|
90
|
+
expect(parsed.define.map(&:name)).to include('BasePattern', 'ExtendedPattern')
|
|
91
|
+
expect(parsed.start.first.element.attr_name).to eq('doc')
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it 'matches parse_file include resolution for in-memory RNC when location is the source directory' do
|
|
95
|
+
main_path = File.expand_path('spec/fixtures/rnc/main_include_trailing.rnc')
|
|
96
|
+
from_memory = Rng.parse_rnc(File.read(main_path), location: File.dirname(main_path))
|
|
97
|
+
from_file = Rng.parse_file(main_path)
|
|
98
|
+
|
|
99
|
+
expect(from_memory.start.first.element.attr_name).to eq(from_file.start.first.element.attr_name)
|
|
100
|
+
expect(from_memory.define.map(&:name).sort).to eq(from_file.define.map(&:name).sort)
|
|
101
|
+
end
|
|
84
102
|
end
|
|
85
103
|
|
|
86
104
|
describe 'RNG to RNC conversion' do
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rng
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-10-19 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: lutaml-model
|
|
@@ -16,14 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 0.8.
|
|
19
|
+
version: 0.8.114
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: 0.8.
|
|
26
|
+
version: 0.8.114
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: nokogiri
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -136,7 +136,6 @@ files:
|
|
|
136
136
|
- lib/rng/optional.rb
|
|
137
137
|
- lib/rng/param.rb
|
|
138
138
|
- lib/rng/parent_ref.rb
|
|
139
|
-
- lib/rng/parse_rnc.rb
|
|
140
139
|
- lib/rng/parse_tree_processor.rb
|
|
141
140
|
- lib/rng/pattern.rb
|
|
142
141
|
- lib/rng/ref.rb
|
|
@@ -166,6 +165,8 @@ files:
|
|
|
166
165
|
- spec/fixtures/external/nested_chain.rng
|
|
167
166
|
- spec/fixtures/external/nested_leaf.rng
|
|
168
167
|
- spec/fixtures/external/nested_mid.rng
|
|
168
|
+
- spec/fixtures/external/order_lib.rng
|
|
169
|
+
- spec/fixtures/external/order_main.rng
|
|
169
170
|
- spec/fixtures/metanorma/3gpp.rnc
|
|
170
171
|
- spec/fixtures/metanorma/3gpp.rng
|
|
171
172
|
- spec/fixtures/metanorma/basicdoc.rnc
|
|
@@ -254,6 +255,7 @@ files:
|
|
|
254
255
|
- spec/rng/metanorma_conversion_spec.rb
|
|
255
256
|
- spec/rng/namespace_declaration_spec.rb
|
|
256
257
|
- spec/rng/namespace_support_spec.rb
|
|
258
|
+
- spec/rng/parse_rnc_spec.rb
|
|
257
259
|
- spec/rng/rnc_parser_spec.rb
|
|
258
260
|
- spec/rng/rnc_roundtrip_spec.rb
|
|
259
261
|
- spec/rng/rng_generation_spec.rb
|
data/lib/rng/parse_rnc.rb
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Rng
|
|
4
|
-
# RNC Parser module
|
|
5
|
-
# Provides functionality to parse RELAX NG Compact Syntax (RNC) files
|
|
6
|
-
module ParseRnc
|
|
7
|
-
class << self
|
|
8
|
-
# Parse RNC syntax and return an RNG schema object
|
|
9
|
-
# @param rnc_string [String] The RNC content to parse
|
|
10
|
-
# @return [Rng::Grammar] The parsed schema object
|
|
11
|
-
def parse(rnc_string)
|
|
12
|
-
# This is a placeholder implementation
|
|
13
|
-
# The actual parsing logic would need to be implemented
|
|
14
|
-
|
|
15
|
-
# For now, we delegate to RncParser which is our internal implementation
|
|
16
|
-
# In the future, this could be expanded with additional functionality
|
|
17
|
-
RncParser.parse(rnc_string)
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
# Add class-level parsing method
|
|
23
|
-
def self.parse_rnc(rnc_string)
|
|
24
|
-
ParseRnc.parse(rnc_string)
|
|
25
|
-
end
|
|
26
|
-
end
|