plurimath-parslet 3.0.0
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 +7 -0
- data/HISTORY.txt +284 -0
- data/LICENSE +23 -0
- data/README.adoc +454 -0
- data/Rakefile +71 -0
- data/lib/parslet/accelerator/application.rb +62 -0
- data/lib/parslet/accelerator/engine.rb +112 -0
- data/lib/parslet/accelerator.rb +162 -0
- data/lib/parslet/atoms/alternative.rb +53 -0
- data/lib/parslet/atoms/base.rb +157 -0
- data/lib/parslet/atoms/can_flatten.rb +137 -0
- data/lib/parslet/atoms/capture.rb +38 -0
- data/lib/parslet/atoms/context.rb +103 -0
- data/lib/parslet/atoms/dsl.rb +112 -0
- data/lib/parslet/atoms/dynamic.rb +32 -0
- data/lib/parslet/atoms/entity.rb +45 -0
- data/lib/parslet/atoms/ignored.rb +26 -0
- data/lib/parslet/atoms/infix.rb +115 -0
- data/lib/parslet/atoms/lookahead.rb +52 -0
- data/lib/parslet/atoms/named.rb +32 -0
- data/lib/parslet/atoms/re.rb +41 -0
- data/lib/parslet/atoms/repetition.rb +87 -0
- data/lib/parslet/atoms/scope.rb +26 -0
- data/lib/parslet/atoms/sequence.rb +48 -0
- data/lib/parslet/atoms/str.rb +42 -0
- data/lib/parslet/atoms/visitor.rb +89 -0
- data/lib/parslet/atoms.rb +34 -0
- data/lib/parslet/cause.rb +101 -0
- data/lib/parslet/context.rb +21 -0
- data/lib/parslet/convenience.rb +33 -0
- data/lib/parslet/error_reporter/contextual.rb +120 -0
- data/lib/parslet/error_reporter/deepest.rb +100 -0
- data/lib/parslet/error_reporter/tree.rb +63 -0
- data/lib/parslet/error_reporter.rb +8 -0
- data/lib/parslet/export.rb +163 -0
- data/lib/parslet/expression/treetop.rb +92 -0
- data/lib/parslet/expression.rb +51 -0
- data/lib/parslet/graphviz.rb +97 -0
- data/lib/parslet/parser.rb +68 -0
- data/lib/parslet/pattern/binding.rb +49 -0
- data/lib/parslet/pattern.rb +113 -0
- data/lib/parslet/position.rb +21 -0
- data/lib/parslet/rig/rspec.rb +52 -0
- data/lib/parslet/scope.rb +42 -0
- data/lib/parslet/slice.rb +105 -0
- data/lib/parslet/source/line_cache.rb +99 -0
- data/lib/parslet/source.rb +96 -0
- data/lib/parslet/transform.rb +265 -0
- data/lib/parslet/version.rb +5 -0
- data/lib/parslet.rb +314 -0
- data/plurimath-parslet.gemspec +42 -0
- data/spec/acceptance/infix_parser_spec.rb +145 -0
- data/spec/acceptance/mixing_parsers_spec.rb +74 -0
- data/spec/acceptance/regression_spec.rb +329 -0
- data/spec/acceptance/repetition_and_maybe_spec.rb +44 -0
- data/spec/acceptance/unconsumed_input_spec.rb +21 -0
- data/spec/examples/boolean_algebra_spec.rb +257 -0
- data/spec/examples/calc_spec.rb +278 -0
- data/spec/examples/capture_spec.rb +137 -0
- data/spec/examples/comments_spec.rb +186 -0
- data/spec/examples/deepest_errors_spec.rb +420 -0
- data/spec/examples/documentation_spec.rb +205 -0
- data/spec/examples/email_parser_spec.rb +275 -0
- data/spec/examples/empty_spec.rb +37 -0
- data/spec/examples/erb_spec.rb +482 -0
- data/spec/examples/ip_address_spec.rb +153 -0
- data/spec/examples/json_spec.rb +413 -0
- data/spec/examples/local_spec.rb +302 -0
- data/spec/examples/mathn_spec.rb +151 -0
- data/spec/examples/minilisp_spec.rb +492 -0
- data/spec/examples/modularity_spec.rb +340 -0
- data/spec/examples/nested_errors_spec.rb +322 -0
- data/spec/examples/optimized_erb_spec.rb +299 -0
- data/spec/examples/parens_spec.rb +239 -0
- data/spec/examples/prec_calc_spec.rb +525 -0
- data/spec/examples/readme_spec.rb +228 -0
- data/spec/examples/scopes_spec.rb +187 -0
- data/spec/examples/seasons_spec.rb +196 -0
- data/spec/examples/sentence_spec.rb +119 -0
- data/spec/examples/simple_xml_spec.rb +250 -0
- data/spec/examples/string_parser_spec.rb +407 -0
- data/spec/fixtures/examples/boolean_algebra.rb +62 -0
- data/spec/fixtures/examples/calc.rb +86 -0
- data/spec/fixtures/examples/capture.rb +36 -0
- data/spec/fixtures/examples/comments.rb +22 -0
- data/spec/fixtures/examples/deepest_errors.rb +99 -0
- data/spec/fixtures/examples/documentation.rb +32 -0
- data/spec/fixtures/examples/email_parser.rb +42 -0
- data/spec/fixtures/examples/empty.rb +10 -0
- data/spec/fixtures/examples/erb.rb +39 -0
- data/spec/fixtures/examples/ip_address.rb +103 -0
- data/spec/fixtures/examples/json.rb +107 -0
- data/spec/fixtures/examples/local.rb +60 -0
- data/spec/fixtures/examples/mathn.rb +47 -0
- data/spec/fixtures/examples/minilisp.rb +75 -0
- data/spec/fixtures/examples/modularity.rb +60 -0
- data/spec/fixtures/examples/nested_errors.rb +95 -0
- data/spec/fixtures/examples/optimized_erb.rb +105 -0
- data/spec/fixtures/examples/parens.rb +25 -0
- data/spec/fixtures/examples/prec_calc.rb +71 -0
- data/spec/fixtures/examples/readme.rb +59 -0
- data/spec/fixtures/examples/scopes.rb +43 -0
- data/spec/fixtures/examples/seasons.rb +40 -0
- data/spec/fixtures/examples/sentence.rb +18 -0
- data/spec/fixtures/examples/simple_xml.rb +51 -0
- data/spec/fixtures/examples/string_parser.rb +77 -0
- data/spec/parslet/atom_results_spec.rb +39 -0
- data/spec/parslet/atoms/alternative_spec.rb +26 -0
- data/spec/parslet/atoms/base_spec.rb +127 -0
- data/spec/parslet/atoms/capture_spec.rb +21 -0
- data/spec/parslet/atoms/combinations_spec.rb +5 -0
- data/spec/parslet/atoms/dsl_spec.rb +7 -0
- data/spec/parslet/atoms/entity_spec.rb +77 -0
- data/spec/parslet/atoms/ignored_spec.rb +15 -0
- data/spec/parslet/atoms/infix_spec.rb +5 -0
- data/spec/parslet/atoms/lookahead_spec.rb +22 -0
- data/spec/parslet/atoms/named_spec.rb +4 -0
- data/spec/parslet/atoms/re_spec.rb +14 -0
- data/spec/parslet/atoms/repetition_spec.rb +24 -0
- data/spec/parslet/atoms/scope_spec.rb +26 -0
- data/spec/parslet/atoms/sequence_spec.rb +28 -0
- data/spec/parslet/atoms/str_spec.rb +15 -0
- data/spec/parslet/atoms/visitor_spec.rb +101 -0
- data/spec/parslet/atoms_spec.rb +488 -0
- data/spec/parslet/convenience_spec.rb +54 -0
- data/spec/parslet/error_reporter/contextual_spec.rb +118 -0
- data/spec/parslet/error_reporter/deepest_spec.rb +82 -0
- data/spec/parslet/error_reporter/tree_spec.rb +7 -0
- data/spec/parslet/export_spec.rb +40 -0
- data/spec/parslet/expression/treetop_spec.rb +74 -0
- data/spec/parslet/minilisp.citrus +29 -0
- data/spec/parslet/minilisp.tt +29 -0
- data/spec/parslet/parser_spec.rb +36 -0
- data/spec/parslet/parslet_spec.rb +38 -0
- data/spec/parslet/pattern_spec.rb +272 -0
- data/spec/parslet/position_spec.rb +14 -0
- data/spec/parslet/rig/rspec_spec.rb +54 -0
- data/spec/parslet/scope_spec.rb +45 -0
- data/spec/parslet/slice_spec.rb +186 -0
- data/spec/parslet/source/line_cache_spec.rb +74 -0
- data/spec/parslet/source_spec.rb +210 -0
- data/spec/parslet/transform/context_spec.rb +56 -0
- data/spec/parslet/transform_spec.rb +183 -0
- data/spec/spec_helper.rb +74 -0
- data/spec/support/opal.rb +8 -0
- data/spec/support/opal.rb.erb +14 -0
- data/spec/support/parslet_matchers.rb +96 -0
- metadata +240 -0
@@ -0,0 +1,119 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require_relative '../fixtures/examples/sentence'
|
5
|
+
|
6
|
+
RSpec.describe 'Sentence Parser Example' do
|
7
|
+
let(:parser) { SentenceExample::MyParser.new }
|
8
|
+
let(:transformer) { SentenceExample::Transformer.new }
|
9
|
+
|
10
|
+
describe SentenceExample::MyParser do
|
11
|
+
describe '#sentence' do
|
12
|
+
it 'parses a single sentence ending with 。' do
|
13
|
+
result = parser.sentence.parse("テスト。")
|
14
|
+
expect(result).to parse_as({ sentence: "テスト。" })
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'parses sentences with complex Unicode characters' do
|
18
|
+
result = parser.sentence.parse("RubyKaigi2009のテーマは、「変わる/変える」です。")
|
19
|
+
expect(result).to parse_as({ sentence: "RubyKaigi2009のテーマは、「変わる/変える」です。" })
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'fails to parse text without sentence ending' do
|
23
|
+
expect { parser.sentence.parse("テスト") }.to raise_error(Parslet::ParseFailed)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#sentences' do
|
28
|
+
it 'parses multiple sentences' do
|
29
|
+
input = "第一。第二。第三。"
|
30
|
+
result = parser.sentences.parse(input)
|
31
|
+
expected = [
|
32
|
+
{ sentence: "第一。" },
|
33
|
+
{ sentence: "第二。" },
|
34
|
+
{ sentence: "第三。" }
|
35
|
+
]
|
36
|
+
expect(result).to parse_as(expected)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'parses single sentence as array' do
|
40
|
+
result = parser.sentences.parse("テスト。")
|
41
|
+
expected = [{ sentence: "テスト。" }]
|
42
|
+
expect(result).to parse_as(expected)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'parses empty input as empty array' do
|
46
|
+
result = parser.sentences.parse("")
|
47
|
+
expect(result).to eq("")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe 'root parser' do
|
52
|
+
it 'parses the full example string correctly' do
|
53
|
+
string = "RubyKaigi2009のテーマは、「変わる/変える」です。 前回の" +
|
54
|
+
"RubyKaigi2008のテーマであった「多様性」の言葉の通り、 " +
|
55
|
+
"2008年はRubyそのものに関しても、またRubyの活躍する舞台に関しても、 " +
|
56
|
+
"ますます多様化が進みつつあります。RubyKaigi2008は、そのような " +
|
57
|
+
"Rubyの生態系をあらためて認識する場となりました。 しかし、" +
|
58
|
+
"こうした多様化が進む中、異なる者同士が単純に距離を 置いたままでは、" +
|
59
|
+
"その違いを認識したところであまり意味がありません。 異なる実装、" +
|
60
|
+
"異なる思想、異なる背景といった、様々な多様性を理解しつつ、 " +
|
61
|
+
"すり合わせるべきものをすり合わせ、変えていくべきところを " +
|
62
|
+
"変えていくことが、豊かな未来へとつながる道に違いありません。"
|
63
|
+
|
64
|
+
result = parser.parse(string)
|
65
|
+
expected = [
|
66
|
+
{ sentence: "RubyKaigi2009のテーマは、「変わる/変える」です。" },
|
67
|
+
{ sentence: " 前回のRubyKaigi2008のテーマであった「多様性」の言葉の通り、 2008年はRubyそのものに関しても、またRubyの活躍する舞台に関しても、 ますます多様化が進みつつあります。" },
|
68
|
+
{ sentence: "RubyKaigi2008は、そのような Rubyの生態系をあらためて認識する場となりました。" },
|
69
|
+
{ sentence: " しかし、こうした多様化が進む中、異なる者同士が単純に距離を 置いたままでは、その違いを認識したところであまり意味がありません。" },
|
70
|
+
{ sentence: " 異なる実装、異なる思想、異なる背景といった、様々な多様性を理解しつつ、 すり合わせるべきものをすり合わせ、変えていくべきところを 変えていくことが、豊かな未来へとつながる道に違いありません。" }
|
71
|
+
]
|
72
|
+
expect(result).to parse_as(expected)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe SentenceExample::Transformer do
|
78
|
+
it 'transforms sentence slices to strings' do
|
79
|
+
input = { sentence: Parslet::Slice.new(Parslet::Position.new("テスト", 0), "テスト") }
|
80
|
+
result = transformer.apply(input)
|
81
|
+
expect(result).to eq("テスト")
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'transforms array of sentences' do
|
85
|
+
input = [
|
86
|
+
{ sentence: Parslet::Slice.new(Parslet::Position.new("第一第二", 0), "第一") },
|
87
|
+
{ sentence: Parslet::Slice.new(Parslet::Position.new("第一第二", 2), "第二") }
|
88
|
+
]
|
89
|
+
result = transformer.apply(input)
|
90
|
+
expect(result).to eq(["第一", "第二"])
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe 'integration test' do
|
95
|
+
it 'processes the full example correctly' do
|
96
|
+
string = "RubyKaigi2009のテーマは、「変わる/変える」です。 前回の" +
|
97
|
+
"RubyKaigi2008のテーマであった「多様性」の言葉の通り、 " +
|
98
|
+
"2008年はRubyそのものに関しても、またRubyの活躍する舞台に関しても、 " +
|
99
|
+
"ますます多様化が進みつつあります。RubyKaigi2008は、そのような " +
|
100
|
+
"Rubyの生態系をあらためて認識する場となりました。 しかし、" +
|
101
|
+
"こうした多様化が進む中、異なる者同士が単純に距離を 置いたままでは、" +
|
102
|
+
"その違いを認識したところであまり意味がありません。 異なる実装、" +
|
103
|
+
"異なる思想、異なる背景といった、様々な多様性を理解しつつ、 " +
|
104
|
+
"すり合わせるべきものをすり合わせ、変えていくべきところを " +
|
105
|
+
"変えていくことが、豊かな未来へとつながる道に違いありません。"
|
106
|
+
|
107
|
+
tree = parser.parse(string)
|
108
|
+
result = transformer.apply(tree)
|
109
|
+
|
110
|
+
expect(result).to be_an(Array)
|
111
|
+
expect(result.length).to eq(5)
|
112
|
+
expect(result[0]).to eq("RubyKaigi2009のテーマは、「変わる/変える」です。")
|
113
|
+
expect(result[1]).to eq(" 前回のRubyKaigi2008のテーマであった「多様性」の言葉の通り、 2008年はRubyそのものに関しても、またRubyの活躍する舞台に関しても、 ますます多様化が進みつつあります。")
|
114
|
+
expect(result[2]).to eq("RubyKaigi2008は、そのような Rubyの生態系をあらためて認識する場となりました。")
|
115
|
+
expect(result[3]).to eq(" しかし、こうした多様化が進む中、異なる者同士が単純に距離を 置いたままでは、その違いを認識したところであまり意味がありません。")
|
116
|
+
expect(result[4]).to eq(" 異なる実装、異なる思想、異なる背景といった、様々な多様性を理解しつつ、 すり合わせるべきものをすり合わせ、変えていくべきところを 変えていくことが、豊かな未来へとつながる道に違いありません。")
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,250 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require_relative '../fixtures/examples/simple_xml'
|
3
|
+
|
4
|
+
RSpec.describe 'Simple XML Parser Example' do
|
5
|
+
let(:parser) { XML.new }
|
6
|
+
|
7
|
+
describe XML do
|
8
|
+
describe '#text' do
|
9
|
+
it 'parses empty text' do
|
10
|
+
result = parser.text.parse('')
|
11
|
+
expect(result).to eq('')
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'parses simple text' do
|
15
|
+
result = parser.text.parse('hello world')
|
16
|
+
expect(result).to eq('hello world')
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'parses text with spaces and punctuation' do
|
20
|
+
result = parser.text.parse('some text in the tags')
|
21
|
+
expect(result).to eq('some text in the tags')
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'stops at angle brackets' do
|
25
|
+
result = parser.text.parse('text')
|
26
|
+
expect(result).to eq('text')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#tag method' do
|
31
|
+
it 'parses opening tags' do
|
32
|
+
result = parser.tag(close: false).parse('<hello>')
|
33
|
+
expect(result).to parse_as({ name: 'hello' })
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'parses closing tags' do
|
37
|
+
result = parser.tag(close: true).parse('</hello>')
|
38
|
+
expect(result).to parse_as({ name: 'hello' })
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'parses single letter tags' do
|
42
|
+
result = parser.tag(close: false).parse('<a>')
|
43
|
+
expect(result).to parse_as({ name: 'a' })
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'parses multi-letter tags' do
|
47
|
+
result = parser.tag(close: false).parse('<body>')
|
48
|
+
expect(result).to parse_as({ name: 'body' })
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'parses mixed case tags' do
|
52
|
+
result = parser.tag(close: false).parse('<MyTag>')
|
53
|
+
expect(result).to parse_as({ name: 'MyTag' })
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'parses closing tags with mixed case' do
|
57
|
+
result = parser.tag(close: true).parse('</MyTag>')
|
58
|
+
expect(result).to parse_as({ name: 'MyTag' })
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#document (root)' do
|
63
|
+
it 'parses simple text documents' do
|
64
|
+
result = parser.parse('hello world')
|
65
|
+
expect(result).to eq('hello world')
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'parses empty documents' do
|
69
|
+
result = parser.parse('')
|
70
|
+
expect(result).to eq('')
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'parses simple tag pairs with text' do
|
74
|
+
result = parser.parse('<a>text</a>')
|
75
|
+
expected = {
|
76
|
+
o: { name: 'a' },
|
77
|
+
i: 'text',
|
78
|
+
c: { name: 'a' }
|
79
|
+
}
|
80
|
+
expect(result).to parse_as(expected)
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'parses nested tags' do
|
84
|
+
result = parser.parse('<a><b>text</b></a>')
|
85
|
+
expected = {
|
86
|
+
o: { name: 'a' },
|
87
|
+
i: {
|
88
|
+
o: { name: 'b' },
|
89
|
+
i: 'text',
|
90
|
+
c: { name: 'b' }
|
91
|
+
},
|
92
|
+
c: { name: 'a' }
|
93
|
+
}
|
94
|
+
expect(result).to parse_as(expected)
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'parses the main example: <a><b>some text in the tags</b></a>' do
|
98
|
+
result = parser.parse('<a><b>some text in the tags</b></a>')
|
99
|
+
expected = {
|
100
|
+
o: { name: 'a' },
|
101
|
+
i: {
|
102
|
+
o: { name: 'b' },
|
103
|
+
i: 'some text in the tags',
|
104
|
+
c: { name: 'b' }
|
105
|
+
},
|
106
|
+
c: { name: 'a' }
|
107
|
+
}
|
108
|
+
expect(result).to parse_as(expected)
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'parses mismatched tags (parser allows this)' do
|
112
|
+
result = parser.parse('<b><b>some text in the tags</b></a>')
|
113
|
+
expected = {
|
114
|
+
o: { name: 'b' },
|
115
|
+
i: {
|
116
|
+
o: { name: 'b' },
|
117
|
+
i: 'some text in the tags',
|
118
|
+
c: { name: 'b' }
|
119
|
+
},
|
120
|
+
c: { name: 'a' }
|
121
|
+
}
|
122
|
+
expect(result).to parse_as(expected)
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'parses tags with empty content' do
|
126
|
+
result = parser.parse('<tag></tag>')
|
127
|
+
expected = {
|
128
|
+
o: { name: 'tag' },
|
129
|
+
i: [],
|
130
|
+
c: { name: 'tag' }
|
131
|
+
}
|
132
|
+
expect(result).to parse_as(expected)
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'parses multiple levels of nesting' do
|
136
|
+
result = parser.parse('<a><b><c>deep</c></b></a>')
|
137
|
+
expected = {
|
138
|
+
o: { name: 'a' },
|
139
|
+
i: {
|
140
|
+
o: { name: 'b' },
|
141
|
+
i: {
|
142
|
+
o: { name: 'c' },
|
143
|
+
i: 'deep',
|
144
|
+
c: { name: 'c' }
|
145
|
+
},
|
146
|
+
c: { name: 'b' }
|
147
|
+
},
|
148
|
+
c: { name: 'a' }
|
149
|
+
}
|
150
|
+
expect(result).to parse_as(expected)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
describe 'check function' do
|
156
|
+
it 'validates matching tag pairs' do
|
157
|
+
result = check('<a><b>some text in the tags</b></a>')
|
158
|
+
expect(result).to eq('verified')
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'handles mismatched tags by showing the structure' do
|
162
|
+
result = check('<b><b>some text in the tags</b></a>')
|
163
|
+
expected = {
|
164
|
+
o: { name: 'b' },
|
165
|
+
i: 'verified',
|
166
|
+
c: { name: 'a' }
|
167
|
+
}
|
168
|
+
expect(result).to eq(expected)
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'validates simple tag pairs' do
|
172
|
+
result = check('<tag>content</tag>')
|
173
|
+
expect(result).to eq('verified')
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'validates nested matching tags' do
|
177
|
+
result = check('<outer><inner>text</inner></outer>')
|
178
|
+
expect(result).to eq('verified')
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'shows structure for partially matching tags' do
|
182
|
+
result = check('<a><b>text</b></c>')
|
183
|
+
expected = {
|
184
|
+
o: { name: 'a' },
|
185
|
+
i: 'verified',
|
186
|
+
c: { name: 'c' }
|
187
|
+
}
|
188
|
+
expect(result).to eq(expected)
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'handles empty tags' do
|
192
|
+
result = check('<empty></empty>')
|
193
|
+
# Empty content results in an array, which doesn't match the transform rule
|
194
|
+
expected = {
|
195
|
+
o: { name: 'empty' },
|
196
|
+
i: [],
|
197
|
+
c: { name: 'empty' }
|
198
|
+
}
|
199
|
+
expect(result).to eq(expected)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
describe 'integration test' do
|
204
|
+
it 'processes the first example correctly: <a><b>some text in the tags</b></a>' do
|
205
|
+
# This should validate to "verified"
|
206
|
+
result = check('<a><b>some text in the tags</b></a>')
|
207
|
+
expect(result).to eq('verified')
|
208
|
+
end
|
209
|
+
|
210
|
+
it 'processes the second example correctly: <b><b>some text in the tags</b></a>' do
|
211
|
+
# This should show the mismatched structure
|
212
|
+
result = check('<b><b>some text in the tags</b></a>')
|
213
|
+
expected = {
|
214
|
+
o: { name: 'b' },
|
215
|
+
i: 'verified',
|
216
|
+
c: { name: 'a' }
|
217
|
+
}
|
218
|
+
expect(result).to eq(expected)
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'produces the expected outputs from the example file' do
|
222
|
+
# First example should verify
|
223
|
+
result1 = check('<a><b>some text in the tags</b></a>')
|
224
|
+
expect(result1).to eq('verified')
|
225
|
+
|
226
|
+
# Second example should show mismatch structure
|
227
|
+
result2 = check('<b><b>some text in the tags</b></a>')
|
228
|
+
expected2 = {
|
229
|
+
o: { name: 'b' },
|
230
|
+
i: 'verified',
|
231
|
+
c: { name: 'a' }
|
232
|
+
}
|
233
|
+
expect(result2).to eq(expected2)
|
234
|
+
end
|
235
|
+
|
236
|
+
it 'demonstrates the validation concept' do
|
237
|
+
# Valid XML reduces to "verified"
|
238
|
+
valid_xml = '<root><child>content</child></root>'
|
239
|
+
expect(check(valid_xml)).to eq('verified')
|
240
|
+
|
241
|
+
# Invalid XML shows the structure with mismatches
|
242
|
+
invalid_xml = '<root><child>content</wrong></root>'
|
243
|
+
result = check(invalid_xml)
|
244
|
+
expect(result).to be_a(Hash)
|
245
|
+
expect(result).to have_key(:o)
|
246
|
+
expect(result).to have_key(:i)
|
247
|
+
expect(result).to have_key(:c)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|