File Coverage

blib/lib/YAML/Loader.pm
Criterion Covered Total %
statement 452 487 92.8
branch 231 268 86.1
condition 93 109 85.3
subroutine 28 28 100.0
pod 0 1 0.0
total 804 893 90.0


line stmt bran cond sub pod time code
1             package YAML::Loader;
2              
3 36     36   1762 use YAML::Mo;
  36         62  
  36         221  
4             extends 'YAML::Loader::Base';
5              
6 36     36   13719 use YAML::Loader::Base;
  36         97  
  36         1065  
7 36     36   7302 use YAML::Types;
  36         78  
  36         886  
8 36     36   203 use YAML::Node;
  36         69  
  36         1778  
9              
10             # Context constants
11 36     36   203 use constant LEAF => 1;
  36         70  
  36         1980  
12 36     36   241 use constant COLLECTION => 2;
  36         108  
  36         1916  
13 36     36   204 use constant VALUE => "\x07YAML\x07VALUE\x07";
  36         59  
  36         1675  
14 36     36   188 use constant COMMENT => "\x07YAML\x07COMMENT\x07";
  36         74  
  36         70239  
15              
16             # Common YAML character sets
17             my $ESCAPE_CHAR = '[\\x00-\\x08\\x0b-\\x0d\\x0e-\\x1f]';
18             my $FOLD_CHAR = '>';
19             my $LIT_CHAR = '|';
20             my $LIT_CHAR_RX = "\\$LIT_CHAR";
21              
22             sub load {
23 318     318 0 499 my $self = shift;
24 318   50     1142 $self->stream($_[0] || '');
25 318         710 return $self->_parse();
26             }
27              
28             # Top level function for parsing. Parse each document in order and
29             # handle processing for YAML headers.
30             sub _parse {
31 318     318   458 my $self = shift;
32 318         459 my (%directives, $preface);
33 318         962 $self->{stream} =~ s|\015\012|\012|g;
34 318         706 $self->{stream} =~ s|\015|\012|g;
35 318         877 $self->line(0);
36 318 100       619 $self->die('YAML_PARSE_ERR_BAD_CHARS')
37             if $self->stream =~ /$ESCAPE_CHAR/;
38 317         3652 $self->{stream} =~ s/(.)\n\Z/$1/s;
39 317         863 $self->lines([split /\x0a/, $self->stream, -1]);
40 317         964 $self->line(1);
41             # Throw away any comments or blanks before the header (or start of
42             # content for headerless streams)
43 317         781 $self->_parse_throwaway_comments();
44 317         897 $self->document(0);
45 317         858 $self->documents([]);
46 317         927 $self->zero_indent([]);
47             # Add an "assumed" header if there is no header and the stream is
48             # not empty (after initial throwaways).
49 317 100       680 if (not $self->eos) {
50 279 100       554 if ($self->lines->[0] !~ /^---(\s|$)/) {
51 36         53 unshift @{$self->lines}, '---';
  36         70  
52 36         60 $self->{line}--;
53             }
54             }
55              
56             # Main Loop. Parse out all the top level nodes and return them.
57 317         707 while (not $self->eos) {
58 317         945 $self->anchor2node({});
59 317         492 $self->{document}++;
60 317         752 $self->done(0);
61 317         814 $self->level(0);
62 317         692 $self->offset->[0] = -1;
63              
64 317 50       620 if ($self->lines->[0] =~ /^---\s*(.*)$/) {
65 317         74974 my @words = split /\s/, $1;
66 317         552 %directives = ();
67 317         799 while (@words) {
68 126 100       538 if ($words[0] =~ /^#(\w+):(\S.*)$/) {
    50          
69 17         65 my ($key, $value) = ($1, $2);
70 17         29 shift(@words);
71 17 100       45 if (defined $directives{$key}) {
72 2         7 $self->warn('YAML_PARSE_WARN_MULTIPLE_DIRECTIVES',
73             $key, $self->document);
74 2         944 next;
75             }
76 15         45 $directives{$key} = $value;
77             }
78             elsif ($words[0] eq '') {
79 0         0 shift @words;
80             }
81             else {
82 109         201 last;
83             }
84             }
85 317         14410 $self->preface(join ' ', @words);
86             }
87             else {
88 0         0 $self->die('YAML_PARSE_ERR_NO_SEPARATOR');
89             }
90              
91 317 50       767 if (not $self->done) {
92 317         654 $self->_parse_next_line(COLLECTION);
93             }
94 315 100       704 if ($self->done) {
95 59         124 $self->{indent} = -1;
96 59         145 $self->content('');
97             }
98              
99 315   100     1399 $directives{YAML} ||= '1.0';
100 315   100     1184 $directives{TAB} ||= 'NONE';
101             ($self->{major_version}, $self->{minor_version}) =
102 315         1422 split /\./, $directives{YAML}, 2;
103             $self->die('YAML_PARSE_ERR_BAD_MAJOR_VERSION', $directives{YAML})
104 315 100       927 if $self->major_version ne '1';
105             $self->warn('YAML_PARSE_WARN_BAD_MINOR_VERSION', $directives{YAML})
106 314 100       819 if $self->minor_version ne '0';
107             $self->die('Unrecognized TAB policy')
108 314 100       1918 unless $directives{TAB} =~ /^(NONE|\d+)(:HARD)?$/;
109              
110 313         476 push @{$self->documents}, $self->_parse_node();
  313         677  
111             }
112 284 100       710 return wantarray ? @{$self->documents} : $self->documents->[-1];
  151         364  
113             }
114              
115             # This function is the dispatcher for parsing each node. Every node
116             # recurses back through here. (Inlines are an exception as they have
117             # their own sub-parser.)
118             sub _parse_node {
119 2020     2020   2596 my $self = shift;
120 2020         3114 my $preface = $self->preface;
121 2020         4189 $self->preface('');
122 2020         4389 my ($node, $type, $indicator, $chomp, $parsed_inline) = ('') x 5;
123 2020         3300 my ($anchor, $alias, $explicit, $implicit) = ('') x 4;
124 2020         3312 ($anchor, $alias, $explicit, $implicit, $preface) =
125             $self->_parse_qualifiers($preface);
126 2011 100       3646 if ($anchor) {
127 20         104 $self->anchor2node->{$anchor} = CORE::bless [], 'YAML-anchor2node';
128             }
129 2011         4163 $self->inline('');
130 2011         3737 while (length $preface) {
131 1346 100       5127 if ($preface =~ s/^($FOLD_CHAR|$LIT_CHAR_RX)//) {
132 65         158 $indicator = $1;
133 65 100       228 if ($preface =~ s/^([+-])[0-9]*//) {
    100          
134 23         51 $chomp = $1;
135             }
136             elsif ($preface =~ s/^[0-9]+([+-]?)//) {
137 6         11 $chomp = $1;
138             }
139 65 100       317 if ($preface =~ s/^(?:\s+#.*$|\s*)$//) {
140             }
141             else {
142 1         4 $self->die('YAML_PARSE_ERR_TEXT_AFTER_INDICATOR');
143             }
144             }
145             else {
146 1281         2830 $self->inline($preface);
147 1281         2886 $preface = '';
148             }
149             }
150 2010 100       4050 if ($alias) {
    100          
    100          
    100          
151             $self->die('YAML_PARSE_ERR_NO_ANCHOR', $alias)
152 21 100       76 unless defined $self->anchor2node->{$alias};
153 20 50       51 if (ref($self->anchor2node->{$alias}) ne 'YAML-anchor2node') {
154 20         41 $node = $self->anchor2node->{$alias};
155             }
156             else {
157 0         0 $node = do {my $sv = "*$alias"};
  0         0  
158 0         0 push @{$self->anchor2node->{$alias}}, [\$node, $self->line];
  0         0  
159             }
160             }
161             elsif (length $self->inline) {
162 1281         2438 $node = $self->_parse_inline(1, $implicit, $explicit);
163 1273         1841 $parsed_inline = 1;
164 1273 100       2213 if (length $self->inline) {
165 1         5 $self->die('YAML_PARSE_ERR_SINGLE_LINE');
166             }
167             }
168             elsif ($indicator eq $LIT_CHAR) {
169 44         99 $self->{level}++;
170 44         105 $node = $self->_parse_block($chomp);
171 44 50       96 $node = $self->_parse_implicit($node) if $implicit;
172 44         72 $self->{level}--;
173             }
174             elsif ($indicator eq $FOLD_CHAR) {
175 20         33 $self->{level}++;
176 20         54 $node = $self->_parse_unfold($chomp);
177 20 100       47 $node = $self->_parse_implicit($node) if $implicit;
178 19         31 $self->{level}--;
179             }
180             else {
181 644         947 $self->{level}++;
182 644   100     1132 $self->offset->[$self->level] ||= 0;
183 644 100       1156 if ($self->indent == $self->offset->[$self->level]) {
184 629 100       1017 if ($self->content =~ /^-( |$)/) {
    50          
    0          
185 155         423 $node = $self->_parse_seq($anchor);
186             }
187             elsif ($self->content =~ /(^\?|\:( |$))/) {
188 474         1090 $node = $self->_parse_mapping($anchor);
189             }
190             elsif ($preface =~ /^\s*$/) {
191 0         0 $node = $self->_parse_implicit('');
192             }
193             else {
194 0         0 $self->die('YAML_PARSE_ERR_BAD_NODE');
195             }
196             }
197             else {
198 15         24 $node = undef;
199             }
200 616         990 $self->{level}--;
201             }
202 1971         3820 $#{$self->offset} = $self->level;
  1971         2970  
203              
204 1971 100       3320 if ($explicit) {
205 84 100       279 $node = $self->_parse_explicit($node, $explicit) if !$parsed_inline;
206             }
207 1970 100       2855 if ($anchor) {
208 20 100       46 if (ref($self->anchor2node->{$anchor}) eq 'YAML-anchor2node') {
209             # XXX Can't remember what this code actually does
210 10         29 for my $ref (@{$self->anchor2node->{$anchor}}) {
  10         24  
211 0         0 ${$ref->[0]} = $node;
  0         0  
212 0         0 $self->warn('YAML_LOAD_WARN_UNRESOLVED_ALIAS',
213             $anchor, $ref->[1]);
214             }
215             }
216 20         44 $self->anchor2node->{$anchor} = $node;
217             }
218 1970         4466 return $node;
219             }
220              
221             # Preprocess the qualifiers that may be attached to any node.
222             sub _parse_qualifiers {
223 4777     4777   5742 my $self = shift;
224 4777         6211 my ($preface) = @_;
225 4777         7082 my ($anchor, $alias, $explicit, $implicit, $token) = ('') x 5;
226 4777         8964 $self->inline('');
227 4777         10574 while ($preface =~ /^[&*!]/) {
228 146 100       745 if ($preface =~ s/^\!(\S+)\s*//) {
    100          
    100          
    50          
229 90 100       209 $self->die('YAML_PARSE_ERR_MANY_EXPLICIT') if $explicit;
230 89         290 $explicit = $1;
231             }
232             elsif ($preface =~ s/^\!\s*//) {
233 5 100       20 $self->die('YAML_PARSE_ERR_MANY_IMPLICIT') if $implicit;
234 4         13 $implicit = 1;
235             }
236             elsif ($preface =~ s/^\&([^ ,:]*)\s*//) {
237 25         59 $token = $1;
238 25 100       94 $self->die('YAML_PARSE_ERR_BAD_ANCHOR')
239             unless $token =~ /^[a-zA-Z0-9_.\/-]+$/;
240 23 100       55 $self->die('YAML_PARSE_ERR_MANY_ANCHOR') if $anchor;
241 22 50       45 $self->die('YAML_PARSE_ERR_ANCHOR_ALIAS') if $alias;
242 22         59 $anchor = $token;
243             }
244             elsif ($preface =~ s/^\*([^ ,:]*)\s*//) {
245 26         58 $token = $1;
246 26 100       87 $self->die('YAML_PARSE_ERR_BAD_ALIAS')
247             unless $token =~ /^[a-zA-Z0-9_.\/-]+$/;
248 24 100       55 $self->die('YAML_PARSE_ERR_MANY_ALIAS') if $alias;
249 23 100       58 $self->die('YAML_PARSE_ERR_ANCHOR_ALIAS') if $anchor;
250 22         51 $alias = $token;
251             }
252             }
253 4768         13683 return ($anchor, $alias, $explicit, $implicit, $preface);
254             }
255              
256             # Morph a node to it's explicit type
257             sub _parse_explicit {
258 88     88   134 my $self = shift;
259 88         252 my ($node, $explicit) = @_;
260 88         129 my ($type, $class);
261 88 100       513 if ($explicit =~ /^\!?perl\/(hash|array|ref|scalar)(?:\:(\w(\w|\:\:)*)?)?$/) {
262 44   50     246 ($type, $class) = (($1 || ''), ($2 || ''));
      100        
263              
264             # FIXME # die unless uc($type) eq ref($node) ?
265              
266 44 100       110 if ( $type eq "ref" ) {
267             $self->die('YAML_LOAD_ERR_NO_DEFAULT_VALUE', 'XXX', $explicit)
268 22 100 66     123 unless exists $node->{VALUE()} and scalar(keys %$node) == 1;
269              
270 21         41 my $value = $node->{VALUE()};
271 21         35 $node = \$value;
272             }
273              
274 43 100 100     136 if ( $type eq "scalar" and length($class) and !ref($node) ) {
      66        
275 4         68 my $value = $node;
276 4         14 $node = \$value;
277             }
278              
279 43 100 100     145 if ( length($class) and $YAML::LoadBlessed ) {
280 15         44 CORE::bless($node, $class);
281             }
282              
283 43         93 return $node;
284             }
285 44 100 100     327 if ($explicit =~ m{^!?perl/(glob|regexp|code)(?:\:(\w(\w|\:\:)*)?)?$}) {
    100          
    100          
286 22   50     192 ($type, $class) = (($1 || ''), ($2 || ''));
      100        
287 22         63 my $type_class = "YAML::Type::$type";
288 36     36   296 no strict 'refs';
  36         78  
  36         145785  
289 22 50       193 if ($type_class->can('yaml_load')) {
290 22         81 return $type_class->yaml_load($node, $class, $self);
291             }
292             else {
293 0         0 $self->die('YAML_LOAD_ERR_NO_CONVERT', 'XXX', $explicit);
294             }
295             }
296             # This !perl/@Foo and !perl/$Foo are deprecated but still parsed
297             elsif ($YAML::TagClass->{$explicit} ||
298             $explicit =~ m{^perl/(\@|\$)?([a-zA-Z](\w|::)+)$}
299             ) {
300 15   66     67 $class = $YAML::TagClass->{$explicit} || $2;
301 15 100       145 if ($class->can('yaml_load')) {
    100          
302 4         22 require YAML::Node;
303 4         18 return $class->yaml_load(YAML::Node->new($node, $explicit));
304             }
305             elsif ($YAML::LoadBlessed) {
306 7 50       18 if (ref $node) {
307 7         33 return CORE::bless $node, $class;
308             }
309             else {
310 0         0 return CORE::bless \$node, $class;
311             }
312             }
313             else {
314 4         9 return $node;
315             }
316             }
317             elsif (ref $node) {
318 5         32 require YAML::Node;
319 5         30 return YAML::Node->new($node, $explicit);
320             }
321             else {
322             # XXX This is likely wrong. Failing test:
323             # --- !unknown 'scalar value'
324 2         5 return $node;
325             }
326             }
327              
328             # Parse a YAML mapping into a Perl hash
329             sub _parse_mapping {
330 513     513   628 my $self = shift;
331 513         767 my ($anchor) = @_;
332 513 100       1001 my $mapping = $self->preserve ? YAML::Node->new({}) : {};
333 513         1035 $self->anchor2node->{$anchor} = $mapping;
334 513         645 my $key;
335 513   100     834 while (not $self->done and $self->indent == $self->offset->[$self->level]) {
336             # If structured key:
337 1386 100       4596 if ($self->{content} =~ s/^\?\s*//) {
    100          
    50          
338 5         14 $self->preface($self->content);
339 5         16 $self->_parse_next_line(COLLECTION);
340 5         13 $key = $self->_parse_node();
341 5         13 $key = "$key";
342             }
343             # If "default" key (equals sign)
344             elsif ($self->{content} =~ s/^\=\s*(?=:)//) {
345 23         49 $key = VALUE;
346             }
347             # If "comment" key (slash slash)
348             elsif ($self->{content} =~ s/^\=\s*(?=:)//) {
349 0         0 $key = COMMENT;
350             }
351             # Regular scalar key:
352             else {
353 1358         2463 $self->inline($self->content);
354 1358         2320 $key = $self->_parse_inline();
355 1358         1844 $key = "$key";
356 1358         2188 $self->content($self->inline);
357 1358         2249 $self->inline('');
358             }
359              
360 1386 100       6311 unless ($self->{content} =~ s/^:(?:\s+#.*$|\s*)//) {
361 1         4 $self->die('YAML_LOAD_ERR_BAD_MAP_ELEMENT');
362             }
363 1385         2878 $self->preface($self->content);
364 1385         2557 my $level = $self->level;
365              
366             # we can get a zero indented sequence, possibly
367 1385         2221 my $zero_indent = $self->zero_indent;
368 1385         1893 $zero_indent->[ $level ] = 0;
369 1385         2544 $self->_parse_next_line(COLLECTION);
370 1382         2978 my $value = $self->_parse_node();
371 1379         2031 $#$zero_indent = $level;
372              
373 1379 100       2293 if (exists $mapping->{$key}) {
374 2         11 $self->warn('YAML_LOAD_WARN_DUPLICATE_KEY', $key);
375             }
376             else {
377 1377         3845 $mapping->{$key} = $value;
378             }
379             }
380 506         998 return $mapping;
381             }
382              
383             # Parse a YAML sequence into a Perl array
384             sub _parse_seq {
385 159     159   228 my $self = shift;
386 159         277 my ($anchor) = @_;
387 159         247 my $seq = [];
388 159         369 $self->anchor2node->{$anchor} = $seq;
389 159   100     345 while (not $self->done and $self->indent == $self->offset->[$self->level]) {
390 368 100       790 if ($self->content =~ /^-(?: (.*))?$/) {
391 365 100       1060 $self->preface(defined($1) ? $1 : '');
392             }
393             else {
394 3 100       9 if ($self->zero_indent->[ $self->level ]) {
395 2         3 last;
396             }
397 1         4 $self->die('YAML_LOAD_ERR_BAD_SEQ_ELEMENT');
398             }
399              
400             # Check whether the preface looks like a YAML mapping ("key: value").
401             # This is complicated because it has to account for the possibility
402             # that a key is a quoted string, which itself may contain escaped
403             # quotes.
404 365         759 my $preface = $self->preface;
405 365 100 66     2821 if ($preface =~ m/^ (\s*) ( - (?: \ .* | $ ) ) /x) {
    100 100        
      100        
406 4         10 $self->indent($self->offset->[$self->level] + 2 + length($1));
407 4         9 $self->content($2);
408 4         8 $self->level($self->level + 1);
409 4         6 $self->offset->[$self->level] = $self->indent;
410 4         10 $self->preface('');
411 4         12 push @$seq, $self->_parse_seq('');
412 4         6 $self->{level}--;
413 4         7 $#{$self->offset} = $self->level;
  4         8  
414             }
415             elsif (
416             $preface =~ /^ (\s*) ((') (?:''|[^'])*? ' \s* \: (?:\ |$).*) $/x or
417             $preface =~ /^ (\s*) ((") (?:\\\\|[^"])*? " \s* \: (?:\ |$).*) $/x or
418             $preface =~ /^ (\s*) (\?.*$)/x or
419             $preface =~ /^ (\s*) ([^'"\s:#&!\[\]\{\},*|>].*\:(\ .*|$))/x
420             ) {
421 39         100 $self->indent($self->offset->[$self->level] + 2 + length($1));
422 39         88 $self->content($2);
423 39         80 $self->level($self->level + 1);
424 39         77 $self->offset->[$self->level] = $self->indent;
425 39         90 $self->preface('');
426 39         94 push @$seq, $self->_parse_mapping('');
427 39         62 $self->{level}--;
428 39         72 $#{$self->offset} = $self->level;
  39         69  
429             }
430             else {
431 322         752 $self->_parse_next_line(COLLECTION);
432 320         871 push @$seq, $self->_parse_node();
433             }
434             }
435 138         326 return $seq;
436             }
437              
438             # Parse an inline value. Since YAML supports inline collections, this is
439             # the top level of a sub parsing.
440             sub _parse_inline {
441 2757     2757   3354 my $self = shift;
442 2757         4586 my ($top, $top_implicit, $top_explicit) = (@_, '', '', '');
443 2757         18798 $self->{inline} =~ s/^\s*(.*)\s*$/$1/; # OUCH - mugwump
444 2757         6239 my ($node, $anchor, $alias, $explicit, $implicit) = ('') x 5;
445 2757         5217 ($anchor, $alias, $explicit, $implicit, $self->{inline}) =
446             $self->_parse_qualifiers($self->inline);
447 2757 50       5150 if ($anchor) {
448 0         0 $self->anchor2node->{$anchor} = CORE::bless [], 'YAML-anchor2node';
449             }
450 2757   66     8400 $implicit ||= $top_implicit;
451 2757   100     7074 $explicit ||= $top_explicit;
452 2757         3928 ($top_implicit, $top_explicit) = ('', '');
453 2757 50       5266 if ($alias) {
    100          
    100          
    100          
    100          
454             $self->die('YAML_PARSE_ERR_NO_ANCHOR', $alias)
455 0 0       0 unless defined $self->anchor2node->{$alias};
456 0 0       0 if (ref($self->anchor2node->{$alias}) ne 'YAML-anchor2node') {
457 0         0 $node = $self->anchor2node->{$alias};
458             }
459             else {
460 0         0 $node = do {my $sv = "*$alias"};
  0         0  
461 0         0 push @{$self->anchor2node->{$alias}}, [\$node, $self->line];
  0         0  
462             }
463             }
464             elsif ($self->inline =~ /^\{/) {
465 27         88 $node = $self->_parse_inline_mapping($anchor);
466             }
467             elsif ($self->inline =~ /^\[/) {
468 32         96 $node = $self->_parse_inline_seq($anchor);
469             }
470             elsif ($self->inline =~ /^"/) {
471 27         90 $node = $self->_parse_inline_double_quoted();
472 25         106 $node = $self->_unescape($node);
473 25 100       87 $node = $self->_parse_implicit($node) if $implicit;
474             }
475             elsif ($self->inline =~ /^'/) {
476 56         161 $node = $self->_parse_inline_single_quoted();
477 54 50       145 $node = $self->_parse_implicit($node) if $implicit;
478             }
479             else {
480 2615 100       3548 if ($top) {
481 1174         1901 $node = $self->inline;
482 1174         1883 $self->inline('');
483             }
484             else {
485 1441         2169 $node = $self->_parse_inline_simple();
486             }
487 2614 100       5567 $node = $self->_parse_implicit($node) unless $explicit;
488              
489 2613 100 66     5320 if ($self->numify and defined $node and not ref $node and length $node
      66        
      33        
      66        
490             and $node =~ m/\A-?(?:0|[1-9][0-9]*)?(?:\.[0-9]*)?(?:[eE][+-]?[0-9]+)?\z/) {
491 3         9 $node += 0;
492             }
493             }
494 2748 100       5052 if ($explicit) {
495 30         172 $node = $self->_parse_explicit($node, $explicit);
496             }
497 2748 50       3755 if ($anchor) {
498 0 0       0 if (ref($self->anchor2node->{$anchor}) eq 'YAML-anchor2node') {
499 0         0 for my $ref (@{$self->anchor2node->{$anchor}}) {
  0         0  
500 0         0 ${$ref->[0]} = $node;
  0         0  
501 0         0 $self->warn('YAML_LOAD_WARN_UNRESOLVED_ALIAS',
502             $anchor, $ref->[1]);
503             }
504             }
505 0         0 $self->anchor2node->{$anchor} = $node;
506             }
507 2748         4687 return $node;
508             }
509              
510             # Parse the inline YAML mapping into a Perl hash
511             sub _parse_inline_mapping {
512 27     27   44 my $self = shift;
513 27         48 my ($anchor) = @_;
514 27         60 my $node = {};
515 27         72 $self->anchor2node->{$anchor} = $node;
516              
517             $self->die('YAML_PARSE_ERR_INLINE_MAP')
518 27 50       153 unless $self->{inline} =~ s/^\{\s*//;
519 27         130 while (not $self->{inline} =~ s/^\s*\}(\s+#.*$|\s*)//) {
520 30         100 my $key = $self->_parse_inline();
521             $self->die('YAML_PARSE_ERR_INLINE_MAP')
522 30 100       126 unless $self->{inline} =~ s/^\: \s*//;
523 29         75 my $value = $self->_parse_inline();
524 29 50       57 if (exists $node->{$key}) {
525 0         0 $self->warn('YAML_LOAD_WARN_DUPLICATE_KEY', $key);
526             }
527             else {
528 29         81 $node->{$key} = $value;
529             }
530 29 100       76 next if $self->inline =~ /^\s*\}/;
531             $self->die('YAML_PARSE_ERR_INLINE_MAP')
532 12 50       55 unless $self->{inline} =~ s/^\,\s*//;
533             }
534 26         137 return $node;
535             }
536              
537             # Parse the inline YAML sequence into a Perl array
538             sub _parse_inline_seq {
539 32     32   55 my $self = shift;
540 32         74 my ($anchor) = @_;
541 32         49 my $node = [];
542 32         87 $self->anchor2node->{$anchor} = $node;
543              
544             $self->die('YAML_PARSE_ERR_INLINE_SEQUENCE')
545 32 50       149 unless $self->{inline} =~ s/^\[\s*//;
546 32         153 while (not $self->{inline} =~ s/^\s*\](\s+#.*$|\s*)//) {
547 59         182 my $value = $self->_parse_inline();
548 58         161 push @$node, $value;
549 58 100       109 next if $self->inline =~ /^\s*\]/;
550             $self->die('YAML_PARSE_ERR_INLINE_SEQUENCE')
551 36 100       194 unless $self->{inline} =~ s/^\,\s*//;
552             }
553 30         75 return $node;
554             }
555              
556             # Parse the inline double quoted string.
557             sub _parse_inline_double_quoted {
558 27     27   47 my $self = shift;
559 27         69 my $inline = $self->inline;
560 27 50       1852 if ($inline =~ s/^"//) {
561 27         52 my $node = '';
562              
563 27         6998 while ($inline =~ s/^(\\.|[^"\\]+)//) {
564 160061         429609 my $capture = $1;
565 160061         354629 $capture =~ s/^\\"/"/;
566 160061         235451 $node .= $capture;
567 160061 100       12911012 last unless length $inline;
568             }
569 27 100       162 if ($inline =~ s/^"(?:\s+#.*|\s*)//) {
570 25         95 $self->inline($inline);
571 25         397 return $node;
572             }
573             }
574 2         10 $self->die('YAML_PARSE_ERR_BAD_DOUBLE');
575             }
576              
577              
578             # Parse the inline single quoted string.
579             sub _parse_inline_single_quoted {
580 56     56   99 my $self = shift;
581 56         125 my $inline = $self->inline;
582 56 50       255 if ($inline =~ s/^'//) {
583 56         94 my $node = '';
584 56         257 while ($inline =~ s/^(''|[^']+)//) {
585 52         123 my $capture = $1;
586 52         112 $capture =~ s/^''/'/;
587 52         91 $node .= $capture;
588 52 100       250 last unless length $inline;
589             }
590 56 100       251 if ($inline =~ s/^'(?:\s+#.*|\s*)//) {
591 54         169 $self->inline($inline);
592 54         187 return $node;
593             }
594             }
595 2         16 $self->die('YAML_PARSE_ERR_BAD_SINGLE');
596             }
597              
598             # Parse the inline unquoted string and do implicit typing.
599             sub _parse_inline_simple {
600 1441     1441   1631 my $self = shift;
601 1441         1463 my $value;
602 1441 100       2031 if ($self->inline =~ /^(|[^!@#%^&*].*?)(?=[\[\]\{\},]|, |: |- |:\s*$|$)/) {
603 1440         2721 $value = $1;
604 1440         4588 substr($self->{inline}, 0, length($1)) = '';
605             }
606             else {
607 1         5 $self->die('YAML_PARSE_ERR_BAD_INLINE_IMPLICIT', $value);
608             }
609 1440         2537 return $value;
610             }
611              
612             sub _parse_implicit {
613 2601     2601   3095 my $self = shift;
614 2601         3791 my ($value) = @_;
615             # remove trailing comments and whitespace
616 2601         3392 $value =~ s/^#.*$//;
617 2601         3199 $value =~ s/\s+#.*$//;
618 2601         8985 $value =~ s/\s*$//;
619 2601 100       4687 return $value if $value eq '';
620 2596 100       4120 return undef if $value =~ /^~$/;
621 2592 100 100     9356 return $value
622             unless $value =~ /^[\@\`]/ or
623             $value =~ /^[\-\?]\s/;
624 2         7 $self->die('YAML_PARSE_ERR_BAD_IMPLICIT', $value);
625             }
626              
627             # Unfold a YAML multiline scalar into a single string.
628             sub _parse_unfold {
629 20     20   35 my $self = shift;
630 20         43 my ($chomp) = @_;
631 20         33 my $node = '';
632 20         31 my $space = 0;
633 20   100     47 while (not $self->done and $self->indent == $self->offset->[$self->level]) {
634 57         126 $node .= $self->content. "\n";
635 57         104 $self->_parse_next_line(LEAF);
636             }
637 20         152 $node =~ s/^(\S.*)\n(?=\S)/$1 /gm;
638 20         52 $node =~ s/^(\S.*)\n(\n+\S)/$1$2/gm;
639 20 100       175 $node =~ s/\n*\Z// unless $chomp eq '+';
640 20 100       54 $node .= "\n" unless $chomp;
641 20         56 return $node;
642             }
643              
644             # Parse a YAML block style scalar. This is like a Perl here-document.
645             sub _parse_block {
646 44     44   79 my $self = shift;
647 44         76 my ($chomp) = @_;
648 44         80 my $node = '';
649 44   100     97 while (not $self->done and $self->indent == $self->offset->[$self->level]) {
650 141         284 $node .= $self->content . "\n";
651 141         248 $self->_parse_next_line(LEAF);
652             }
653 44 100       135 return $node if '+' eq $chomp;
654 41         447 $node =~ s/\n*\Z/\n/;
655 41 100       139 $node =~ s/\n\Z// if $chomp eq '-';
656 41         90 return $node;
657             }
658              
659             # Handle Perl style '#' comments. Comments must be at the same indentation
660             # level as the collection line following them.
661             sub _parse_throwaway_comments {
662 2696     2696   3279 my $self = shift;
663 2696   100     3051 while (@{$self->lines} and
  3225         4822  
664             $self->lines->[0] =~ m{^\s*(\#|$)}
665             ) {
666 529         676 shift @{$self->lines};
  529         762  
667 529         622 $self->{line}++;
668             }
669 2696         3696 $self->eos($self->{done} = not @{$self->lines});
  2696         4152  
670             }
671              
672             # This is the routine that controls what line is being parsed. It gets called
673             # once for each line in the YAML stream.
674             #
675             # This routine must:
676             # 1) Skip past the current line
677             # 2) Determine the indentation offset for a new level
678             # 3) Find the next _content_ line
679             # A) Skip over any throwaways (Comments/blanks)
680             # B) Set $self->indent, $self->content, $self->line
681             # 4) Expand tabs appropriately
682             sub _parse_next_line {
683 2227     2227   2736 my $self = shift;
684 2227         3060 my ($type) = @_;
685 2227         3419 my $level = $self->level;
686 2227         3459 my $offset = $self->offset->[$level];
687 2227 50       3932 $self->die('YAML_EMIT_ERR_BAD_LEVEL') unless defined $offset;
688 2227         2378 shift @{$self->lines};
  2227         3527  
689 2227         2833 $self->eos($self->{done} = not @{$self->lines});
  2227         3620  
690 2227 100       3643 if ($self->eos) {
691 257         545 $self->offset->[$level + 1] = $offset + 1;
692 257         631 return;
693             }
694 1970         2748 $self->{line}++;
695              
696             # Determine the offset for a new leaf node
697             # TODO
698 1970 100 100     3341 if ($self->preface =~
    100          
699             qr/(?:^|\s)(?:$FOLD_CHAR|$LIT_CHAR_RX)(?:[+-]([0-9]*)|([0-9]*)[+-]?)(?:\s+#.*|\s*)$/
700             ) {
701 62 50       261 my $explicit_indent = defined $1 ? $1 : defined $2 ? $2 : '';
    100          
702 62 100 100     219 $self->die('YAML_PARSE_ERR_ZERO_INDENT')
703             if length($explicit_indent) and $explicit_indent == 0;
704 61         84 $type = LEAF;
705 61 100       111 if (length($explicit_indent)) {
706 8         16 $self->offset->[$level + 1] = $offset + $explicit_indent;
707             }
708             else {
709             # First get rid of any comments.
710 53   66     72 while (@{$self->lines} && ($self->lines->[0] =~ /^\s*#/)) {
  53         115  
711 1         3 $self->lines->[0] =~ /^( *)/;
712 1 50       4 last unless length($1) <= $offset;
713 0         0 shift @{$self->lines};
  0         0  
714 0         0 $self->{line}++;
715             }
716 53         99 $self->eos($self->{done} = not @{$self->lines});
  53         105  
717 53 50       104 return if $self->eos;
718 53 100 66     118 if ($self->lines->[0] =~ /^( *)\S/ and length($1) > $offset) {
719 52         141 $self->offset->[$level+1] = length($1);
720             }
721             else {
722 1         4 $self->offset->[$level+1] = $offset + 1;
723             }
724             }
725 61         119 $offset = $self->offset->[++$level];
726             }
727             # Determine the offset for a new collection level
728             elsif ($type == COLLECTION and
729             $self->preface =~ /^(\s*(\!\S*|\&\S+))*\s*$/) {
730 644         1460 $self->_parse_throwaway_comments();
731 644         1124 my $zero_indent = $self->zero_indent;
732 644 50 100     1095 if ($self->eos) {
    100 100        
733 0         0 $self->offset->[$level+1] = $offset + 1;
734 0         0 return;
735             }
736             elsif (
737             defined $zero_indent->[ $level ]
738             and not $zero_indent->[ $level ]
739             and $self->lines->[0] =~ /^( {$offset,})-(?: |$)/
740             ) {
741 49         122 my $new_offset = length($1);
742 49         108 $self->offset->[$level+1] = $new_offset;
743 49 100       122 if ($new_offset == $offset) {
744 3         5 $zero_indent->[ $level+1 ] = 1;
745             }
746             }
747             else {
748 595 100       1148 $self->lines->[0] =~ /^( *)\S/ or
749             $self->die('YAML_PARSE_ERR_NONSPACE_INDENTATION');
750 594 100       1593 if (length($1) > $offset) {
751 585         1245 $self->offset->[$level+1] = length($1);
752             }
753             else {
754 9         27 $self->offset->[$level+1] = $offset + 1;
755             }
756             }
757 643         1308 $offset = $self->offset->[++$level];
758             }
759              
760 1968 100       4585 if ($type == LEAF) {
761 233 100 66     260 if (@{$self->lines} and
  233   100     373  
762             $self->lines->[0] =~ m{^( *)(\#)} and
763             length($1) < $offset
764             ) {
765 5 50       13 if ( length($1) < $offset) {
766 5         8 shift @{$self->lines};
  5         10  
767 5         7 $self->{line}++;
768             # every comment after that is also thrown away regardless
769             # of identation
770 5   100     8 while (@{$self->lines} and
  12         17  
771             $self->lines->[0] =~ m{^( *)(\#)}
772             ) {
773 7         10 shift @{$self->lines};
  7         11  
774 7         9 $self->{line}++;
775             }
776             }
777             }
778 233         303 $self->eos($self->{done} = not @{$self->lines});
  233         369  
779             }
780             else {
781 1735         2866 $self->_parse_throwaway_comments();
782             }
783 1968 100       3206 return if $self->eos;
784              
785 1961 100       3361 if ($self->lines->[0] =~ /^---(\s|$)/) {
786 38         94 $self->done(1);
787 38         151 return;
788             }
789 1923 100 100     4948 if ($type == LEAF and
    100          
790             $self->lines->[0] =~ /^ {$offset}(.*)$/
791             ) {
792 183         452 $self->indent($offset);
793 183         376 $self->content($1);
794             }
795             elsif ($self->lines->[0] =~ /^\s*$/) {
796 15         35 $self->indent($offset);
797 15         38 $self->content('');
798             }
799             else {
800 1725         3133 $self->lines->[0] =~ /^( *)(\S.*)$/;
801 1725         3269 while ($self->offset->[$level] > length($1)) {
802 397         695 $level--;
803             }
804 1725 100       2883 $self->die('YAML_PARSE_ERR_INCONSISTENT_INDENTATION')
805             if $self->offset->[$level] != length($1);
806 1720         4615 $self->indent(length($1));
807 1720         2998 $self->content($2);
808             }
809 1918 50       3283 $self->die('YAML_PARSE_ERR_INDENTATION')
810             if $self->indent - $offset > 1;
811             }
812              
813             #==============================================================================
814             # Utility subroutines.
815             #==============================================================================
816              
817             # Printable characters for escapes
818             my %unescapes = (
819             0 => "\x00",
820             a => "\x07",
821             t => "\x09",
822             n => "\x0a",
823             'v' => "\x0b", # Potential v-string error on 5.6.2 if not quoted
824             f => "\x0c",
825             r => "\x0d",
826             e => "\x1b",
827             '\\' => '\\',
828             );
829              
830             # Transform all the backslash style escape characters to their literal meaning
831             sub _unescape {
832 25     25   47 my $self = shift;
833 25         51 my ($node) = @_;
834 25         189 $node =~ s/\\([never\\fart0]|x([0-9a-fA-F]{2}))/
835 22 50       109 (length($1)>1)?pack("H2",$2):$unescapes{$1}/gex;
836 25         73 return $node;
837             }
838              
839             1;