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   1785 use YAML::Mo;
  36         64  
  36         212  
4             extends 'YAML::Loader::Base';
5              
6 36     36   13823 use YAML::Loader::Base;
  36         101  
  36         1034  
7 36     36   7309 use YAML::Types;
  36         84  
  36         917  
8 36     36   194 use YAML::Node;
  36         77  
  36         1629  
9              
10             # Context constants
11 36     36   205 use constant LEAF => 1;
  36         81  
  36         1961  
12 36     36   222 use constant COLLECTION => 2;
  36         109  
  36         1885  
13 36     36   230 use constant VALUE => "\x07YAML\x07VALUE\x07";
  36         57  
  36         1696  
14 36     36   183 use constant COMMENT => "\x07YAML\x07COMMENT\x07";
  36         66  
  36         86579  
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 537 my $self = shift;
24 318   50     1121 $self->stream($_[0] || '');
25 318         669 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   444 my $self = shift;
32 318         468 my (%directives, $preface);
33 318         938 $self->{stream} =~ s|\015\012|\012|g;
34 318         718 $self->{stream} =~ s|\015|\012|g;
35 318         826 $self->line(0);
36 318 100       642 $self->die('YAML_PARSE_ERR_BAD_CHARS')
37             if $self->stream =~ /$ESCAPE_CHAR/;
38 317         3571 $self->{stream} =~ s/(.)\n\Z/$1/s;
39 317         905 $self->lines([split /\x0a/, $self->stream, -1]);
40 317         954 $self->line(1);
41             # Throw away any comments or blanks before the header (or start of
42             # content for headerless streams)
43 317         748 $self->_parse_throwaway_comments();
44 317         868 $self->document(0);
45 317         817 $self->documents([]);
46 317         853 $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       628 if (not $self->eos) {
50 279 100       582 if ($self->lines->[0] !~ /^---(\s|$)/) {
51 36         53 unshift @{$self->lines}, '---';
  36         76  
52 36         67 $self->{line}--;
53             }
54             }
55              
56             # Main Loop. Parse out all the top level nodes and return them.
57 317         708 while (not $self->eos) {
58 317         933 $self->anchor2node({});
59 317         478 $self->{document}++;
60 317         740 $self->done(0);
61 317         778 $self->level(0);
62 317         678 $self->offset->[0] = -1;
63              
64 317 50       643 if ($self->lines->[0] =~ /^---\s*(.*)$/) {
65 317         78026 my @words = split /\s/, $1;
66 317         576 %directives = ();
67 317         726 while (@words) {
68 126 100       457 if ($words[0] =~ /^#(\w+):(\S.*)$/) {
    50          
69 17         63 my ($key, $value) = ($1, $2);
70 17         33 shift(@words);
71 17 100       57 if (defined $directives{$key}) {
72 2         5 $self->warn('YAML_PARSE_WARN_MULTIPLE_DIRECTIVES',
73             $key, $self->document);
74 2         915 next;
75             }
76 15         45 $directives{$key} = $value;
77             }
78             elsif ($words[0] eq '') {
79 0         0 shift @words;
80             }
81             else {
82 109         193 last;
83             }
84             }
85 317         14113 $self->preface(join ' ', @words);
86             }
87             else {
88 0         0 $self->die('YAML_PARSE_ERR_NO_SEPARATOR');
89             }
90              
91 317 50       739 if (not $self->done) {
92 317         621 $self->_parse_next_line(COLLECTION);
93             }
94 315 100       679 if ($self->done) {
95 59         119 $self->{indent} = -1;
96 59         137 $self->content('');
97             }
98              
99 315   100     1408 $directives{YAML} ||= '1.0';
100 315   100     1173 $directives{TAB} ||= 'NONE';
101             ($self->{major_version}, $self->{minor_version}) =
102 315         1454 split /\./, $directives{YAML}, 2;
103             $self->die('YAML_PARSE_ERR_BAD_MAJOR_VERSION', $directives{YAML})
104 315 100       897 if $self->major_version ne '1';
105             $self->warn('YAML_PARSE_WARN_BAD_MINOR_VERSION', $directives{YAML})
106 314 100       789 if $self->minor_version ne '0';
107             $self->die('Unrecognized TAB policy')
108 314 100       1879 unless $directives{TAB} =~ /^(NONE|\d+)(:HARD)?$/;
109              
110 313         466 push @{$self->documents}, $self->_parse_node();
  313         642  
111             }
112 284 100       713 return wantarray ? @{$self->documents} : $self->documents->[-1];
  151         350  
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   2517 my $self = shift;
120 2020         3152 my $preface = $self->preface;
121 2020         4108 $self->preface('');
122 2020         4280 my ($node, $type, $indicator, $chomp, $parsed_inline) = ('') x 5;
123 2020         3125 my ($anchor, $alias, $explicit, $implicit) = ('') x 4;
124 2020         3382 ($anchor, $alias, $explicit, $implicit, $preface) =
125             $self->_parse_qualifiers($preface);
126 2011 100       3558 if ($anchor) {
127 20         99 $self->anchor2node->{$anchor} = CORE::bless [], 'YAML-anchor2node';
128             }
129 2011         3917 $self->inline('');
130 2011         4007 while (length $preface) {
131 1346 100       5032 if ($preface =~ s/^($FOLD_CHAR|$LIT_CHAR_RX)//) {
132 65         152 $indicator = $1;
133 65 100       208 if ($preface =~ s/^([+-])[0-9]*//) {
    100          
134 23         42 $chomp = $1;
135             }
136             elsif ($preface =~ s/^[0-9]+([+-]?)//) {
137 6         11 $chomp = $1;
138             }
139 65 100       305 if ($preface =~ s/^(?:\s+#.*$|\s*)$//) {
140             }
141             else {
142 1         5 $self->die('YAML_PARSE_ERR_TEXT_AFTER_INDICATOR');
143             }
144             }
145             else {
146 1281         2843 $self->inline($preface);
147 1281         2774 $preface = '';
148             }
149             }
150 2010 100       3991 if ($alias) {
    100          
    100          
    100          
151             $self->die('YAML_PARSE_ERR_NO_ANCHOR', $alias)
152 21 100       61 unless defined $self->anchor2node->{$alias};
153 20 50       43 if (ref($self->anchor2node->{$alias}) ne 'YAML-anchor2node') {
154 20         47 $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         2344 $node = $self->_parse_inline(1, $implicit, $explicit);
163 1273         1730 $parsed_inline = 1;
164 1273 100       2069 if (length $self->inline) {
165 1         4 $self->die('YAML_PARSE_ERR_SINGLE_LINE');
166             }
167             }
168             elsif ($indicator eq $LIT_CHAR) {
169 44         68 $self->{level}++;
170 44         110 $node = $self->_parse_block($chomp);
171 44 50       94 $node = $self->_parse_implicit($node) if $implicit;
172 44         70 $self->{level}--;
173             }
174             elsif ($indicator eq $FOLD_CHAR) {
175 20         39 $self->{level}++;
176 20         54 $node = $self->_parse_unfold($chomp);
177 20 100       46 $node = $self->_parse_implicit($node) if $implicit;
178 19         33 $self->{level}--;
179             }
180             else {
181 644         923 $self->{level}++;
182 644   100     1159 $self->offset->[$self->level] ||= 0;
183 644 100       1188 if ($self->indent == $self->offset->[$self->level]) {
184 629 100       1016 if ($self->content =~ /^-( |$)/) {
    50          
    0          
185 155         395 $node = $self->_parse_seq($anchor);
186             }
187             elsif ($self->content =~ /(^\?|\:( |$))/) {
188 474         1035 $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         25 $node = undef;
199             }
200 616         1036 $self->{level}--;
201             }
202 1971         3708 $#{$self->offset} = $self->level;
  1971         2871  
203              
204 1971 100       3196 if ($explicit) {
205 84 100       253 $node = $self->_parse_explicit($node, $explicit) if !$parsed_inline;
206             }
207 1970 100       2885 if ($anchor) {
208 20 100       49 if (ref($self->anchor2node->{$anchor}) eq 'YAML-anchor2node') {
209             # XXX Can't remember what this code actually does
210 10         31 for my $ref (@{$self->anchor2node->{$anchor}}) {
  10         20  
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         67 $self->anchor2node->{$anchor} = $node;
217             }
218 1970         4183 return $node;
219             }
220              
221             # Preprocess the qualifiers that may be attached to any node.
222             sub _parse_qualifiers {
223 4777     4777   5931 my $self = shift;
224 4777         6136 my ($preface) = @_;
225 4777         7038 my ($anchor, $alias, $explicit, $implicit, $token) = ('') x 5;
226 4777         8640 $self->inline('');
227 4777         10887 while ($preface =~ /^[&*!]/) {
228 146 100       725 if ($preface =~ s/^\!(\S+)\s*//) {
    100          
    100          
    50          
229 90 100       219 $self->die('YAML_PARSE_ERR_MANY_EXPLICIT') if $explicit;
230 89         300 $explicit = $1;
231             }
232             elsif ($preface =~ s/^\!\s*//) {
233 5 100       27 $self->die('YAML_PARSE_ERR_MANY_IMPLICIT') if $implicit;
234 4         14 $implicit = 1;
235             }
236             elsif ($preface =~ s/^\&([^ ,:]*)\s*//) {
237 25         59 $token = $1;
238 25 100       82 $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         56 $anchor = $token;
243             }
244             elsif ($preface =~ s/^\*([^ ,:]*)\s*//) {
245 26         56 $token = $1;
246 26 100       85 $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       43 $self->die('YAML_PARSE_ERR_ANCHOR_ALIAS') if $anchor;
250 22         49 $alias = $token;
251             }
252             }
253 4768         13409 return ($anchor, $alias, $explicit, $implicit, $preface);
254             }
255              
256             # Morph a node to it's explicit type
257             sub _parse_explicit {
258 88     88   126 my $self = shift;
259 88         256 my ($node, $explicit) = @_;
260 88         141 my ($type, $class);
261 88 100       493 if ($explicit =~ /^\!?perl\/(hash|array|ref|scalar)(?:\:(\w(\w|\:\:)*)?)?$/) {
262 44   50     251 ($type, $class) = (($1 || ''), ($2 || ''));
      100        
263              
264             # FIXME # die unless uc($type) eq ref($node) ?
265              
266 44 100       108 if ( $type eq "ref" ) {
267             $self->die('YAML_LOAD_ERR_NO_DEFAULT_VALUE', 'XXX', $explicit)
268 22 100 66     107 unless exists $node->{VALUE()} and scalar(keys %$node) == 1;
269              
270 21         39 my $value = $node->{VALUE()};
271 21         37 $node = \$value;
272             }
273              
274 43 100 100     132 if ( $type eq "scalar" and length($class) and !ref($node) ) {
      66        
275 4         73 my $value = $node;
276 4         13 $node = \$value;
277             }
278              
279 43 100 100     142 if ( length($class) and $YAML::LoadBlessed ) {
280 15         39 CORE::bless($node, $class);
281             }
282              
283 43         104 return $node;
284             }
285 44 100 100     313 if ($explicit =~ m{^!?perl/(glob|regexp|code)(?:\:(\w(\w|\:\:)*)?)?$}) {
    100          
    100          
286 22   50     201 ($type, $class) = (($1 || ''), ($2 || ''));
      100        
287 22         63 my $type_class = "YAML::Type::$type";
288 36     36   285 no strict 'refs';
  36         78  
  36         154105  
289 22 50       199 if ($type_class->can('yaml_load')) {
290 22         82 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     80 $class = $YAML::TagClass->{$explicit} || $2;
301 15 100       147 if ($class->can('yaml_load')) {
    100          
302 4         19 require YAML::Node;
303 4         17 return $class->yaml_load(YAML::Node->new($node, $explicit));
304             }
305             elsif ($YAML::LoadBlessed) {
306 7 50       24 if (ref $node) {
307 7         44 return CORE::bless $node, $class;
308             }
309             else {
310 0         0 return CORE::bless \$node, $class;
311             }
312             }
313             else {
314 4         8 return $node;
315             }
316             }
317             elsif (ref $node) {
318 5         33 require YAML::Node;
319 5         25 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   709 my $self = shift;
331 513         707 my ($anchor) = @_;
332 513 100       993 my $mapping = $self->preserve ? YAML::Node->new({}) : {};
333 513         1072 $self->anchor2node->{$anchor} = $mapping;
334 513         622 my $key;
335 513   100     849 while (not $self->done and $self->indent == $self->offset->[$self->level]) {
336             # If structured key:
337 1386 100       4515 if ($self->{content} =~ s/^\?\s*//) {
    100          
    50          
338 5         15 $self->preface($self->content);
339 5         14 $self->_parse_next_line(COLLECTION);
340 5         13 $key = $self->_parse_node();
341 5         12 $key = "$key";
342             }
343             # If "default" key (equals sign)
344             elsif ($self->{content} =~ s/^\=\s*(?=:)//) {
345 23         45 $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         2276 $self->inline($self->content);
354 1358         2384 $key = $self->_parse_inline();
355 1358         1861 $key = "$key";
356 1358         2157 $self->content($self->inline);
357 1358         2343 $self->inline('');
358             }
359              
360 1386 100       6249 unless ($self->{content} =~ s/^:(?:\s+#.*$|\s*)//) {
361 1         3 $self->die('YAML_LOAD_ERR_BAD_MAP_ELEMENT');
362             }
363 1385         2702 $self->preface($self->content);
364 1385         2649 my $level = $self->level;
365              
366             # we can get a zero indented sequence, possibly
367 1385         2315 my $zero_indent = $self->zero_indent;
368 1385         2259 $zero_indent->[ $level ] = 0;
369 1385         2516 $self->_parse_next_line(COLLECTION);
370 1382         2862 my $value = $self->_parse_node();
371 1379         1979 $#$zero_indent = $level;
372              
373 1379 100       2648 if (exists $mapping->{$key}) {
374 2         6 $self->warn('YAML_LOAD_WARN_DUPLICATE_KEY', $key);
375             }
376             else {
377 1377         3788 $mapping->{$key} = $value;
378             }
379             }
380 506         988 return $mapping;
381             }
382              
383             # Parse a YAML sequence into a Perl array
384             sub _parse_seq {
385 159     159   225 my $self = shift;
386 159         279 my ($anchor) = @_;
387 159         240 my $seq = [];
388 159         344 $self->anchor2node->{$anchor} = $seq;
389 159   100     342 while (not $self->done and $self->indent == $self->offset->[$self->level]) {
390 368 100       773 if ($self->content =~ /^-(?: (.*))?$/) {
391 365 100       1042 $self->preface(defined($1) ? $1 : '');
392             }
393             else {
394 3 100       10 if ($self->zero_indent->[ $self->level ]) {
395 2         4 last;
396             }
397 1         3 $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         686 my $preface = $self->preface;
405 365 100 66     2773 if ($preface =~ m/^ (\s*) ( - (?: \ .* | $ ) ) /x) {
    100 100        
      100        
406 4         7 $self->indent($self->offset->[$self->level] + 2 + length($1));
407 4         9 $self->content($2);
408 4         9 $self->level($self->level + 1);
409 4         7 $self->offset->[$self->level] = $self->indent;
410 4         9 $self->preface('');
411 4         11 push @$seq, $self->_parse_seq('');
412 4         8 $self->{level}--;
413 4         5 $#{$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         102 $self->indent($self->offset->[$self->level] + 2 + length($1));
422 39         98 $self->content($2);
423 39         80 $self->level($self->level + 1);
424 39         81 $self->offset->[$self->level] = $self->indent;
425 39         91 $self->preface('');
426 39         104 push @$seq, $self->_parse_mapping('');
427 39         64 $self->{level}--;
428 39         77 $#{$self->offset} = $self->level;
  39         81  
429             }
430             else {
431 322         717 $self->_parse_next_line(COLLECTION);
432 320         879 push @$seq, $self->_parse_node();
433             }
434             }
435 138         316 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   3302 my $self = shift;
442 2757         4313 my ($top, $top_implicit, $top_explicit) = (@_, '', '', '');
443 2757         18690 $self->{inline} =~ s/^\s*(.*)\s*$/$1/; # OUCH - mugwump
444 2757         5823 my ($node, $anchor, $alias, $explicit, $implicit) = ('') x 5;
445 2757         4618 ($anchor, $alias, $explicit, $implicit, $self->{inline}) =
446             $self->_parse_qualifiers($self->inline);
447 2757 50       5001 if ($anchor) {
448 0         0 $self->anchor2node->{$anchor} = CORE::bless [], 'YAML-anchor2node';
449             }
450 2757   66     7870 $implicit ||= $top_implicit;
451 2757   100     6855 $explicit ||= $top_explicit;
452 2757         3722 ($top_implicit, $top_explicit) = ('', '');
453 2757 50       5196 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         82 $node = $self->_parse_inline_mapping($anchor);
466             }
467             elsif ($self->inline =~ /^\[/) {
468 32         98 $node = $self->_parse_inline_seq($anchor);
469             }
470             elsif ($self->inline =~ /^"/) {
471 27         97 $node = $self->_parse_inline_double_quoted();
472 25         89 $node = $self->_unescape($node);
473 25 100       71 $node = $self->_parse_implicit($node) if $implicit;
474             }
475             elsif ($self->inline =~ /^'/) {
476 56         165 $node = $self->_parse_inline_single_quoted();
477 54 50       123 $node = $self->_parse_implicit($node) if $implicit;
478             }
479             else {
480 2615 100       3567 if ($top) {
481 1174         1839 $node = $self->inline;
482 1174         1964 $self->inline('');
483             }
484             else {
485 1441         2302 $node = $self->_parse_inline_simple();
486             }
487 2614 100       5482 $node = $self->_parse_implicit($node) unless $explicit;
488              
489 2613 100 66     5023 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         11 $node += 0;
492             }
493             }
494 2748 100       4855 if ($explicit) {
495 30         158 $node = $self->_parse_explicit($node, $explicit);
496             }
497 2748 50       3842 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         4610 return $node;
508             }
509              
510             # Parse the inline YAML mapping into a Perl hash
511             sub _parse_inline_mapping {
512 27     27   40 my $self = shift;
513 27         51 my ($anchor) = @_;
514 27         56 my $node = {};
515 27         77 $self->anchor2node->{$anchor} = $node;
516              
517             $self->die('YAML_PARSE_ERR_INLINE_MAP')
518 27 50       148 unless $self->{inline} =~ s/^\{\s*//;
519 27         127 while (not $self->{inline} =~ s/^\s*\}(\s+#.*$|\s*)//) {
520 30         98 my $key = $self->_parse_inline();
521             $self->die('YAML_PARSE_ERR_INLINE_MAP')
522 30 100       111 unless $self->{inline} =~ s/^\: \s*//;
523 29         53 my $value = $self->_parse_inline();
524 29 50       56 if (exists $node->{$key}) {
525 0         0 $self->warn('YAML_LOAD_WARN_DUPLICATE_KEY', $key);
526             }
527             else {
528 29         68 $node->{$key} = $value;
529             }
530 29 100       77 next if $self->inline =~ /^\s*\}/;
531             $self->die('YAML_PARSE_ERR_INLINE_MAP')
532 12 50       378 unless $self->{inline} =~ s/^\,\s*//;
533             }
534 26         62 return $node;
535             }
536              
537             # Parse the inline YAML sequence into a Perl array
538             sub _parse_inline_seq {
539 32     32   52 my $self = shift;
540 32         55 my ($anchor) = @_;
541 32         55 my $node = [];
542 32         86 $self->anchor2node->{$anchor} = $node;
543              
544             $self->die('YAML_PARSE_ERR_INLINE_SEQUENCE')
545 32 50       138 unless $self->{inline} =~ s/^\[\s*//;
546 32         140 while (not $self->{inline} =~ s/^\s*\](\s+#.*$|\s*)//) {
547 59         157 my $value = $self->_parse_inline();
548 58         211 push @$node, $value;
549 58 100       131 next if $self->inline =~ /^\s*\]/;
550             $self->die('YAML_PARSE_ERR_INLINE_SEQUENCE')
551 36 100       168 unless $self->{inline} =~ s/^\,\s*//;
552             }
553 30         68 return $node;
554             }
555              
556             # Parse the inline double quoted string.
557             sub _parse_inline_double_quoted {
558 27     27   50 my $self = shift;
559 27         63 my $inline = $self->inline;
560 27 50       1900 if ($inline =~ s/^"//) {
561 27         54 my $node = '';
562              
563 27         6735 while ($inline =~ s/^(\\.|[^"\\]+)//) {
564 160061         444232 my $capture = $1;
565 160061         370451 $capture =~ s/^\\"/"/;
566 160061         238605 $node .= $capture;
567 160061 100       13090411 last unless length $inline;
568             }
569 27 100       128 if ($inline =~ s/^"(?:\s+#.*|\s*)//) {
570 25         97 $self->inline($inline);
571 25         410 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   98 my $self = shift;
581 56         132 my $inline = $self->inline;
582 56 50       257 if ($inline =~ s/^'//) {
583 56         99 my $node = '';
584 56         249 while ($inline =~ s/^(''|[^']+)//) {
585 52         124 my $capture = $1;
586 52         89 $capture =~ s/^''/'/;
587 52         93 $node .= $capture;
588 52 100       221 last unless length $inline;
589             }
590 56 100       285 if ($inline =~ s/^'(?:\s+#.*|\s*)//) {
591 54         167 $self->inline($inline);
592 54         153 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   1686 my $self = shift;
601 1441         1468 my $value;
602 1441 100       2072 if ($self->inline =~ /^(|[^!@#%^&*].*?)(?=[\[\]\{\},]|, |: |- |:\s*$|$)/) {
603 1440         2621 $value = $1;
604 1440         4691 substr($self->{inline}, 0, length($1)) = '';
605             }
606             else {
607 1         4 $self->die('YAML_PARSE_ERR_BAD_INLINE_IMPLICIT', $value);
608             }
609 1440         2524 return $value;
610             }
611              
612             sub _parse_implicit {
613 2601     2601   3100 my $self = shift;
614 2601         3563 my ($value) = @_;
615             # remove trailing comments and whitespace
616 2601         3415 $value =~ s/^#.*$//;
617 2601         3163 $value =~ s/\s+#.*$//;
618 2601         8943 $value =~ s/\s*$//;
619 2601 100       4777 return $value if $value eq '';
620 2596 100       4011 return undef if $value =~ /^~$/;
621 2592 100 100     9379 return $value
622             unless $value =~ /^[\@\`]/ or
623             $value =~ /^[\-\?]\s/;
624 2         10 $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   33 my $self = shift;
630 20         47 my ($chomp) = @_;
631 20         34 my $node = '';
632 20         32 my $space = 0;
633 20   100     49 while (not $self->done and $self->indent == $self->offset->[$self->level]) {
634 57         121 $node .= $self->content. "\n";
635 57         106 $self->_parse_next_line(LEAF);
636             }
637 20         155 $node =~ s/^(\S.*)\n(?=\S)/$1 /gm;
638 20         51 $node =~ s/^(\S.*)\n(\n+\S)/$1$2/gm;
639 20 100       172 $node =~ s/\n*\Z// unless $chomp eq '+';
640 20 100       63 $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   108 my $self = shift;
647 44         76 my ($chomp) = @_;
648 44         87 my $node = '';
649 44   100     100 while (not $self->done and $self->indent == $self->offset->[$self->level]) {
650 141         300 $node .= $self->content . "\n";
651 141         253 $self->_parse_next_line(LEAF);
652             }
653 44 100       157 return $node if '+' eq $chomp;
654 41         441 $node =~ s/\n*\Z/\n/;
655 41 100       131 $node =~ s/\n\Z// if $chomp eq '-';
656 41         87 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   3236 my $self = shift;
663 2696   100     3039 while (@{$self->lines} and
  3225         4634  
664             $self->lines->[0] =~ m{^\s*(\#|$)}
665             ) {
666 529         626 shift @{$self->lines};
  529         746  
667 529         624 $self->{line}++;
668             }
669 2696         3654 $self->eos($self->{done} = not @{$self->lines});
  2696         4112  
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   2625 my $self = shift;
684 2227         3002 my ($type) = @_;
685 2227         3357 my $level = $self->level;
686 2227         3457 my $offset = $self->offset->[$level];
687 2227 50       4010 $self->die('YAML_EMIT_ERR_BAD_LEVEL') unless defined $offset;
688 2227         2274 shift @{$self->lines};
  2227         3451  
689 2227         2759 $self->eos($self->{done} = not @{$self->lines});
  2227         3336  
690 2227 100       3657 if ($self->eos) {
691 257         526 $self->offset->[$level + 1] = $offset + 1;
692 257         577 return;
693             }
694 1970         2947 $self->{line}++;
695              
696             # Determine the offset for a new leaf node
697             # TODO
698 1970 100 100     3129 if ($self->preface =~
    100          
699             qr/(?:^|\s)(?:$FOLD_CHAR|$LIT_CHAR_RX)(?:[+-]([0-9]*)|([0-9]*)[+-]?)(?:\s+#.*|\s*)$/
700             ) {
701 62 50       255 my $explicit_indent = defined $1 ? $1 : defined $2 ? $2 : '';
    100          
702 62 100 100     213 $self->die('YAML_PARSE_ERR_ZERO_INDENT')
703             if length($explicit_indent) and $explicit_indent == 0;
704 61         88 $type = LEAF;
705 61 100       116 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     82 while (@{$self->lines} && ($self->lines->[0] =~ /^\s*#/)) {
  53         106  
711 1         4 $self->lines->[0] =~ /^( *)/;
712 1 50       5 last unless length($1) <= $offset;
713 0         0 shift @{$self->lines};
  0         0  
714 0         0 $self->{line}++;
715             }
716 53         91 $self->eos($self->{done} = not @{$self->lines});
  53         107  
717 53 50       99 return if $self->eos;
718 53 100 66     114 if ($self->lines->[0] =~ /^( *)\S/ and length($1) > $offset) {
719 52         138 $self->offset->[$level+1] = length($1);
720             }
721             else {
722 1         4 $self->offset->[$level+1] = $offset + 1;
723             }
724             }
725 61         127 $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         1517 $self->_parse_throwaway_comments();
731 644         1124 my $zero_indent = $self->zero_indent;
732 644 50 100     1061 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         139 my $new_offset = length($1);
742 49         111 $self->offset->[$level+1] = $new_offset;
743 49 100       127 if ($new_offset == $offset) {
744 3         5 $zero_indent->[ $level+1 ] = 1;
745             }
746             }
747             else {
748 595 100       1133 $self->lines->[0] =~ /^( *)\S/ or
749             $self->die('YAML_PARSE_ERR_NONSPACE_INDENTATION');
750 594 100       1562 if (length($1) > $offset) {
751 585         1185 $self->offset->[$level+1] = length($1);
752             }
753             else {
754 9         25 $self->offset->[$level+1] = $offset + 1;
755             }
756             }
757 643         1332 $offset = $self->offset->[++$level];
758             }
759              
760 1968 100       4544 if ($type == LEAF) {
761 233 100 66     269 if (@{$self->lines} and
  233   100     384  
762             $self->lines->[0] =~ m{^( *)(\#)} and
763             length($1) < $offset
764             ) {
765 5 50       14 if ( length($1) < $offset) {
766 5         6 shift @{$self->lines};
  5         11  
767 5         6 $self->{line}++;
768             # every comment after that is also thrown away regardless
769             # of identation
770 5   100     7 while (@{$self->lines} and
  12         21  
771             $self->lines->[0] =~ m{^( *)(\#)}
772             ) {
773 7         11 shift @{$self->lines};
  7         12  
774 7         9 $self->{line}++;
775             }
776             }
777             }
778 233         313 $self->eos($self->{done} = not @{$self->lines});
  233         377  
779             }
780             else {
781 1735         3047 $self->_parse_throwaway_comments();
782             }
783 1968 100       3247 return if $self->eos;
784              
785 1961 100       3484 if ($self->lines->[0] =~ /^---(\s|$)/) {
786 38         94 $self->done(1);
787 38         132 return;
788             }
789 1923 100 100     4702 if ($type == LEAF and
    100          
790             $self->lines->[0] =~ /^ {$offset}(.*)$/
791             ) {
792 183         477 $self->indent($offset);
793 183         362 $self->content($1);
794             }
795             elsif ($self->lines->[0] =~ /^\s*$/) {
796 15         37 $self->indent($offset);
797 15         28 $self->content('');
798             }
799             else {
800 1725         2835 $self->lines->[0] =~ /^( *)(\S.*)$/;
801 1725         3340 while ($self->offset->[$level] > length($1)) {
802 397         708 $level--;
803             }
804 1725 100       2906 $self->die('YAML_PARSE_ERR_INCONSISTENT_INDENTATION')
805             if $self->offset->[$level] != length($1);
806 1720         4160 $self->indent(length($1));
807 1720         2828 $self->content($2);
808             }
809 1918 50       3203 $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   53 my $self = shift;
833 25         53 my ($node) = @_;
834 25         193 $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         66 return $node;
837             }
838              
839             1;