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   1607 use YAML::Mo;
  36         61  
  36         193  
4             extends 'YAML::Loader::Base';
5              
6 36     36   13055 use YAML::Loader::Base;
  36         93  
  36         995  
7 36     36   7281 use YAML::Types;
  36         87  
  36         849  
8 36     36   202 use YAML::Node;
  36         60  
  36         1575  
9              
10             # Context constants
11 36     36   187 use constant LEAF => 1;
  36         74  
  36         1826  
12 36     36   193 use constant COLLECTION => 2;
  36         103  
  36         1884  
13 36     36   230 use constant VALUE => "\x07YAML\x07VALUE\x07";
  36         60  
  36         1996  
14 36     36   201 use constant COMMENT => "\x07YAML\x07COMMENT\x07";
  36         58  
  36         69804  
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 319     319 0 436 my $self = shift;
24 319   50     987 $self->stream($_[0] || '');
25 319         899 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 319     319   445 my $self = shift;
32 319         417 my (%directives, $preface);
33 319         856 $self->{stream} =~ s|\015\012|\012|g;
34 319         646 $self->{stream} =~ s|\015|\012|g;
35 319         748 $self->line(0);
36 319 100       564 $self->die('YAML_PARSE_ERR_BAD_CHARS')
37             if $self->stream =~ /$ESCAPE_CHAR/;
38 318         3388 $self->{stream} =~ s/(.)\n\Z/$1/s;
39 318         750 $self->lines([split /\x0a/, $self->stream, -1]);
40 318         870 $self->line(1);
41             # Throw away any comments or blanks before the header (or start of
42             # content for headerless streams)
43 318         684 $self->_parse_throwaway_comments();
44 318         784 $self->document(0);
45 318         740 $self->documents([]);
46 318         753 $self->zero_indent([]);
47             # Add an "assumed" header if there is no header and the stream is
48             # not empty (after initial throwaways).
49 318 100       584 if (not $self->eos) {
50 280 100       498 if ($self->lines->[0] !~ /^---(\s|$)/) {
51 36         51 unshift @{$self->lines}, '---';
  36         61  
52 36         65 $self->{line}--;
53             }
54             }
55              
56             # Main Loop. Parse out all the top level nodes and return them.
57 318         638 while (not $self->eos) {
58 318         814 $self->anchor2node({});
59 318         443 $self->{document}++;
60 318         657 $self->done(0);
61 318         685 $self->level(0);
62 318         609 $self->offset->[0] = -1;
63              
64 318 50       537 if ($self->lines->[0] =~ /^---\s*(.*)$/) {
65 318         60166 my @words = split /\s/, $1;
66 318         486 %directives = ();
67 318         669 while (@words) {
68 127 100       391 if ($words[0] =~ /^#(\w+):(\S.*)$/) {
    50          
69 17         49 my ($key, $value) = ($1, $2);
70 17         25 shift(@words);
71 17 100       34 if (defined $directives{$key}) {
72 2         4 $self->warn('YAML_PARSE_WARN_MULTIPLE_DIRECTIVES',
73             $key, $self->document);
74 2         752 next;
75             }
76 15         37 $directives{$key} = $value;
77             }
78             elsif ($words[0] eq '') {
79 0         0 shift @words;
80             }
81             else {
82 110         169 last;
83             }
84             }
85 318         10876 $self->preface(join ' ', @words);
86             }
87             else {
88 0         0 $self->die('YAML_PARSE_ERR_NO_SEPARATOR');
89             }
90              
91 318 50       631 if (not $self->done) {
92 318         566 $self->_parse_next_line(COLLECTION);
93             }
94 316 100       659 if ($self->done) {
95 60         98 $self->{indent} = -1;
96 60         138 $self->content('');
97             }
98              
99 316   100     1263 $directives{YAML} ||= '1.0';
100 316   100     989 $directives{TAB} ||= 'NONE';
101             ($self->{major_version}, $self->{minor_version}) =
102 316         1293 split /\./, $directives{YAML}, 2;
103             $self->die('YAML_PARSE_ERR_BAD_MAJOR_VERSION', $directives{YAML})
104 316 100       815 if $self->major_version ne '1';
105             $self->warn('YAML_PARSE_WARN_BAD_MINOR_VERSION', $directives{YAML})
106 315 100       689 if $self->minor_version ne '0';
107             $self->die('Unrecognized TAB policy')
108 315 100       1710 unless $directives{TAB} =~ /^(NONE|\d+)(:HARD)?$/;
109              
110 314         418 push @{$self->documents}, $self->_parse_node();
  314         602  
111             }
112 285 100       679 return wantarray ? @{$self->documents} : $self->documents->[-1];
  151         298  
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 2021     2021   2431 my $self = shift;
120 2021         3093 my $preface = $self->preface;
121 2021         3976 $self->preface('');
122 2021         4077 my ($node, $type, $indicator, $chomp, $parsed_inline) = ('') x 5;
123 2021         2916 my ($anchor, $alias, $explicit, $implicit) = ('') x 4;
124 2021         3206 ($anchor, $alias, $explicit, $implicit, $preface) =
125             $self->_parse_qualifiers($preface);
126 2012 100       3464 if ($anchor) {
127 20         86 $self->anchor2node->{$anchor} = CORE::bless [], 'YAML-anchor2node';
128             }
129 2012         4015 $self->inline('');
130 2012         3529 while (length $preface) {
131 1347 100       5016 if ($preface =~ s/^($FOLD_CHAR|$LIT_CHAR_RX)//) {
132 65         127 $indicator = $1;
133 65 100       184 if ($preface =~ s/^([+-])[0-9]*//) {
    100          
134 23         43 $chomp = $1;
135             }
136             elsif ($preface =~ s/^[0-9]+([+-]?)//) {
137 6         10 $chomp = $1;
138             }
139 65 100       285 if ($preface =~ s/^(?:\s+#.*$|\s*)$//) {
140             }
141             else {
142 1         3 $self->die('YAML_PARSE_ERR_TEXT_AFTER_INDICATOR');
143             }
144             }
145             else {
146 1282         2677 $self->inline($preface);
147 1282         2669 $preface = '';
148             }
149             }
150 2011 100       3669 if ($alias) {
    100          
    100          
    100          
151             $self->die('YAML_PARSE_ERR_NO_ANCHOR', $alias)
152 21 100       53 unless defined $self->anchor2node->{$alias};
153 20 50       38 if (ref($self->anchor2node->{$alias}) ne 'YAML-anchor2node') {
154 20         43 $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 1282         2009 $node = $self->_parse_inline(1, $implicit, $explicit);
163 1274         1682 $parsed_inline = 1;
164 1274 100       2092 if (length $self->inline) {
165 1         4 $self->die('YAML_PARSE_ERR_SINGLE_LINE');
166             }
167             }
168             elsif ($indicator eq $LIT_CHAR) {
169 44         63 $self->{level}++;
170 44         94 $node = $self->_parse_block($chomp);
171 44 50       93 $node = $self->_parse_implicit($node) if $implicit;
172 44         76 $self->{level}--;
173             }
174             elsif ($indicator eq $FOLD_CHAR) {
175 20         32 $self->{level}++;
176 20         40 $node = $self->_parse_unfold($chomp);
177 20 100       40 $node = $self->_parse_implicit($node) if $implicit;
178 19         30 $self->{level}--;
179             }
180             else {
181 644         828 $self->{level}++;
182 644   100     972 $self->offset->[$self->level] ||= 0;
183 644 100       1072 if ($self->indent == $self->offset->[$self->level]) {
184 629 100       977 if ($self->content =~ /^-( |$)/) {
    50          
    0          
185 155         371 $node = $self->_parse_seq($anchor);
186             }
187             elsif ($self->content =~ /(^\?|\:( |$))/) {
188 474         969 $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         913 $self->{level}--;
201             }
202 1972         3445 $#{$self->offset} = $self->level;
  1972         2835  
203              
204 1972 100       3074 if ($explicit) {
205 84 100       263 $node = $self->_parse_explicit($node, $explicit) if !$parsed_inline;
206             }
207 1971 100       2748 if ($anchor) {
208 20 100       36 if (ref($self->anchor2node->{$anchor}) eq 'YAML-anchor2node') {
209             # XXX Can't remember what this code actually does
210 10         14 for my $ref (@{$self->anchor2node->{$anchor}}) {
  10         30  
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         41 $self->anchor2node->{$anchor} = $node;
217             }
218 1971         4040 return $node;
219             }
220              
221             # Preprocess the qualifiers that may be attached to any node.
222             sub _parse_qualifiers {
223 4779     4779   5426 my $self = shift;
224 4779         5936 my ($preface) = @_;
225 4779         6834 my ($anchor, $alias, $explicit, $implicit, $token) = ('') x 5;
226 4779         8305 $self->inline('');
227 4779         10239 while ($preface =~ /^[&*!]/) {
228 146 100       642 if ($preface =~ s/^\!(\S+)\s*//) {
    100          
    100          
    50          
229 90 100       195 $self->die('YAML_PARSE_ERR_MANY_EXPLICIT') if $explicit;
230 89         273 $explicit = $1;
231             }
232             elsif ($preface =~ s/^\!\s*//) {
233 5 100       13 $self->die('YAML_PARSE_ERR_MANY_IMPLICIT') if $implicit;
234 4         11 $implicit = 1;
235             }
236             elsif ($preface =~ s/^\&([^ ,:]*)\s*//) {
237 25         87 $token = $1;
238 25 100       82 $self->die('YAML_PARSE_ERR_BAD_ANCHOR')
239             unless $token =~ /^[a-zA-Z0-9_.\/-]+$/;
240 23 100       53 $self->die('YAML_PARSE_ERR_MANY_ANCHOR') if $anchor;
241 22 50       40 $self->die('YAML_PARSE_ERR_ANCHOR_ALIAS') if $alias;
242 22         51 $anchor = $token;
243             }
244             elsif ($preface =~ s/^\*([^ ,:]*)\s*//) {
245 26         45 $token = $1;
246 26 100       73 $self->die('YAML_PARSE_ERR_BAD_ALIAS')
247             unless $token =~ /^[a-zA-Z0-9_.\/-]+$/;
248 24 100       47 $self->die('YAML_PARSE_ERR_MANY_ALIAS') if $alias;
249 23 100       35 $self->die('YAML_PARSE_ERR_ANCHOR_ALIAS') if $anchor;
250 22         43 $alias = $token;
251             }
252             }
253 4770         12887 return ($anchor, $alias, $explicit, $implicit, $preface);
254             }
255              
256             # Morph a node to it's explicit type
257             sub _parse_explicit {
258 88     88   140 my $self = shift;
259 88         170 my ($node, $explicit) = @_;
260 88         133 my ($type, $class);
261 88 100       475 if ($explicit =~ /^\!?perl\/(hash|array|ref|scalar)(?:\:(\w(\w|\:\:)*)?)?$/) {
262 44   50     231 ($type, $class) = (($1 || ''), ($2 || ''));
      100        
263              
264             # FIXME # die unless uc($type) eq ref($node) ?
265              
266 44 100       94 if ( $type eq "ref" ) {
267             $self->die('YAML_LOAD_ERR_NO_DEFAULT_VALUE', 'XXX', $explicit)
268 22 100 66     103 unless exists $node->{VALUE()} and scalar(keys %$node) == 1;
269              
270 21         35 my $value = $node->{VALUE()};
271 21         36 $node = \$value;
272             }
273              
274 43 100 100     114 if ( $type eq "scalar" and length($class) and !ref($node) ) {
      66        
275 4         12 my $value = $node;
276 4         79 $node = \$value;
277             }
278              
279 43 100 100     118 if ( length($class) and $YAML::LoadBlessed ) {
280 9         16 CORE::bless($node, $class);
281             }
282              
283 43         104 return $node;
284             }
285 44 100 100     325 if ($explicit =~ m{^!?perl/(glob|regexp|code)(?:\:(\w(\w|\:\:)*)?)?$}) {
    100          
    100          
286 22   50     131 ($type, $class) = (($1 || ''), ($2 || ''));
      100        
287 22         120 my $type_class = "YAML::Type::$type";
288 36     36   273 no strict 'refs';
  36         77  
  36         143403  
289 22 50       193 if ($type_class->can('yaml_load')) {
290 22         72 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     75 $class = $YAML::TagClass->{$explicit} || $2;
301 15 100       142 if ($class->can('yaml_load')) {
    100          
302 4         22 require YAML::Node;
303 4         15 return $class->yaml_load(YAML::Node->new($node, $explicit));
304             }
305             elsif ($YAML::LoadBlessed) {
306 5 50       22 if (ref $node) {
307 5         21 return CORE::bless $node, $class;
308             }
309             else {
310 0         0 return CORE::bless \$node, $class;
311             }
312             }
313             else {
314 6         17 return $node;
315             }
316             }
317             elsif (ref $node) {
318 5         27 require YAML::Node;
319 5         29 return YAML::Node->new($node, $explicit);
320             }
321             else {
322             # XXX This is likely wrong. Failing test:
323             # --- !unknown 'scalar value'
324 2         4 return $node;
325             }
326             }
327              
328             # Parse a YAML mapping into a Perl hash
329             sub _parse_mapping {
330 513     513   609 my $self = shift;
331 513         726 my ($anchor) = @_;
332 513 100       888 my $mapping = $self->preserve ? YAML::Node->new({}) : {};
333 513         890 $self->anchor2node->{$anchor} = $mapping;
334 513         594 my $key;
335 513   100     839 while (not $self->done and $self->indent == $self->offset->[$self->level]) {
336             # If structured key:
337 1386 100       4197 if ($self->{content} =~ s/^\?\s*//) {
    100          
    50          
338 5         14 $self->preface($self->content);
339 5         14 $self->_parse_next_line(COLLECTION);
340 5         12 $key = $self->_parse_node();
341 5         12 $key = "$key";
342             }
343             # If "default" key (equals sign)
344             elsif ($self->{content} =~ s/^\=\s*(?=:)//) {
345 23         41 $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         2167 $self->inline($self->content);
354 1358         2041 $key = $self->_parse_inline();
355 1358         1758 $key = "$key";
356 1358         2093 $self->content($self->inline);
357 1358         2341 $self->inline('');
358             }
359              
360 1386 100       6189 unless ($self->{content} =~ s/^:(?:\s+#.*$|\s*)//) {
361 1         3 $self->die('YAML_LOAD_ERR_BAD_MAP_ELEMENT');
362             }
363 1385         2659 $self->preface($self->content);
364 1385         2574 my $level = $self->level;
365              
366             # we can get a zero indented sequence, possibly
367 1385         2172 my $zero_indent = $self->zero_indent;
368 1385         1845 $zero_indent->[ $level ] = 0;
369 1385         2472 $self->_parse_next_line(COLLECTION);
370 1382         2724 my $value = $self->_parse_node();
371 1379         1998 $#$zero_indent = $level;
372              
373 1379 100       2216 if (exists $mapping->{$key}) {
374 2         8 $self->warn('YAML_LOAD_WARN_DUPLICATE_KEY', $key);
375             }
376             else {
377 1377         3791 $mapping->{$key} = $value;
378             }
379             }
380 506         1225 return $mapping;
381             }
382              
383             # Parse a YAML sequence into a Perl array
384             sub _parse_seq {
385 159     159   223 my $self = shift;
386 159         224 my ($anchor) = @_;
387 159         202 my $seq = [];
388 159         287 $self->anchor2node->{$anchor} = $seq;
389 159   100     279 while (not $self->done and $self->indent == $self->offset->[$self->level]) {
390 368 100       702 if ($self->content =~ /^-(?: (.*))?$/) {
391 365 100       963 $self->preface(defined($1) ? $1 : '');
392             }
393             else {
394 3 100       11 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         621 my $preface = $self->preface;
405 365 100 66     2502 if ($preface =~ m/^ (\s*) ( - (?: \ .* | $ ) ) /x) {
    100 100        
      100        
406 4         9 $self->indent($self->offset->[$self->level] + 2 + length($1));
407 4         9 $self->content($2);
408 4         7 $self->level($self->level + 1);
409 4         6 $self->offset->[$self->level] = $self->indent;
410 4         9 $self->preface('');
411 4         22 push @$seq, $self->_parse_seq('');
412 4         6 $self->{level}--;
413 4         7 $#{$self->offset} = $self->level;
  4         7  
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         92 $self->indent($self->offset->[$self->level] + 2 + length($1));
422 39         86 $self->content($2);
423 39         77 $self->level($self->level + 1);
424 39         69 $self->offset->[$self->level] = $self->indent;
425 39         87 $self->preface('');
426 39         90 push @$seq, $self->_parse_mapping('');
427 39         56 $self->{level}--;
428 39         65 $#{$self->offset} = $self->level;
  39         62  
429             }
430             else {
431 322         670 $self->_parse_next_line(COLLECTION);
432 320         710 push @$seq, $self->_parse_node();
433             }
434             }
435 138         281 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 2758     2758   3173 my $self = shift;
442 2758         4362 my ($top, $top_implicit, $top_explicit) = (@_, '', '', '');
443 2758         18365 $self->{inline} =~ s/^\s*(.*)\s*$/$1/; # OUCH - mugwump
444 2758         5585 my ($node, $anchor, $alias, $explicit, $implicit) = ('') x 5;
445 2758         4533 ($anchor, $alias, $explicit, $implicit, $self->{inline}) =
446             $self->_parse_qualifiers($self->inline);
447 2758 50       4918 if ($anchor) {
448 0         0 $self->anchor2node->{$anchor} = CORE::bless [], 'YAML-anchor2node';
449             }
450 2758   66     7573 $implicit ||= $top_implicit;
451 2758   100     6857 $explicit ||= $top_explicit;
452 2758         3802 ($top_implicit, $top_explicit) = ('', '');
453 2758 50       5358 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         67 $node = $self->_parse_inline_mapping($anchor);
466             }
467             elsif ($self->inline =~ /^\[/) {
468 33         79 $node = $self->_parse_inline_seq($anchor);
469             }
470             elsif ($self->inline =~ /^"/) {
471 27         88 $node = $self->_parse_inline_double_quoted();
472 25         64 $node = $self->_unescape($node);
473 25 100       90 $node = $self->_parse_implicit($node) if $implicit;
474             }
475             elsif ($self->inline =~ /^'/) {
476 56         131 $node = $self->_parse_inline_single_quoted();
477 54 50       108 $node = $self->_parse_implicit($node) if $implicit;
478             }
479             else {
480 2615 100       3437 if ($top) {
481 1174         1607 $node = $self->inline;
482 1174         1849 $self->inline('');
483             }
484             else {
485 1441         2057 $node = $self->_parse_inline_simple();
486             }
487 2614 100       5406 $node = $self->_parse_implicit($node) unless $explicit;
488              
489 2613 100 66     4979 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         13 $node += 0;
492             }
493             }
494 2749 100       4579 if ($explicit) {
495 31         64 $node = $self->_parse_explicit($node, $explicit);
496             }
497 2749 50       3647 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 2749         4415 return $node;
508             }
509              
510             # Parse the inline YAML mapping into a Perl hash
511             sub _parse_inline_mapping {
512 27     27   85 my $self = shift;
513 27         75 my ($anchor) = @_;
514 27         48 my $node = {};
515 27         63 $self->anchor2node->{$anchor} = $node;
516              
517             $self->die('YAML_PARSE_ERR_INLINE_MAP')
518 27 50       119 unless $self->{inline} =~ s/^\{\s*//;
519 27         121 while (not $self->{inline} =~ s/^\s*\}(\s+#.*$|\s*)//) {
520 30         75 my $key = $self->_parse_inline();
521             $self->die('YAML_PARSE_ERR_INLINE_MAP')
522 30 100       107 unless $self->{inline} =~ s/^\: \s*//;
523 29         60 my $value = $self->_parse_inline();
524 29 50       58 if (exists $node->{$key}) {
525 0         0 $self->warn('YAML_LOAD_WARN_DUPLICATE_KEY', $key);
526             }
527             else {
528 29         55 $node->{$key} = $value;
529             }
530 29 100       76 next if $self->inline =~ /^\s*\}/;
531             $self->die('YAML_PARSE_ERR_INLINE_MAP')
532 12 50       57 unless $self->{inline} =~ s/^\,\s*//;
533             }
534 26         57 return $node;
535             }
536              
537             # Parse the inline YAML sequence into a Perl array
538             sub _parse_inline_seq {
539 33     33   49 my $self = shift;
540 33         49 my ($anchor) = @_;
541 33         51 my $node = [];
542 33         72 $self->anchor2node->{$anchor} = $node;
543              
544             $self->die('YAML_PARSE_ERR_INLINE_SEQUENCE')
545 33 50       165 unless $self->{inline} =~ s/^\[\s*//;
546 33         128 while (not $self->{inline} =~ s/^\s*\](\s+#.*$|\s*)//) {
547 59         149 my $value = $self->_parse_inline();
548 58         102 push @$node, $value;
549 58 100       168 next if $self->inline =~ /^\s*\]/;
550             $self->die('YAML_PARSE_ERR_INLINE_SEQUENCE')
551 36 100       160 unless $self->{inline} =~ s/^\,\s*//;
552             }
553 31         62 return $node;
554             }
555              
556             # Parse the inline double quoted string.
557             sub _parse_inline_double_quoted {
558 27     27   39 my $self = shift;
559 27         54 my $inline = $self->inline;
560 27 50       1953 if ($inline =~ s/^"//) {
561 27         61 my $node = '';
562              
563 27         7920 while ($inline =~ s/^(\\.|[^"\\]+)//) {
564 160061         353715 my $capture = $1;
565 160061         297076 $capture =~ s/^\\"/"/;
566 160061         190052 $node .= $capture;
567 160061 100       10444998 last unless length $inline;
568             }
569 27 100       104 if ($inline =~ s/^"(?:\s+#.*|\s*)//) {
570 25         87 $self->inline($inline);
571 25         347 return $node;
572             }
573             }
574 2         32 $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   93 my $self = shift;
581 56         110 my $inline = $self->inline;
582 56 50       207 if ($inline =~ s/^'//) {
583 56         85 my $node = '';
584 56         209 while ($inline =~ s/^(''|[^']+)//) {
585 52         111 my $capture = $1;
586 52         71 $capture =~ s/^''/'/;
587 52         89 $node .= $capture;
588 52 100       195 last unless length $inline;
589             }
590 56 100       205 if ($inline =~ s/^'(?:\s+#.*|\s*)//) {
591 54         134 $self->inline($inline);
592 54         138 return $node;
593             }
594             }
595 2         13 $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   1608 my $self = shift;
601 1441         1550 my $value;
602 1441 100       1945 if ($self->inline =~ /^(|[^!@#%^&*].*?)(?=[\[\]\{\},]|, |: |- |:\s*$|$)/) {
603 1440         2590 $value = $1;
604 1440         4725 substr($self->{inline}, 0, length($1)) = '';
605             }
606             else {
607 1         4 $self->die('YAML_PARSE_ERR_BAD_INLINE_IMPLICIT', $value);
608             }
609 1440         2523 return $value;
610             }
611              
612             sub _parse_implicit {
613 2601     2601   2973 my $self = shift;
614 2601         3361 my ($value) = @_;
615             # remove trailing comments and whitespace
616 2601         3171 $value =~ s/^#.*$//;
617 2601         3091 $value =~ s/\s+#.*$//;
618 2601         9141 $value =~ s/\s*$//;
619 2601 100       4685 return $value if $value eq '';
620 2596 100       3825 return undef if $value =~ /^~$/;
621 2592 100 100     8883 return $value
622             unless $value =~ /^[\@\`]/ or
623             $value =~ /^[\-\?]\s/;
624 2         6 $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   29 my $self = shift;
630 20         52 my ($chomp) = @_;
631 20         33 my $node = '';
632 20         21 my $space = 0;
633 20   100     39 while (not $self->done and $self->indent == $self->offset->[$self->level]) {
634 57         127 $node .= $self->content. "\n";
635 57         104 $self->_parse_next_line(LEAF);
636             }
637 20         137 $node =~ s/^(\S.*)\n(?=\S)/$1 /gm;
638 20         56 $node =~ s/^(\S.*)\n(\n+\S)/$1$2/gm;
639 20 100       159 $node =~ s/\n*\Z// unless $chomp eq '+';
640 20 100       58 $node .= "\n" unless $chomp;
641 20         45 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   62 my $self = shift;
647 44         80 my ($chomp) = @_;
648 44         56 my $node = '';
649 44   100     95 while (not $self->done and $self->indent == $self->offset->[$self->level]) {
650 141         259 $node .= $self->content . "\n";
651 141         225 $self->_parse_next_line(LEAF);
652             }
653 44 100       111 return $node if '+' eq $chomp;
654 41         413 $node =~ s/\n*\Z/\n/;
655 41 100       131 $node =~ s/\n\Z// if $chomp eq '-';
656 41         83 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 2697     2697   3075 my $self = shift;
663 2697   100     2841 while (@{$self->lines} and
  3226         4558  
664             $self->lines->[0] =~ m{^\s*(\#|$)}
665             ) {
666 529         630 shift @{$self->lines};
  529         713  
667 529         617 $self->{line}++;
668             }
669 2697         3518 $self->eos($self->{done} = not @{$self->lines});
  2697         4190  
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 2228     2228   2634 my $self = shift;
684 2228         2925 my ($type) = @_;
685 2228         3225 my $level = $self->level;
686 2228         3365 my $offset = $self->offset->[$level];
687 2228 50       3798 $self->die('YAML_EMIT_ERR_BAD_LEVEL') unless defined $offset;
688 2228         2247 shift @{$self->lines};
  2228         3395  
689 2228         2717 $self->eos($self->{done} = not @{$self->lines});
  2228         3226  
690 2228 100       3472 if ($self->eos) {
691 258         569 $self->offset->[$level + 1] = $offset + 1;
692 258         471 return;
693             }
694 1970         2666 $self->{line}++;
695              
696             # Determine the offset for a new leaf node
697             # TODO
698 1970 100 100     2942 if ($self->preface =~
    100          
699             qr/(?:^|\s)(?:$FOLD_CHAR|$LIT_CHAR_RX)(?:[+-]([0-9]*)|([0-9]*)[+-]?)(?:\s+#.*|\s*)$/
700             ) {
701 62 50       217 my $explicit_indent = defined $1 ? $1 : defined $2 ? $2 : '';
    100          
702 62 100 100     181 $self->die('YAML_PARSE_ERR_ZERO_INDENT')
703             if length($explicit_indent) and $explicit_indent == 0;
704 61         83 $type = LEAF;
705 61 100       99 if (length($explicit_indent)) {
706 8         15 $self->offset->[$level + 1] = $offset + $explicit_indent;
707             }
708             else {
709             # First get rid of any comments.
710 53   66     63 while (@{$self->lines} && ($self->lines->[0] =~ /^\s*#/)) {
  53         102  
711 1         2 $self->lines->[0] =~ /^( *)/;
712 1 50       3 last unless length($1) <= $offset;
713 0         0 shift @{$self->lines};
  0         0  
714 0         0 $self->{line}++;
715             }
716 53         83 $self->eos($self->{done} = not @{$self->lines});
  53         95  
717 53 50       83 return if $self->eos;
718 53 100 66     95 if ($self->lines->[0] =~ /^( *)\S/ and length($1) > $offset) {
719 52         122 $self->offset->[$level+1] = length($1);
720             }
721             else {
722 1         3 $self->offset->[$level+1] = $offset + 1;
723             }
724             }
725 61         124 $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         1077 my $zero_indent = $self->zero_indent;
732 644 50 100     982 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         107 my $new_offset = length($1);
742 49         94 $self->offset->[$level+1] = $new_offset;
743 49 100       111 if ($new_offset == $offset) {
744 3         5 $zero_indent->[ $level+1 ] = 1;
745             }
746             }
747             else {
748 595 100       1084 $self->lines->[0] =~ /^( *)\S/ or
749             $self->die('YAML_PARSE_ERR_NONSPACE_INDENTATION');
750 594 100       1396 if (length($1) > $offset) {
751 585         1152 $self->offset->[$level+1] = length($1);
752             }
753             else {
754 9         23 $self->offset->[$level+1] = $offset + 1;
755             }
756             }
757 643         1185 $offset = $self->offset->[++$level];
758             }
759              
760 1968 100       4349 if ($type == LEAF) {
761 233 100 66     265 if (@{$self->lines} and
  233   100     371  
762             $self->lines->[0] =~ m{^( *)(\#)} and
763             length($1) < $offset
764             ) {
765 5 50       13 if ( length($1) < $offset) {
766 5         6 shift @{$self->lines};
  5         10  
767 5         8 $self->{line}++;
768             # every comment after that is also thrown away regardless
769             # of identation
770 5   100     6 while (@{$self->lines} and
  12         18  
771             $self->lines->[0] =~ m{^( *)(\#)}
772             ) {
773 7         11 shift @{$self->lines};
  7         10  
774 7         18 $self->{line}++;
775             }
776             }
777             }
778 233         295 $self->eos($self->{done} = not @{$self->lines});
  233         345  
779             }
780             else {
781 1735         2677 $self->_parse_throwaway_comments();
782             }
783 1968 100       3027 return if $self->eos;
784              
785 1961 100       3326 if ($self->lines->[0] =~ /^---(\s|$)/) {
786 38         84 $self->done(1);
787 38         69 return;
788             }
789 1923 100 100     4491 if ($type == LEAF and
    100          
790             $self->lines->[0] =~ /^ {$offset}(.*)$/
791             ) {
792 183         422 $self->indent($offset);
793 183         340 $self->content($1);
794             }
795             elsif ($self->lines->[0] =~ /^\s*$/) {
796 15         33 $self->indent($offset);
797 15         23 $self->content('');
798             }
799             else {
800 1725         2763 $self->lines->[0] =~ /^( *)(\S.*)$/;
801 1725         3042 while ($self->offset->[$level] > length($1)) {
802 397         647 $level--;
803             }
804 1725 100       2752 $self->die('YAML_PARSE_ERR_INCONSISTENT_INDENTATION')
805             if $self->offset->[$level] != length($1);
806 1720         4029 $self->indent(length($1));
807 1720         2802 $self->content($2);
808             }
809 1918 50       3154 $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   37 my $self = shift;
833 25         47 my ($node) = @_;
834 25         185 $node =~ s/\\([never\\fart0]|x([0-9a-fA-F]{2}))/
835 22 50       107 (length($1)>1)?pack("H2",$2):$unescapes{$1}/gex;
836 25         64 return $node;
837             }
838              
839             1;