| 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; |