line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package MARC::Spec::Parser;
|
2
|
|
|
|
|
|
|
|
3
|
13
|
|
|
13
|
|
13489
|
use Carp qw(croak);
|
|
13
|
|
|
|
|
13
|
|
|
13
|
|
|
|
|
518
|
|
4
|
13
|
|
|
13
|
|
5479
|
use Const::Fast;
|
|
13
|
|
|
|
|
14540
|
|
|
13
|
|
|
|
|
848
|
|
5
|
13
|
|
|
13
|
|
1716
|
use Moo;
|
|
13
|
|
|
|
|
8019
|
|
|
13
|
|
|
|
|
739
|
|
6
|
13
|
|
|
13
|
|
3597
|
use MARC::Spec;
|
|
13
|
|
|
|
|
17
|
|
|
13
|
|
|
|
|
222
|
|
7
|
13
|
|
|
13
|
|
4107
|
use MARC::Spec::Field;
|
|
13
|
|
|
|
|
26
|
|
|
13
|
|
|
|
|
607
|
|
8
|
|
|
|
|
|
|
require MARC::Spec::Subfield;
|
9
|
|
|
|
|
|
|
require MARC::Spec::Comparisonstring;
|
10
|
|
|
|
|
|
|
require MARC::Spec::Subspec;
|
11
|
13
|
|
|
13
|
|
70
|
use namespace::clean;
|
|
13
|
|
|
|
|
15
|
|
|
13
|
|
|
|
|
68
|
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
our $VERSION = '0.1.4';
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
has spec => (
|
16
|
|
|
|
|
|
|
is => 'rw',
|
17
|
|
|
|
|
|
|
required => 1
|
18
|
|
|
|
|
|
|
);
|
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
has marcspec => (
|
21
|
|
|
|
|
|
|
is => 'rwp'
|
22
|
|
|
|
|
|
|
);
|
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
const my $FIELDTAG => q{^(?(?:[a-z0-9\.]{3,3}|[A-Z0-9\.]{3,3}|[0-9\.]{3,3}))?};
|
25
|
|
|
|
|
|
|
const my $POSITIONORRANGE => q{(?:(?:(?:[0-9]+|#)\-(?:[0-9]+|#))|(?:[0-9]+|#))};
|
26
|
|
|
|
|
|
|
const my $INDEX => qq{(?:\\[(?$POSITIONORRANGE)\\])?};
|
27
|
|
|
|
|
|
|
const my $CHARPOS => qq{\\/(?$POSITIONORRANGE)};
|
28
|
|
|
|
|
|
|
const my $INDICATORS => q{_(?(?:[_a-z0-9][_a-z0-9]{0,1}))};
|
29
|
|
|
|
|
|
|
const my $SUBSPECS => q{(?(?:\\{.+?(?
|
30
|
|
|
|
|
|
|
const my $SUBFIELDS => q{(?\$.+)?};
|
31
|
|
|
|
|
|
|
const my $FIELD => qr/(?(?:$FIELDTAG$INDEX(?:$CHARPOS|$INDICATORS)?$SUBSPECS$SUBFIELDS))/s;
|
32
|
|
|
|
|
|
|
const my $SUBFIELDRANGE => q{(?(?:[0-9a-z]\-[0-9a-z]))};
|
33
|
|
|
|
|
|
|
const my $SUBFIELDTAG => q{(?[\!-\?\[-\\{\\}-~])};
|
34
|
|
|
|
|
|
|
const my $SUBFIELD => qr/(?\$(?:$SUBFIELDRANGE|$SUBFIELDTAG)$INDEX(?:$CHARPOS)?$SUBSPECS)/s;
|
35
|
|
|
|
|
|
|
const my $LEFTSUBTERM => q{^(?(?:\\\(?:(?<=\\\)[\!\=\~\?]|[^\!\=\~\?])+)|(?:(?<=\$)[\!\=\~\?]|[^\!\=\~\?])+)?};
|
36
|
|
|
|
|
|
|
const my $OPERATOR => q{(?\!\=|\!\~|\=|\~|\!|\?)};
|
37
|
|
|
|
|
|
|
const my $SUBTERMS => qq{(?:$LEFTSUBTERM$OPERATOR)?(?.+)}.q{$};
|
38
|
|
|
|
|
|
|
const my $SUBSPEC => qr/(?:\{(.+?)\})/s;
|
39
|
|
|
|
|
|
|
const my $UNESCAPED => qr/(?
|
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
const my $MIN_LENGTH_FIELD => 3;
|
42
|
|
|
|
|
|
|
const my $MIN_LENGTH_SUBFIELD => 2;
|
43
|
|
|
|
|
|
|
const my $NO_LENGTH => -1;
|
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
my %cache;
|
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
sub BUILDARGS {
|
48
|
47
|
|
|
47
|
0
|
17004
|
my ($class, @args) = @_;
|
49
|
47
|
50
|
|
|
|
120
|
if (@args % 2 == 1) { unshift @args, "spec" }
|
|
47
|
|
|
|
|
75
|
|
50
|
47
|
|
|
|
|
637
|
return { @args };
|
51
|
|
|
|
|
|
|
}
|
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
sub BUILD {
|
54
|
47
|
|
|
47
|
0
|
455
|
my ($self) = @_;
|
55
|
47
|
|
|
|
|
88
|
my $field = $self->_match_field();
|
56
|
37
|
|
|
|
|
418
|
my $ms = MARC::Spec->new($field);
|
57
|
37
|
100
|
|
|
|
279
|
if($self->{_parsed}->{subfields}) {
|
58
|
23
|
|
|
|
|
58
|
my $subfields = $self->_match_subfields();
|
59
|
22
|
|
|
|
|
60
|
$ms->add_subfields($subfields);
|
60
|
|
|
|
|
|
|
}
|
61
|
36
|
|
|
|
|
456
|
$self->_set_marcspec($ms);
|
62
|
|
|
|
|
|
|
}
|
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
sub _match_field {
|
65
|
47
|
|
|
47
|
|
45
|
my ($self) = @_;
|
66
|
|
|
|
|
|
|
|
67
|
47
|
|
|
|
|
188
|
_do_checks($self->spec, $MIN_LENGTH_FIELD);
|
68
|
|
|
|
|
|
|
|
69
|
44
|
|
|
|
|
292
|
$self->spec =~ $FIELD;
|
70
|
|
|
|
|
|
|
|
71
|
13
|
|
|
13
|
|
13722
|
%{$self->{_parsed}} = %+;
|
|
13
|
|
|
|
|
3761
|
|
|
13
|
|
|
|
|
16392
|
|
|
44
|
|
|
|
|
405
|
|
|
44
|
|
|
|
|
293
|
|
72
|
|
|
|
|
|
|
|
73
|
44
|
100
|
|
|
|
146
|
if(!$self->{_parsed}->{tag}) {
|
74
|
2
|
|
|
|
|
5
|
_throw("For fieldtag only '.', digits and lowercase alphabetic or digits and upper case alphabetics characters are allowed.", $self->spec);
|
75
|
|
|
|
|
|
|
}
|
76
|
|
|
|
|
|
|
|
77
|
42
|
100
|
|
|
|
113
|
if( length $self->{_parsed}->{field} != length $self->spec ) {
|
78
|
3
|
|
|
|
|
6
|
_throw('Detected useless data fragment or invalid field spec.', $self->spec);
|
79
|
|
|
|
|
|
|
}
|
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
# create a new Field
|
82
|
39
|
|
|
|
|
502
|
my $field = MARC::Spec::Field->new($self->{_parsed}->{tag});
|
83
|
|
|
|
|
|
|
|
84
|
39
|
100
|
|
|
|
298
|
if(defined $self->{_parsed}->{indicators}) {
|
|
|
100
|
|
|
|
|
|
85
|
1
|
|
|
|
|
3
|
my $ind1 = substr $self->{_parsed}->{indicators}, 0, 1;
|
86
|
1
|
50
|
|
|
|
14
|
if('_' ne $ind1) { $field->indicator1($ind1) }
|
|
1
|
|
|
|
|
5
|
|
87
|
|
|
|
|
|
|
|
88
|
1
|
50
|
|
|
|
11
|
if(2 == length($self->{_parsed}->{indicators})) {
|
89
|
1
|
|
|
|
|
3
|
my $ind2 = substr $self->{_parsed}->{indicators}, 1, 1;
|
90
|
1
|
50
|
|
|
|
3
|
if('_' ne $ind2) { $field->indicator2($ind2) }
|
|
1
|
|
|
|
|
2
|
|
91
|
|
|
|
|
|
|
}
|
92
|
|
|
|
|
|
|
} elsif(defined $self->{_parsed}->{charpos}) {
|
93
|
7
|
|
|
|
|
30
|
$field->set_char_start_end($self->{_parsed}->{charpos});
|
94
|
|
|
|
|
|
|
}
|
95
|
|
|
|
|
|
|
|
96
|
38
|
100
|
|
|
|
76
|
if(defined $self->{_parsed}->{index}) {
|
97
|
9
|
|
|
|
|
47
|
$field->set_index_start_end($self->{_parsed}->{index});
|
98
|
|
|
|
|
|
|
}
|
99
|
|
|
|
|
|
|
|
100
|
38
|
100
|
100
|
|
|
528
|
if(defined $field->char_start && defined $self->{_parsed}->{subfields}) {
|
101
|
1
|
|
|
|
|
10
|
_throw("Either characterSpec for field or subfields are allowed.", $self->spec);
|
102
|
|
|
|
|
|
|
}
|
103
|
|
|
|
|
|
|
|
104
|
37
|
|
|
|
|
714
|
$self->{field_base} = $field->base;
|
105
|
|
|
|
|
|
|
|
106
|
37
|
100
|
|
|
|
123
|
if($self->{_parsed}->{subspecs}) {
|
107
|
3
|
|
|
|
|
12
|
my $field_subspecs = $self->_match_subspecs($self->{_parsed}->{subspecs});
|
108
|
3
|
|
|
|
|
76
|
$self->_populate_subspecs($field, $field_subspecs, [$self->{field_base}]);
|
109
|
|
|
|
|
|
|
}
|
110
|
37
|
|
|
|
|
61
|
return $field;
|
111
|
|
|
|
|
|
|
}
|
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
sub _populate_subspecs {
|
114
|
33
|
|
|
33
|
|
44
|
my ($self, $spec, $subspecs, $base) = @_;
|
115
|
33
|
|
|
|
|
27
|
foreach my $subspec (@{$subspecs}) {
|
|
33
|
|
|
|
|
43
|
|
116
|
|
|
|
|
|
|
# check if array length is above 1
|
117
|
62
|
100
|
|
|
|
160
|
if(1 < scalar @{$subspec}) {
|
|
62
|
|
|
|
|
104
|
|
118
|
|
|
|
|
|
|
# alternatives to array (OR)
|
119
|
29
|
|
|
|
|
27
|
my @or = ();
|
120
|
29
|
|
|
|
|
19
|
foreach my $or_subspec (@{$subspec}) {
|
|
29
|
|
|
|
|
33
|
|
121
|
58
|
|
|
|
|
87
|
push @or, $self->_match_subterms($or_subspec, $base);
|
122
|
|
|
|
|
|
|
}
|
123
|
29
|
|
|
|
|
110
|
$spec->add_subspecs([\@or]);
|
124
|
|
|
|
|
|
|
}
|
125
|
|
|
|
|
|
|
else {
|
126
|
33
|
|
|
|
|
59
|
$spec->add_subspec( $self->_match_subterms($subspec->[0], $base ) );
|
127
|
|
|
|
|
|
|
}
|
128
|
|
|
|
|
|
|
}
|
129
|
|
|
|
|
|
|
}
|
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
sub _match_subfields {
|
132
|
23
|
|
|
23
|
|
28
|
my ($self) = @_;
|
133
|
|
|
|
|
|
|
|
134
|
23
|
|
|
|
|
54
|
_do_checks($self->{_parsed}->{subfields}, $MIN_LENGTH_SUBFIELD);
|
135
|
|
|
|
|
|
|
|
136
|
23
|
|
|
|
|
35
|
my $subfields = [];
|
137
|
23
|
|
|
|
|
22
|
my $i = 0;
|
138
|
23
|
|
|
|
|
170
|
while($self->{_parsed}->{subfields} =~ /$SUBFIELD/g) {
|
139
|
26
|
100
|
|
|
|
120
|
if(defined $+{range}) {
|
140
|
1
|
|
|
|
|
4
|
my $from = substr $+{range},0,1;
|
141
|
1
|
|
|
|
|
4
|
my $to = substr $+{range},2,1;
|
142
|
1
|
|
|
|
|
3
|
for my $code ( $from .. $to) {
|
143
|
26
|
|
|
|
|
18
|
push @{$subfields}, $self->_create_subfield($code,%+);
|
|
26
|
|
|
|
|
180
|
|
144
|
|
|
|
|
|
|
}
|
145
|
|
|
|
|
|
|
} else {
|
146
|
25
|
|
|
|
|
21
|
push @{$subfields}, $self->_create_subfield(undef,%+);
|
|
25
|
|
|
|
|
163
|
|
147
|
|
|
|
|
|
|
}
|
148
|
26
|
|
|
|
|
126
|
$i++;
|
149
|
|
|
|
|
|
|
}
|
150
|
|
|
|
|
|
|
|
151
|
23
|
100
|
|
|
|
45
|
if(0 == $i) {
|
152
|
1
|
|
|
|
|
2
|
_throw("Invalid subfield spec detected.", $self->{_parsed}->{subfields});
|
153
|
|
|
|
|
|
|
}
|
154
|
|
|
|
|
|
|
|
155
|
22
|
|
|
|
|
33
|
return $subfields;
|
156
|
|
|
|
|
|
|
}
|
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
sub _create_subfield {
|
159
|
51
|
|
|
51
|
|
247
|
my ($self,$code,%args) = @_;
|
160
|
|
|
|
|
|
|
# create a new Subfield
|
161
|
51
|
|
66
|
|
|
798
|
my $subfield = MARC::Spec::Subfield->new($code // $args{code});
|
162
|
|
|
|
|
|
|
|
163
|
51
|
100
|
|
|
|
221
|
if(defined $args{index}) {
|
164
|
4
|
|
|
|
|
20
|
$subfield->set_index_start_end($args{index});
|
165
|
|
|
|
|
|
|
}
|
166
|
|
|
|
|
|
|
|
167
|
51
|
100
|
|
|
|
79
|
if(defined $args{charpos}) {
|
168
|
1
|
|
|
|
|
11
|
$subfield->set_char_start_end($args{charpos});
|
169
|
|
|
|
|
|
|
}
|
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
# handle subspecs
|
172
|
51
|
100
|
|
|
|
84
|
if(defined $args{subspecs}) {
|
173
|
30
|
|
|
|
|
55
|
my $subfield_subspecs = $self->_match_subspecs($args{subspecs});
|
174
|
30
|
|
|
|
|
427
|
$self->_populate_subspecs($subfield, $subfield_subspecs, [$self->{field_base}, $subfield->base]);
|
175
|
|
|
|
|
|
|
}
|
176
|
51
|
|
|
|
|
291
|
return $subfield;
|
177
|
|
|
|
|
|
|
}
|
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
sub _match_subspecs {
|
180
|
33
|
|
|
33
|
|
40
|
my ($self, $subspecs) = @_;
|
181
|
33
|
|
|
|
|
33
|
my @subspecs;
|
182
|
|
|
|
|
|
|
|
183
|
33
|
|
|
|
|
191
|
foreach ($subspecs =~ /$SUBSPEC/g) {
|
184
|
62
|
|
|
|
|
202
|
push @subspecs, [split /(?
|
185
|
|
|
|
|
|
|
}
|
186
|
33
|
|
|
|
|
49
|
return \@subspecs;
|
187
|
|
|
|
|
|
|
}
|
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
sub _match_subterms {
|
190
|
91
|
|
|
91
|
|
100
|
my ($self,$subTerms,$context) = @_;
|
191
|
|
|
|
|
|
|
|
192
|
91
|
50
|
|
|
|
322
|
if($subTerms =~ $UNESCAPED) {
|
193
|
0
|
|
|
|
|
0
|
_throw("Unescaped character detected.", $subTerms);
|
194
|
|
|
|
|
|
|
}
|
195
|
|
|
|
|
|
|
|
196
|
91
|
50
|
|
|
|
916
|
if($subTerms !~ /$SUBTERMS/sg) {
|
197
|
0
|
|
|
|
|
0
|
_throw("Assuming invalid spec.", $subTerms);
|
198
|
|
|
|
|
|
|
}
|
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
# create a new Subspec
|
201
|
91
|
|
|
|
|
1228
|
my $subSpec = MARC::Spec::Subspec->new;
|
202
|
|
|
|
|
|
|
|
203
|
91
|
|
|
|
|
250
|
foreach my $side (('left', 'right')) {
|
204
|
182
|
100
|
|
|
|
1036
|
if(defined $+{$side}) {
|
|
|
50
|
|
|
|
|
|
205
|
175
|
100
|
|
|
|
462
|
if('\\' ne substr $+{$side},0,1) {
|
206
|
91
|
|
|
|
|
183
|
my $spec = _spec_context($+{$side},$context);
|
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
# this prevents the spec parsed again
|
209
|
91
|
100
|
|
|
|
191
|
if($cache{$spec}) {
|
210
|
79
|
|
|
|
|
1152
|
$subSpec->$side( $cache{$spec} );
|
211
|
|
|
|
|
|
|
} else {
|
212
|
12
|
|
|
|
|
180
|
$subSpec->$side( MARC::Spec::Parser->new($spec)->marcspec );
|
213
|
|
|
|
|
|
|
|
214
|
12
|
|
|
|
|
228
|
$cache{$spec} = $subSpec->$side;
|
215
|
|
|
|
|
|
|
}
|
216
|
|
|
|
|
|
|
} else {
|
217
|
84
|
|
|
|
|
1173
|
$subSpec->$side( MARC::Spec::Comparisonstring->new(substr $+{$side},1) );
|
218
|
|
|
|
|
|
|
}
|
219
|
|
|
|
|
|
|
} elsif($side eq 'left') {
|
220
|
7
|
|
|
|
|
9
|
my $spec = _spec_context(@{$context}[$#{$context}],$context);
|
|
7
|
|
|
|
|
17
|
|
|
7
|
|
|
|
|
6
|
|
221
|
7
|
100
|
|
|
|
29
|
if($cache{$spec}) {
|
222
|
2
|
|
|
|
|
27
|
$subSpec->left( $cache{$spec} );
|
223
|
|
|
|
|
|
|
} else {
|
224
|
5
|
|
|
|
|
84
|
$subSpec->left( MARC::Spec::Parser->new($spec)->marcspec );
|
225
|
5
|
|
|
|
|
96
|
$cache{$spec} = $subSpec->left;
|
226
|
|
|
|
|
|
|
}
|
227
|
|
|
|
|
|
|
} else {
|
228
|
0
|
|
|
|
|
0
|
_throw("Right hand subTerm is missing.", $subTerms);
|
229
|
|
|
|
|
|
|
}
|
230
|
|
|
|
|
|
|
}
|
231
|
|
|
|
|
|
|
|
232
|
91
|
100
|
|
|
|
789
|
if(defined $+{operator}) { $subSpec->operator( $+{operator} )}
|
|
84
|
|
|
|
|
238
|
|
233
|
|
|
|
|
|
|
|
234
|
91
|
|
|
|
|
266
|
return $subSpec;
|
235
|
|
|
|
|
|
|
}
|
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
sub _spec_context {
|
238
|
98
|
|
|
98
|
|
197
|
my ($spec, $context) = @_;
|
239
|
98
|
|
|
|
|
82
|
my $fieldContext = @{$context}[0];
|
|
98
|
|
|
|
|
119
|
|
240
|
98
|
|
|
|
|
75
|
my $fullcontext = join '', @{$context};
|
|
98
|
|
|
|
|
130
|
|
241
|
|
|
|
|
|
|
|
242
|
98
|
100
|
|
|
|
161
|
if($spec eq $fullcontext) { return $spec }
|
|
2
|
|
|
|
|
4
|
|
243
|
|
|
|
|
|
|
|
244
|
96
|
|
|
|
|
103
|
my $firstChar = substr $spec,0,1;
|
245
|
96
|
50
|
|
|
|
125
|
if($firstChar eq '_') {
|
246
|
0
|
|
|
|
|
0
|
my $refPos = index $fullcontext, $firstChar;
|
247
|
|
|
|
|
|
|
|
248
|
0
|
0
|
|
|
|
0
|
if(0 <= $refPos) {
|
249
|
0
|
0
|
|
|
|
0
|
if('$' ne substr $fullcontext,$refPos - 1,1) {
|
250
|
0
|
|
|
|
|
0
|
return substr($fullcontext,0,$refPos).$spec;
|
251
|
|
|
|
|
|
|
}
|
252
|
|
|
|
|
|
|
}
|
253
|
0
|
|
|
|
|
0
|
return $fullcontext.$spec;
|
254
|
|
|
|
|
|
|
}
|
255
|
|
|
|
|
|
|
|
256
|
96
|
100
|
|
|
|
132
|
if($firstChar eq '$') { return $fieldContext.$spec }
|
|
9
|
|
|
|
|
17
|
|
257
|
|
|
|
|
|
|
|
258
|
87
|
50
|
|
|
|
228
|
if($firstChar =~ /\[|\//) {
|
259
|
0
|
|
|
|
|
0
|
my $refPos = rindex $fullcontext, $firstChar;
|
260
|
|
|
|
|
|
|
|
261
|
0
|
0
|
|
|
|
0
|
if(0 <= $refPos) {
|
262
|
0
|
0
|
|
|
|
0
|
if('$' ne substr $fullcontext,$refPos - 1,1) {
|
263
|
0
|
|
|
|
|
0
|
return substr($fullcontext,0,$refPos).$spec;
|
264
|
|
|
|
|
|
|
}
|
265
|
|
|
|
|
|
|
}
|
266
|
0
|
|
|
|
|
0
|
return $fullcontext.$spec;
|
267
|
|
|
|
|
|
|
}
|
268
|
|
|
|
|
|
|
|
269
|
87
|
|
|
|
|
117
|
return $spec;
|
270
|
|
|
|
|
|
|
}
|
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
sub _do_checks {
|
273
|
70
|
|
|
70
|
|
78
|
my ($spec, $min_length) = @_;
|
274
|
|
|
|
|
|
|
|
275
|
70
|
100
|
|
|
|
160
|
if(ref \$spec ne 'SCALAR') {
|
276
|
1
|
|
|
|
|
3
|
_throw("Argument must be of type SCALAR.", ref \$spec);
|
277
|
|
|
|
|
|
|
}
|
278
|
|
|
|
|
|
|
|
279
|
69
|
100
|
|
|
|
179
|
if($spec =~ /\s/s) {
|
280
|
1
|
|
|
|
|
2
|
_throw("Whitespaces are not allowed.", $spec);
|
281
|
|
|
|
|
|
|
}
|
282
|
|
|
|
|
|
|
|
283
|
68
|
100
|
|
|
|
116
|
if($min_length > length $spec) {
|
284
|
1
|
|
|
|
|
6
|
_throw("Spec must be at least ".$min_length." chracters long.", $spec);
|
285
|
|
|
|
|
|
|
}
|
286
|
|
|
|
|
|
|
|
287
|
67
|
|
|
|
|
66
|
return;
|
288
|
|
|
|
|
|
|
}
|
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
sub _throw {
|
291
|
10
|
|
|
10
|
|
14
|
my ($message, $hint) = @_;
|
292
|
10
|
|
|
|
|
87
|
croak 'MARCspec Parser exception. '.$message.' Tried to parse: '.$hint;
|
293
|
|
|
|
|
|
|
}
|
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
1;
|
296
|
|
|
|
|
|
|
__END__
|