ruby-marc-spec 0.1.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/.github/workflows/build.yml +18 -0
- data/.gitignore +388 -0
- data/.gitmodules +3 -0
- data/.idea/codeStyles/codeStyleConfig.xml +5 -0
- data/.idea/go.imports.xml +6 -0
- data/.idea/inspectionProfiles/Project_Default.xml +23 -0
- data/.idea/marc_spec.iml +102 -0
- data/.idea/misc.xml +6 -0
- data/.idea/modules.xml +8 -0
- data/.idea/templateLanguages.xml +6 -0
- data/.idea/vcs.xml +7 -0
- data/.rubocop.yml +269 -0
- data/.ruby-version +1 -0
- data/.simplecov +8 -0
- data/CHANGES.md +3 -0
- data/Gemfile +6 -0
- data/LICENSE.md +21 -0
- data/README.md +172 -0
- data/Rakefile +20 -0
- data/lib/.rubocop.yml +5 -0
- data/lib/marc/spec/module_info.rb +14 -0
- data/lib/marc/spec/parsing/closed_int_range.rb +28 -0
- data/lib/marc/spec/parsing/closed_lc_alpha_range.rb +28 -0
- data/lib/marc/spec/parsing/parser.rb +213 -0
- data/lib/marc/spec/parsing.rb +1 -0
- data/lib/marc/spec/queries/al_num_range.rb +105 -0
- data/lib/marc/spec/queries/applicable.rb +18 -0
- data/lib/marc/spec/queries/character_spec.rb +81 -0
- data/lib/marc/spec/queries/comparison_string.rb +45 -0
- data/lib/marc/spec/queries/condition.rb +133 -0
- data/lib/marc/spec/queries/condition_context.rb +49 -0
- data/lib/marc/spec/queries/dsl.rb +80 -0
- data/lib/marc/spec/queries/indicator_value.rb +77 -0
- data/lib/marc/spec/queries/operator.rb +129 -0
- data/lib/marc/spec/queries/part.rb +63 -0
- data/lib/marc/spec/queries/position.rb +59 -0
- data/lib/marc/spec/queries/position_or_range.rb +27 -0
- data/lib/marc/spec/queries/query.rb +94 -0
- data/lib/marc/spec/queries/query_executor.rb +52 -0
- data/lib/marc/spec/queries/selector.rb +12 -0
- data/lib/marc/spec/queries/subfield.rb +88 -0
- data/lib/marc/spec/queries/subfield_value.rb +63 -0
- data/lib/marc/spec/queries/tag.rb +107 -0
- data/lib/marc/spec/queries/transform.rb +154 -0
- data/lib/marc/spec/queries.rb +1 -0
- data/lib/marc/spec.rb +32 -0
- data/rakelib/.rubocop.yml +19 -0
- data/rakelib/bundle.rake +8 -0
- data/rakelib/coverage.rake +11 -0
- data/rakelib/gem.rake +54 -0
- data/rakelib/parser_specs/formatter.rb +31 -0
- data/rakelib/parser_specs/parser_specs.rb.txt.erb +35 -0
- data/rakelib/parser_specs/rule.rb +95 -0
- data/rakelib/parser_specs/suite.rb +91 -0
- data/rakelib/parser_specs/test.rb +97 -0
- data/rakelib/parser_specs.rb +1 -0
- data/rakelib/rubocop.rake +18 -0
- data/rakelib/spec.rake +27 -0
- data/ruby-marc-spec.gemspec +42 -0
- data/spec/.rubocop.yml +46 -0
- data/spec/README.md +16 -0
- data/spec/data/b23161018-sru.xml +182 -0
- data/spec/data/sandburg.xml +82 -0
- data/spec/generated/char_indicator_spec.rb +174 -0
- data/spec/generated/char_spec.rb +113 -0
- data/spec/generated/comparison_string_spec.rb +74 -0
- data/spec/generated/field_tag_spec.rb +156 -0
- data/spec/generated/index_char_spec.rb +669 -0
- data/spec/generated/index_indicator_spec.rb +174 -0
- data/spec/generated/index_spec.rb +113 -0
- data/spec/generated/index_sub_spec_spec.rb +1087 -0
- data/spec/generated/indicators_spec.rb +75 -0
- data/spec/generated/position_or_range_spec.rb +110 -0
- data/spec/generated/sub_spec_spec.rb +208 -0
- data/spec/generated/sub_spec_sub_spec_spec.rb +1829 -0
- data/spec/generated/subfield_char_spec.rb +405 -0
- data/spec/generated/subfield_range_range_spec.rb +48 -0
- data/spec/generated/subfield_range_spec.rb +87 -0
- data/spec/generated/subfield_range_sub_spec_spec.rb +214 -0
- data/spec/generated/subfield_tag_range_spec.rb +477 -0
- data/spec/generated/subfield_tag_sub_spec_spec.rb +3216 -0
- data/spec/generated/subfield_tag_tag_spec.rb +5592 -0
- data/spec/marc/spec/parsing/closed_int_range_spec.rb +49 -0
- data/spec/marc/spec/parsing/closed_lc_alpha_range_spec.rb +49 -0
- data/spec/marc/spec/parsing/parser_spec.rb +545 -0
- data/spec/marc/spec/queries/al_num_range_spec.rb +114 -0
- data/spec/marc/spec/queries/character_spec_spec.rb +28 -0
- data/spec/marc/spec/queries/comparison_string_spec.rb +28 -0
- data/spec/marc/spec/queries/indicator_value_spec.rb +28 -0
- data/spec/marc/spec/queries/query_spec.rb +200 -0
- data/spec/marc/spec/queries/subfield_spec.rb +92 -0
- data/spec/marc/spec/queries/subfield_value_spec.rb +31 -0
- data/spec/marc/spec/queries/tag_spec.rb +144 -0
- data/spec/marc/spec/queries/transform_spec.rb +459 -0
- data/spec/marc_spec_spec.rb +247 -0
- data/spec/scratch_spec.rb +112 -0
- data/spec/spec_helper.rb +23 -0
- metadata +341 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'parslet/rig/rspec'
|
3
|
+
|
4
|
+
module MARC::Spec
|
5
|
+
module Parsing
|
6
|
+
describe ClosedIntRange do
|
7
|
+
attr_reader :range
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
@range = ClosedIntRange.new
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'parses a valid range' do
|
14
|
+
valid_ranges = %w[
|
15
|
+
0-1
|
16
|
+
1-2
|
17
|
+
12-345
|
18
|
+
67890-123456
|
19
|
+
]
|
20
|
+
aggregate_failures 'valid ranges' do
|
21
|
+
valid_ranges.each do |r|
|
22
|
+
expect(range).to parse(r)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'does not parse an invalid range' do
|
28
|
+
invalid_ranges = %w[
|
29
|
+
1-0
|
30
|
+
2-1
|
31
|
+
345-12
|
32
|
+
123456-67890
|
33
|
+
]
|
34
|
+
aggregate_failures 'invalid ranges' do
|
35
|
+
invalid_ranges.each do |r|
|
36
|
+
expect(range).not_to parse(r)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe :to_s do
|
42
|
+
it 'accepts a precedece argument' do
|
43
|
+
prec = Parslet::Atoms::Precedence::OUTER
|
44
|
+
expect(range.to_s(prec)).to eq('ClosedIntRange')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'parslet/rig/rspec'
|
3
|
+
|
4
|
+
module MARC::Spec
|
5
|
+
module Parsing
|
6
|
+
describe ClosedLcAlphaRange do
|
7
|
+
attr_reader :range
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
@range = ClosedLcAlphaRange.new
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'parses a valid range' do
|
14
|
+
valid_ranges = %w[
|
15
|
+
a-b
|
16
|
+
c-d
|
17
|
+
e-f
|
18
|
+
g-z
|
19
|
+
]
|
20
|
+
aggregate_failures 'valid ranges' do
|
21
|
+
valid_ranges.each do |r|
|
22
|
+
expect(range).to parse(r)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'does not parse an invalid range' do
|
28
|
+
invalid_ranges = %w[
|
29
|
+
z-a
|
30
|
+
b-a
|
31
|
+
d-c
|
32
|
+
x-f
|
33
|
+
]
|
34
|
+
aggregate_failures 'invalid ranges' do
|
35
|
+
invalid_ranges.each do |r|
|
36
|
+
expect(range).not_to parse(r)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe :to_s do
|
42
|
+
it 'accepts a precedece argument' do
|
43
|
+
prec = Parslet::Atoms::Precedence::OUTER
|
44
|
+
expect(range.to_s(prec)).to eq('ClosedLcAlphaRange')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,545 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'parslet/rig/rspec'
|
3
|
+
|
4
|
+
# noinspection RubyResolve
|
5
|
+
module MARC::Spec
|
6
|
+
module Parsing
|
7
|
+
include MARC::Spec::Queries::Part
|
8
|
+
|
9
|
+
describe Parser do
|
10
|
+
let(:parser) { Parser.new }
|
11
|
+
let(:tags) { %w[245 2.. 24. .45 ..5 ... LDR] }
|
12
|
+
let(:positions) { %w[0 3 5] }
|
13
|
+
let(:pos_ranges) { [%w[1 3], %w[1 #], %w[# 1], %w[2 4], %w[# #]] }
|
14
|
+
let(:codes) { %w[b 2 $ \\ { }] }
|
15
|
+
let(:code_ranges) { [%w[a c], %w[1 3]] }
|
16
|
+
let(:inds) { %w[1 2] }
|
17
|
+
|
18
|
+
let(:r) { Parslet::ErrorReporter::Deepest.new }
|
19
|
+
|
20
|
+
# TODO: clean this up
|
21
|
+
# before(:all) do
|
22
|
+
# @all_parses = {}
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# after(:all) do
|
26
|
+
# parse_list = @all_parses.map do |val, parse_tree|
|
27
|
+
# [val.inspect, parse_tree.inspect].join(' => ')
|
28
|
+
# end
|
29
|
+
# parse_list.sort!
|
30
|
+
# parse_list.uniq!
|
31
|
+
# puts "{\n#{parse_list.join(",\n")}\n}"
|
32
|
+
# end
|
33
|
+
|
34
|
+
def parse_with(rule, value)
|
35
|
+
rule.parse(value).tap do |result|
|
36
|
+
# @all_parses[value] = result
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe :field_tag do
|
41
|
+
let(:rule) { parser.field_tag }
|
42
|
+
|
43
|
+
it 'parses tags' do
|
44
|
+
aggregate_failures do
|
45
|
+
tags.each do |tag|
|
46
|
+
expect(rule).to parse(tag)
|
47
|
+
result = parse_with(rule, tag)
|
48
|
+
expect(result).to eq(tag)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe :position do
|
55
|
+
let(:rule) { parser.position }
|
56
|
+
|
57
|
+
it 'parses positions' do
|
58
|
+
aggregate_failures do
|
59
|
+
%w[0 7 17 317].each do |pos|
|
60
|
+
expect(rule).to parse(pos, reporter: r)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe :position_or_range do
|
67
|
+
let(:rule) { parser.position_or_range }
|
68
|
+
|
69
|
+
it 'parses positions' do
|
70
|
+
aggregate_failures do
|
71
|
+
positions.each do |pos|
|
72
|
+
expect(rule).to parse(pos, reporter: r)
|
73
|
+
result = parse_with(rule, pos)
|
74
|
+
expect(result[:pos]).to eq(pos)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'parses ranges' do
|
80
|
+
aggregate_failures do
|
81
|
+
pos_ranges.each do |from, to|
|
82
|
+
val = "#{from}-#{to}"
|
83
|
+
expect(rule).to parse(val, reporter: r)
|
84
|
+
result = parse_with(rule, val)
|
85
|
+
expect(result[:from]).to eq(from == '#' ? nil : from)
|
86
|
+
expect(result[:to]).to eq(to == '#' ? nil : to)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe :character_spec do
|
93
|
+
let(:rule) { parser.character_spec }
|
94
|
+
|
95
|
+
it 'parses positions' do
|
96
|
+
aggregate_failures do
|
97
|
+
positions.each do |pos|
|
98
|
+
val = "/#{pos}"
|
99
|
+
expect(rule).to parse(val, reporter: r)
|
100
|
+
result = parse_with(rule, val)
|
101
|
+
character_spec = result[:character_spec]
|
102
|
+
expect(character_spec[:pos]).to eq(pos)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'parses ranges' do
|
108
|
+
aggregate_failures do
|
109
|
+
pos_ranges.each do |from, to|
|
110
|
+
val = "/#{from}-#{to}"
|
111
|
+
expect(rule).to parse(val, reporter: r)
|
112
|
+
result = parse_with(rule, val)
|
113
|
+
character_spec = result[:character_spec]
|
114
|
+
expect(character_spec[:from]).to eq(from == '#' ? nil : from)
|
115
|
+
expect(character_spec[:to]).to eq(to == '#' ? nil : to)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe :field_spec do
|
122
|
+
let(:rule) { parser.field_spec }
|
123
|
+
|
124
|
+
it 'parses tags' do
|
125
|
+
aggregate_failures do
|
126
|
+
tags.each do |tag|
|
127
|
+
expect(rule).to parse(tag)
|
128
|
+
result = parse_with(rule, tag)
|
129
|
+
expect(result[:tag]).to eq(tag)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
describe 'with substrings' do
|
135
|
+
it 'parses positions' do
|
136
|
+
aggregate_failures do
|
137
|
+
tags.each do |tag|
|
138
|
+
positions.each do |pos|
|
139
|
+
val = "#{tag}/#{pos}"
|
140
|
+
expect(rule).to parse(val, reporter: r)
|
141
|
+
result = parse_with(rule, val)
|
142
|
+
expect(result[:tag]).to eq(tag)
|
143
|
+
selector = result[:selector]
|
144
|
+
character_spec = selector[:character_spec]
|
145
|
+
expect(character_spec[:pos]).to eq(pos)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'parses ranges' do
|
152
|
+
aggregate_failures do
|
153
|
+
tags.each do |tag|
|
154
|
+
pos_ranges.each do |from, to|
|
155
|
+
val = "#{tag}/#{from}-#{to}"
|
156
|
+
expect(rule).to parse(val, reporter: r)
|
157
|
+
result = parse_with(rule, val)
|
158
|
+
expect(result[:tag]).to eq(tag)
|
159
|
+
selector = result[:selector]
|
160
|
+
character_spec = selector[:character_spec]
|
161
|
+
expect(character_spec[:from]).to eq(from == '#' ? nil : from)
|
162
|
+
expect(character_spec[:to]).to eq(to == '#' ? nil : to)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
describe 'with indices' do
|
170
|
+
it 'parses positions' do
|
171
|
+
aggregate_failures do
|
172
|
+
tags.each do |tag|
|
173
|
+
positions.each do |pos_index|
|
174
|
+
val = "#{tag}[#{pos_index}]"
|
175
|
+
expect(rule).to parse(val, reporter: r)
|
176
|
+
result = parse_with(rule, val)
|
177
|
+
expect(result[:tag]).to eq(tag)
|
178
|
+
index = result[:index]
|
179
|
+
expect(index[:pos]).to eq(pos_index)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'parses ranges' do
|
186
|
+
aggregate_failures do
|
187
|
+
tags.each do |tag|
|
188
|
+
pos_ranges.each do |from_index, to_index|
|
189
|
+
val = "#{tag}[#{from_index}-#{to_index}]"
|
190
|
+
expect(rule).to parse(val, reporter: r)
|
191
|
+
result = parse_with(rule, val)
|
192
|
+
expect(result[:tag]).to eq(tag)
|
193
|
+
index = result[:index]
|
194
|
+
expect(index[:from]).to eq(from_index == '#' ? nil : from_index)
|
195
|
+
expect(index[:to]).to eq(to_index == '#' ? nil : to_index)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
describe :subfield_code do
|
204
|
+
let(:rule) { parser.subfield_code }
|
205
|
+
|
206
|
+
it 'parses codes' do
|
207
|
+
aggregate_failures do
|
208
|
+
codes.each do |code|
|
209
|
+
val = "$#{code}"
|
210
|
+
expect(rule).to parse(val, reporter: r)
|
211
|
+
expect(parse_with(rule, val)).to eq(code)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
describe :subfield_spec do
|
218
|
+
let(:rule) { parser.subfield_spec }
|
219
|
+
|
220
|
+
it 'parses codes' do
|
221
|
+
aggregate_failures do
|
222
|
+
tags.each do |tag|
|
223
|
+
codes.each do |code|
|
224
|
+
val = "#{tag}$#{code}"
|
225
|
+
expect(rule).to parse(val, reporter: r)
|
226
|
+
result = parse_with(rule, val)
|
227
|
+
expect(result[:tag]).to eq(tag)
|
228
|
+
selector = result[:selector]
|
229
|
+
expect(selector).to eq({ code: code })
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
it 'parses code ranges' do
|
236
|
+
aggregate_failures do
|
237
|
+
tags.each do |tag|
|
238
|
+
code_ranges.each do |from, to|
|
239
|
+
val = "#{tag}$#{from}-#{to}"
|
240
|
+
expect(rule).to parse(val, reporter: r)
|
241
|
+
result = parse_with(rule, val)
|
242
|
+
expect(result[:tag]).to eq(tag)
|
243
|
+
|
244
|
+
selector = result[:selector]
|
245
|
+
expect(selector).not_to be_nil
|
246
|
+
|
247
|
+
code_range = selector[:code]
|
248
|
+
expect(code_range[:from]).to eq(from)
|
249
|
+
expect(code_range[:to]).to eq(to)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
it 'parses codes with indices' do
|
256
|
+
aggregate_failures do
|
257
|
+
tags.each do |tag|
|
258
|
+
positions.each do |pos_index|
|
259
|
+
codes.each do |code|
|
260
|
+
val = "#{tag}[#{pos_index}]$#{code}"
|
261
|
+
expect(rule).to parse(val, reporter: r)
|
262
|
+
result = parse_with(rule, val)
|
263
|
+
expect(result[:tag]).to eq(tag)
|
264
|
+
|
265
|
+
index = result[:index]
|
266
|
+
expect(index[:pos]).to eq(pos_index)
|
267
|
+
|
268
|
+
selector = result[:selector]
|
269
|
+
expect(selector).not_to be_nil
|
270
|
+
expect(selector[:code]).to eq(code)
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
it 'parses code ranges with indices' do
|
278
|
+
pos_ranges.each do |from_index, to_index|
|
279
|
+
aggregate_failures do
|
280
|
+
tags.each do |tag|
|
281
|
+
code_ranges.each do |from, to|
|
282
|
+
val = "#{tag}[#{from_index}-#{to_index}]$#{from}-#{to}"
|
283
|
+
expect(rule).to parse(val, reporter: r)
|
284
|
+
result = parse_with(rule, val)
|
285
|
+
expect(result[:tag]).to eq(tag)
|
286
|
+
|
287
|
+
index = result[:index]
|
288
|
+
expect(index[:from]).to eq(from_index == '#' ? nil : from_index)
|
289
|
+
expect(index[:to]).to eq(to_index == '#' ? nil : to_index)
|
290
|
+
|
291
|
+
selector = result[:selector]
|
292
|
+
expect(selector).not_to be_nil
|
293
|
+
|
294
|
+
code_range = selector[:code]
|
295
|
+
expect(code_range[:from]).to eq(from)
|
296
|
+
expect(code_range[:to]).to eq(to)
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
describe :indicator_spec do
|
305
|
+
let(:rule) { parser.indicator_spec }
|
306
|
+
|
307
|
+
it 'parses indicators with plain tags' do
|
308
|
+
aggregate_failures do
|
309
|
+
tags.each do |tag|
|
310
|
+
inds.each do |ind|
|
311
|
+
val = "#{tag}^#{ind}"
|
312
|
+
expect(rule).to parse(val)
|
313
|
+
result = parse_with(rule, val)
|
314
|
+
expect(result[:tag]).to eq(tag)
|
315
|
+
selector = result[:selector]
|
316
|
+
expect(selector[:ind]).to eq(ind)
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
it 'parses indicators with position-indexed tags' do
|
323
|
+
aggregate_failures do
|
324
|
+
tags.each do |tag|
|
325
|
+
positions.each do |pos_index|
|
326
|
+
inds.each do |ind|
|
327
|
+
val = "#{tag}[#{pos_index}]^#{ind}"
|
328
|
+
result = parse_with(rule, val)
|
329
|
+
expect(result[:tag]).to eq(tag)
|
330
|
+
selector = result[:selector]
|
331
|
+
expect(selector[:ind]).to eq(ind)
|
332
|
+
index = result[:index]
|
333
|
+
expect(index[:pos]).to eq(pos_index)
|
334
|
+
end
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
it 'parses indicators with range-indexed tags' do
|
341
|
+
aggregate_failures do
|
342
|
+
tags.each do |tag|
|
343
|
+
pos_ranges.each do |from_index, to_index|
|
344
|
+
inds.each do |ind|
|
345
|
+
val = "#{tag}[#{from_index}-#{to_index}]^#{ind}"
|
346
|
+
result = parse_with(rule, val)
|
347
|
+
expect(result[:tag]).to eq(tag)
|
348
|
+
selector = result[:selector]
|
349
|
+
expect(selector[:ind]).to eq(ind)
|
350
|
+
index = result[:index]
|
351
|
+
expect(index[:from]).to eq(from_index == '#' ? nil : from_index)
|
352
|
+
expect(index[:to]).to eq(to_index == '#' ? nil : to_index)
|
353
|
+
end
|
354
|
+
end
|
355
|
+
end
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
end
|
360
|
+
|
361
|
+
describe :comparison_string do
|
362
|
+
let(:rule) { parser._comparison_string }
|
363
|
+
|
364
|
+
it 'parses a comparison string' do
|
365
|
+
expecteds = {
|
366
|
+
'\\svalue' => '\\svalue',
|
367
|
+
'\\\\svalue' => '\\svalue',
|
368
|
+
'\\value' => 'value',
|
369
|
+
'\\value\\!' => 'value\\!',
|
370
|
+
'\\!value' => '!value',
|
371
|
+
'\\\\!value' => '\\!value',
|
372
|
+
'\\help\\sI\\sam\\strapped\\sin\\sa\\sunit\\stest\\!\\sso\\sam\\sI' =>
|
373
|
+
'help\\sI\\sam\\strapped\\sin\\sa\\sunit\\stest\\!\\sso\\sam\\sI',
|
374
|
+
'\\a\\{b\\}\\$1\\\\23\\=\\~\\|\\?' => 'a\\{b\\}\\$1\\\\23\\=\\~\\|\\?'
|
375
|
+
}
|
376
|
+
aggregate_failures do
|
377
|
+
expecteds.each do |val, expected|
|
378
|
+
expect(rule).to parse(val, reporter: r)
|
379
|
+
result = parse_with(rule, val)
|
380
|
+
expect(result).to be_a(Hash)
|
381
|
+
next unless result.is_a?(Hash)
|
382
|
+
|
383
|
+
cstr = result[:comparison_string]
|
384
|
+
expect(cstr).to eq(expected)
|
385
|
+
end
|
386
|
+
end
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
390
|
+
describe :sub_spec do
|
391
|
+
let(:rule) { parser.sub_spec }
|
392
|
+
|
393
|
+
it 'parses a condition' do
|
394
|
+
expecteds = {
|
395
|
+
'{/#=\\/}' => {
|
396
|
+
left: {
|
397
|
+
selector: {
|
398
|
+
character_spec: {
|
399
|
+
pos: '#'
|
400
|
+
}
|
401
|
+
}
|
402
|
+
},
|
403
|
+
operator: '=',
|
404
|
+
right: {
|
405
|
+
comparison_string: '/'
|
406
|
+
}
|
407
|
+
}
|
408
|
+
}
|
409
|
+
aggregate_failures do
|
410
|
+
expecteds.each do |val, expected|
|
411
|
+
expect(rule).to parse(val, reporter: r)
|
412
|
+
result = parse_with(rule, val)
|
413
|
+
expect(result).to eq(expected)
|
414
|
+
end
|
415
|
+
end
|
416
|
+
end
|
417
|
+
end
|
418
|
+
|
419
|
+
describe 'with multiple subfields' do
|
420
|
+
it 'parses subfield code lists' do
|
421
|
+
aggregate_failures do
|
422
|
+
tags.each do |tag|
|
423
|
+
code_list = codes.map { |c| "$#{c}" }.join
|
424
|
+
val = "#{tag}#{code_list}"
|
425
|
+
expect(parser).to parse(val, reporter: r)
|
426
|
+
result = parse_with(parser, val)
|
427
|
+
|
428
|
+
expect(result[:tag]).to eq(tag)
|
429
|
+
|
430
|
+
subqueries = result[:subqueries]
|
431
|
+
expect(subqueries.size).to eq(codes.size)
|
432
|
+
subqueries.each_with_index do |subquery, i|
|
433
|
+
selector = subquery[:selector]
|
434
|
+
subfield = selector
|
435
|
+
expect(subfield[:code]).to eq(codes[i])
|
436
|
+
end
|
437
|
+
end
|
438
|
+
end
|
439
|
+
end
|
440
|
+
|
441
|
+
it 'handles indices' do
|
442
|
+
aggregate_failures do
|
443
|
+
tags.each do |tag|
|
444
|
+
pos_ranges.each do |from_index, to_index|
|
445
|
+
code_list = codes.map { |c| "$#{c}" }.join
|
446
|
+
val = "#{tag}[#{from_index}-#{to_index}]#{code_list}"
|
447
|
+
expect(parser).to parse(val, reporter: r)
|
448
|
+
result = parse_with(parser, val)
|
449
|
+
|
450
|
+
expect(result[:tag]).to eq(tag)
|
451
|
+
index = result[:index]
|
452
|
+
expect(index[:from]).to eq(from_index == '#' ? nil : from_index)
|
453
|
+
expect(index[:to]).to eq(to_index == '#' ? nil : to_index)
|
454
|
+
|
455
|
+
subqueries = result[:subqueries]
|
456
|
+
expect(subqueries.size).to eq(codes.size)
|
457
|
+
subqueries.each_with_index do |subquery, i|
|
458
|
+
selector = subquery[:selector]
|
459
|
+
subfield = selector
|
460
|
+
expect(subfield[:code]).to eq(codes[i])
|
461
|
+
end
|
462
|
+
end
|
463
|
+
end
|
464
|
+
end
|
465
|
+
end
|
466
|
+
|
467
|
+
it 'parses subfield code lists with conditions' do
|
468
|
+
aggregate_failures do
|
469
|
+
tags.each do |tag|
|
470
|
+
pos_ranges.each do |from_index, to_index|
|
471
|
+
code_list = codes.map.with_index { |c, i| "$#{c}{~\\ok#{i}}" }.join
|
472
|
+
val = "#{tag}[#{from_index}-#{to_index}]#{code_list}"
|
473
|
+
expect(parser).to parse(val, reporter: r)
|
474
|
+
result = parse_with(parser, val)
|
475
|
+
|
476
|
+
expect(result[:tag]).to eq(tag)
|
477
|
+
index = result[:index]
|
478
|
+
expect(index[:from]).to eq(from_index == '#' ? nil : from_index)
|
479
|
+
expect(index[:to]).to eq(to_index == '#' ? nil : to_index)
|
480
|
+
|
481
|
+
subqueries = result[:subqueries]
|
482
|
+
expect(subqueries.size).to eq(codes.size)
|
483
|
+
subqueries.each_with_index do |subquery, i|
|
484
|
+
selector = subquery[:selector]
|
485
|
+
subfield = selector
|
486
|
+
expect(subfield[:code]).to eq(codes[i])
|
487
|
+
condition = subquery[:condition]
|
488
|
+
expect(condition[:operator]).to eq('~')
|
489
|
+
right_operand = condition[:right]
|
490
|
+
expect(right_operand[:comparison_string]).to eq("ok#{i}")
|
491
|
+
end
|
492
|
+
end
|
493
|
+
end
|
494
|
+
end
|
495
|
+
end
|
496
|
+
|
497
|
+
it 'handles complex combinations of subfields and subspecs' do
|
498
|
+
val = '880$a{?$f}$b$c$e{$f=\\q}'
|
499
|
+
|
500
|
+
expect(parser).to parse(val, reporter: r)
|
501
|
+
result = parse_with(parser, val)
|
502
|
+
expect(result[:tag]).to eq('880')
|
503
|
+
|
504
|
+
subqueries = result[:subqueries]
|
505
|
+
expect(subqueries.size).to eq(4)
|
506
|
+
|
507
|
+
expect(subqueries[0][:selector]).to eq({ code: 'a' })
|
508
|
+
condition0 = subqueries[0][:condition]
|
509
|
+
expect(condition0[:operator]).to eq('?')
|
510
|
+
expect(condition0[:right][:selector]).to eq({ code: 'f' })
|
511
|
+
|
512
|
+
expect(subqueries[1][:selector]).to eq({ code: 'b' })
|
513
|
+
|
514
|
+
expect(subqueries[2][:selector]).to eq({ code: 'c' })
|
515
|
+
|
516
|
+
expect(subqueries[3][:selector]).to eq({ code: 'e' })
|
517
|
+
condition3 = subqueries[3][:condition]
|
518
|
+
expect(condition3[:left][:selector]).to eq({ code: 'f' })
|
519
|
+
expect(condition3[:operator]).to eq('=')
|
520
|
+
expect(condition3[:right]).to eq({ comparison_string: 'q' })
|
521
|
+
end
|
522
|
+
end
|
523
|
+
|
524
|
+
describe 'indicators with conditions' do
|
525
|
+
it 'handles plain tags' do
|
526
|
+
aggregate_failures do
|
527
|
+
tags.each do |tag|
|
528
|
+
inds.each do |ind|
|
529
|
+
val = "#{tag}^#{ind}{=\\a}"
|
530
|
+
expect(parser).to parse(val)
|
531
|
+
result = parse_with(parser, val)
|
532
|
+
expect(result[:tag]).to eq(tag)
|
533
|
+
selector = result[:selector]
|
534
|
+
expect(selector[:ind]).to eq(ind)
|
535
|
+
condition = result[:condition]
|
536
|
+
expect(condition[:operator]).to eq('=')
|
537
|
+
expect(condition[:right][:comparison_string]).to eq('a')
|
538
|
+
end
|
539
|
+
end
|
540
|
+
end
|
541
|
+
end
|
542
|
+
end
|
543
|
+
end
|
544
|
+
end
|
545
|
+
end
|