File Coverage

blib/lib/YAML/PP/Parser.pm
Criterion Covered Total %
statement 747 818 97.5
branch 204 238 85.7
condition 68 98 69.3
subroutine 126 137 97.8
pod 0 120 0.0
total 1145 1411 85.3


line stmt bran cond sub pod time code
1             # ABSTRACT: YAML Parser
2 42     42   366964 use strict;
  42         120  
  42         1246  
3 42     42   206 use warnings;
  42         84  
  42         2512  
4             package YAML::PP::Parser;
5              
6             our $VERSION = '0.036_002'; # TRIAL VERSION
7              
8 42 50   42   281 use constant TRACE => $ENV{YAML_PP_TRACE} ? 1 : 0;
  42         113  
  42         3756  
9 42 100 66 42   344 use constant DEBUG => ($ENV{YAML_PP_DEBUG} || $ENV{YAML_PP_TRACE}) ? 1 : 0;
  42         98  
  42         3167  
10              
11 42         2801 use YAML::PP::Common qw/
12             YAML_PLAIN_SCALAR_STYLE YAML_SINGLE_QUOTED_SCALAR_STYLE
13             YAML_DOUBLE_QUOTED_SCALAR_STYLE
14             YAML_LITERAL_SCALAR_STYLE YAML_FOLDED_SCALAR_STYLE
15             YAML_FLOW_SEQUENCE_STYLE YAML_FLOW_MAPPING_STYLE
16 42     42   2750 /;
  42         86  
17 42     42   17409 use YAML::PP::Render;
  42         107  
  42         1230  
18 42     42   21516 use YAML::PP::Lexer;
  42         140  
  42         1834  
19 42     42   322 use YAML::PP::Grammar qw/ $GRAMMAR /;
  42         94  
  42         3760  
20 42     42   18922 use YAML::PP::Exception;
  42         111  
  42         1346  
21 42     42   16803 use YAML::PP::Reader;
  42         105  
  42         1302  
22 42     42   275 use Carp qw/ croak /;
  42         85  
  42         38119  
23              
24              
25             sub new {
26 4658     4658 0 3622536 my ($class, %args) = @_;
27 4658   33     20138 my $reader = delete $args{reader} || YAML::PP::Reader->new;
28 4658         9125 my $default_yaml_version = delete $args{default_yaml_version};
29 4658   100     21056 my $self = bless {
30             default_yaml_version => $default_yaml_version || '1.2',
31             lexer => YAML::PP::Lexer->new(
32             reader => $reader,
33             ),
34             }, $class;
35 4658         9130 my $receiver = delete $args{receiver};
36 4658 100       10368 if ($receiver) {
37 3911         8872 $self->set_receiver($receiver);
38             }
39 4658         36118 return $self;
40             }
41              
42             sub clone {
43 9     9 0 17 my ($self) = @_;
44 9         19 my $clone = {
45             default_yaml_version => $self->default_yaml_version,
46             lexer => YAML::PP::Lexer->new(),
47             };
48 9         41 return bless $clone, ref $self;
49             }
50              
51 747     747 0 2184 sub receiver { return $_[0]->{receiver} }
52             sub set_receiver {
53 4667     4667 0 8309 my ($self, $receiver) = @_;
54 4667         6427 my $callback;
55 4667 100       12238 if (ref $receiver eq 'CODE') {
56 3911         5879 $callback = $receiver;
57             }
58             else {
59             $callback = sub {
60 21726     21726   37147 my ($self, $event, $info) = @_;
61 21726         67952 return $receiver->$event($info);
62 756         3410 };
63             }
64 4667         8232 $self->{callback} = $callback;
65 4667         8371 $self->{receiver} = $receiver;
66             }
67 4     4 0 13 sub reader { return $_[0]->lexer->{reader} }
68             sub set_reader {
69 7571     7571 0 12763 my ($self, $reader) = @_;
70 7571         13261 $self->lexer->set_reader($reader);
71             }
72 116692     116692 0 322643 sub lexer { return $_[0]->{lexer} }
73 83573     83573 0 224421 sub callback { return $_[0]->{callback} }
74 0     0 0 0 sub set_callback { $_[0]->{callback} = $_[1] }
75 19358     19358 0 28566 sub level { return $#{ $_[0]->{offset} } }
  19358         58946  
76 105226     105226 0 174759 sub offset { return $_[0]->{offset} }
77 7571     7571 0 13630 sub set_offset { $_[0]->{offset} = $_[1] }
78 160985     160985 0 264958 sub events { return $_[0]->{events} }
79 7571     7571 0 13390 sub set_events { $_[0]->{events} = $_[1] }
80 46601     46601 0 96588 sub new_node { return $_[0]->{new_node} }
81 69533     69533 0 124901 sub set_new_node { $_[0]->{new_node} = $_[1] }
82 2846     2846 0 6506 sub tagmap { return $_[0]->{tagmap} }
83 15576     15576 0 34375 sub set_tagmap { $_[0]->{tagmap} = $_[1] }
84 26257     26257 0 43821 sub tokens { return $_[0]->{tokens} }
85 7571     7571 0 34172 sub set_tokens { $_[0]->{tokens} = $_[1] }
86 104420     104420 0 170026 sub event_stack { return $_[0]->{event_stack} }
87 7571     7571 0 13185 sub set_event_stack { $_[0]->{event_stack} = $_[1] }
88 7580     7580 0 20783 sub default_yaml_version { return $_[0]->{default_yaml_version} }
89 8232     8232 0 21567 sub yaml_version { return $_[0]->{yaml_version} }
90 7729     7729 0 12963 sub set_yaml_version { $_[0]->{yaml_version} = $_[1] }
91 8353     8353 0 13117 sub yaml_version_directive { return $_[0]->{yaml_version_directive} }
92 15923     15923 0 25578 sub set_yaml_version_directive { $_[0]->{yaml_version_directive} = $_[1] }
93              
94 24432     24432 0 50568 sub rule { return $_[0]->{rule} }
95             sub set_rule {
96 141912     141912 0 244969 my ($self, $name) = @_;
97 42     42   346 no warnings 'uninitialized';
  42         135  
  42         400351  
98 141912         177060 DEBUG and $self->info("set_rule($name)");
99 141912         245687 $self->{rule} = $name;
100             }
101              
102             sub init {
103 7571     7571 0 11382 my ($self) = @_;
104 7571         18820 $self->set_offset([]);
105 7571         17524 $self->set_events([]);
106 7571         17338 $self->set_new_node(0);
107 7571         21707 $self->set_tagmap({
108             '!!' => "tag:yaml.org,2002:",
109             });
110 7571         18840 $self->set_tokens([]);
111 7571         17911 $self->set_rule(undef);
112 7571         17738 $self->set_event_stack([]);
113 7571         14490 $self->set_yaml_version($self->default_yaml_version);
114 7571         16928 $self->set_yaml_version_directive(undef);
115 7571         13641 $self->lexer->init;
116             }
117              
118             sub parse_string {
119 5383     5383 0 76951 my ($self, $yaml) = @_;
120 5383         13439 $self->set_reader(YAML::PP::Reader->new( input => $yaml ));
121 5383         12187 $self->parse();
122             }
123              
124             sub parse_file {
125 0     0 0 0 my ($self, $file) = @_;
126 0         0 $self->set_reader(YAML::PP::Reader::File->new( input => $file ));
127 0         0 $self->parse();
128             }
129              
130             my %nodetypes = (
131             MAPVALUE => 'NODETYPE_COMPLEX',
132             MAP => 'NODETYPE_MAP',
133             # IMAP => 'NODETYPE_SEQ',
134             SEQ => 'NODETYPE_SEQ',
135             SEQ0 => 'NODETYPE_SEQ',
136             FLOWMAP => 'NODETYPE_FLOWMAP',
137             FLOWMAPVALUE => 'NODETYPE_FLOWMAPVALUE',
138             FLOWSEQ => 'NODETYPE_FLOWSEQ',
139             FLOWSEQ_NEXT => 'FLOWSEQ_NEXT',
140             DOC => 'FULLNODE',
141             DOC_END => 'DOCUMENT_END',
142             STR => 'STREAM',
143             END_FLOW => 'END_FLOW',
144             );
145              
146             sub parse {
147 7571     7571 0 12552 my ($self) = @_;
148 7571         9877 TRACE and warn "=== parse()\n";
149 7571         9575 TRACE and $self->debug_yaml;
150 7571         17509 $self->init;
151 7571         13816 $self->lexer->init;
152 7571         11487 eval {
153 7571         18406 $self->start_stream;
154 7571         30171 $self->set_rule( 'STREAM' );
155              
156 7571         18828 $self->parse_tokens();
157              
158 7416         14421 $self->end_stream;
159             };
160 7571 100       27833 if (my $error = $@) {
161 155 100       397 if (ref $error) {
162 124         356 croak "$error\n ";
163             }
164 31         2671 croak $error;
165             }
166              
167 7416         10050 DEBUG and $self->highlight_yaml;
168 7416         15714 TRACE and $self->debug_tokens;
169             }
170              
171             sub lex_next_tokens {
172 31903     31903 0 51339 my ($self) = @_;
173              
174 31903         40155 DEBUG and $self->info("----------------> lex_next_tokens");
175 31903         39075 TRACE and $self->debug_events;
176              
177 31903         52414 my $indent = $self->offset->[-1];
178 31903         53140 my $event_types = $self->events;
179 31903         57948 my $next_tokens = $self->lexer->fetch_next_tokens($indent);
180 31868 100       73542 return unless @$next_tokens;
181              
182 24443         36088 my $next = $next_tokens->[0];
183              
184 24443 100       61832 return 1 if ($next->{name} ne 'SPACE');
185 18371         36297 my $flow = $event_types->[-1] =~ m/^FLOW/;
186 18371         33875 my $space = length $next->{value};
187 18371         38889 my $tokens = $self->tokens;
188              
189 18371 100       35183 if (not $space) {
190 13988         22158 shift @$next_tokens;
191             }
192             else {
193 4383         9119 push @$tokens, shift @$next_tokens;
194             }
195 18371 100       34148 if ($flow) {
196 678 100       1737 if ($space >= $indent) {
197 675         2047 return 1;
198             }
199 3         14 $self->exception("Bad indendation in " . $self->events->[-1]);
200             }
201 17693         38920 $next = $next_tokens->[0];
202 17693 100       36197 if ($space > $indent ) {
203 7856 100       23121 return 1 if $indent < 0;
204 1823 100       3792 unless ($self->new_node) {
205 4         13 $self->exception("Bad indendation in " . $self->events->[-1]);
206             }
207 1819         4823 return 1;
208             }
209 9837 100       19635 if ($self->new_node) {
210 1287 100       3017 if ($space < $indent) {
211 437         1982 $self->scalar_event({ style => YAML_PLAIN_SCALAR_STYLE, value => '' });
212 437         1124 $self->remove_nodes($space);
213             }
214             else {
215             # unindented sequence starts
216 850         1820 my $exp = $self->events->[-1];
217 850         1757 my $seq_start = $next->{name} eq 'DASH';
218 850 100 100     3869 if ( $seq_start and ($exp eq 'MAPVALUE' or $exp eq 'MAP')) {
      100        
219             }
220             else {
221 289         1215 $self->scalar_event({ style => YAML_PLAIN_SCALAR_STYLE, value => '' });
222             }
223             }
224             }
225             else {
226 8550 100       16919 if ($space < $indent) {
227 1905         4578 $self->remove_nodes($space);
228             }
229             }
230              
231 9837         17672 my $exp = $self->events->[-1];
232              
233 9837 100 100     24344 if ($exp eq 'SEQ0' and $next->{name} ne 'DASH') {
234 240         604 TRACE and $self->info("In unindented sequence");
235 240         711 $self->end_sequence;
236 240         575 $exp = $self->events->[-1];
237             }
238              
239 9837 100       18571 if ($self->offset->[-1] != $space) {
240 4         20 $self->exception("Expected " . $self->events->[-1]);
241             }
242 9833         25913 return 1;
243             }
244              
245             my %next_event = (
246             MAP => 'MAPVALUE',
247             IMAP => 'IMAPVALUE',
248             MAPVALUE => 'MAP',
249             IMAPVALUE => 'IMAP',
250             SEQ => 'SEQ',
251             SEQ0 => 'SEQ0',
252             DOC => 'DOC_END',
253             STR => 'STR',
254             FLOWSEQ => 'FLOWSEQ_NEXT',
255             FLOWSEQ_NEXT => 'FLOWSEQ',
256             FLOWMAP => 'FLOWMAPVALUE',
257             FLOWMAPVALUE => 'FLOWMAP',
258             );
259              
260             my %event_to_method = (
261             MAP => 'mapping',
262             IMAP => 'mapping',
263             FLOWMAP => 'mapping',
264             SEQ => 'sequence',
265             SEQ0 => 'sequence',
266             FLOWSEQ => 'sequence',
267             DOC => 'document',
268             STR => 'stream',
269             VAL => 'scalar',
270             ALI => 'alias',
271             MAPVALUE => 'mapping',
272             IMAPVALUE => 'mapping',
273             );
274              
275             #sub process_events {
276             # my ($self, $res) = @_;
277             #
278             # my $event_stack = $self->event_stack;
279             # return unless @$event_stack;
280             #
281             # if (@$event_stack == 1 and $event_stack->[0]->[0] eq 'properties') {
282             # return;
283             # }
284             #
285             # my $event_types = $self->events;
286             # my $properties;
287             # my @send_events;
288             # for my $event (@$event_stack) {
289             # TRACE and warn __PACKAGE__.':'.__LINE__.$".Data::Dumper->Dump([\$event], ['event']);
290             # my ($type, $info) = @$event;
291             # if ($type eq 'properties') {
292             # $properties = $info;
293             # }
294             # elsif ($type eq 'scalar') {
295             # $info->{name} = 'scalar_event';
296             # $event_types->[-1] = $next_event{ $event_types->[-1] };
297             # push @send_events, $info;
298             # }
299             # elsif ($type eq 'begin') {
300             # my $name = $info->{name};
301             # $info->{name} = $event_to_method{ $name } . '_start_event';
302             # push @{ $event_types }, $name;
303             # push @{ $self->offset }, $info->{offset};
304             # push @send_events, $info;
305             # }
306             # elsif ($type eq 'end') {
307             # my $name = $info->{name};
308             # $info->{name} = $event_to_method{ $name } . '_end_event';
309             # $self->$type($name, $info);
310             # push @send_events, $info;
311             # if (@$event_types) {
312             # $event_types->[-1] = $next_event{ $event_types->[-1] };
313             # }
314             # }
315             # elsif ($type eq 'alias') {
316             # if ($properties) {
317             # $self->exception("Parse error: Alias not allowed in this context");
318             # }
319             # $info->{name} = 'alias_event';
320             # $event_types->[-1] = $next_event{ $event_types->[-1] };
321             # push @send_events, $info;
322             # }
323             # }
324             # @$event_stack = ();
325             # for my $info (@send_events) {
326             # DEBUG and $self->debug_event( $info );
327             # $self->callback->($self, $info->{name}, $info);
328             # }
329             #}
330              
331             my %fetch_method = (
332             '"' => 'fetch_quoted',
333             "'" => 'fetch_quoted',
334             '|' => 'fetch_block',
335             '>' => 'fetch_block',
336             '' => 'fetch_plain',
337             );
338              
339             sub parse_tokens {
340 7571     7571 0 11428 my ($self) = @_;
341 7571         12582 my $event_types = $self->events;
342 7571         13046 my $offsets = $self->offset;
343 7571         13542 my $tokens = $self->tokens;
344 7571         12719 my $next_tokens = $self->lexer->next_tokens;
345              
346 7571 100       14777 unless ($self->lex_next_tokens) {
347 69         225 $self->end_document(1);
348 69         185 return 0;
349             }
350 7468 50       16304 unless ($self->new_node) {
351 7468 50       14195 if ($self->level > 0) {
352 0 0       0 my $new_rule = $nodetypes{ $event_types->[-1] }
353             or die "Did not find '$event_types->[-1]'";
354 0         0 $self->set_rule( $new_rule );
355             }
356             }
357              
358 7468         14830 my $rule_name = $self->rule;
359 7468         10766 DEBUG and $self->info("----------------> parse_tokens($rule_name)");
360 7468 50       18688 my $rule = $GRAMMAR->{ $rule_name }
361             or die "Could not find rule $rule_name";
362              
363 7468         9560 TRACE and $self->debug_rules($rule);
364 7468         9366 TRACE and $self->debug_yaml;
365 7468         9898 DEBUG and $self->debug_next_line;
366              
367 7468         13936 RULE: while ($rule_name) {
368 201676         242563 DEBUG and $self->info("RULE: $rule_name");
369 201676         232120 TRACE and $self->debug_tokens($next_tokens);
370              
371 201676 50       338215 unless (@$next_tokens) {
372 0         0 $self->exception("No more tokens");
373             }
374 201676         236501 TRACE and warn __PACKAGE__.':'.__LINE__.$".Data::Dumper->Dump([\$next_tokens->[0]], ['next_token']);
375 201676         303341 my $got = $next_tokens->[0]->{name};
376 201676 100       348884 if ($got eq 'CONTEXT') {
377 26958         39369 my $context = shift @$next_tokens;
378 26958         41601 my $indent = $offsets->[-1];
379 26958 100       50002 $indent++ unless $self->lexer->flowcontext;
380 26958         55873 my $method = $fetch_method{ $context->{value} };
381 26958         44344 my $partial = $self->lexer->$method($indent, $context->{value});
382 26932         94120 next RULE;
383             }
384 174718         275562 my $def = $rule->{ $got };
385 174718 100       312130 if ($def) {
    100          
386 113624         196622 push @$tokens, shift @$next_tokens;
387             }
388             elsif ($def = $rule->{DEFAULT}) {
389 61046         83889 $got = 'DEFAULT';
390             }
391             else {
392 48         241 $self->expected(
393             expected => [keys %$rule],
394             got => $next_tokens->[0],
395             );
396             }
397              
398 174670         218282 DEBUG and $self->got("---got $got");
399 174670 100       341261 if (my $sub = $def->{match}) {
400 83025         98862 DEBUG and $self->info("CALLBACK $sub");
401 83025 100       253479 $self->$sub(@$tokens ? $tokens->[-1] : ());
402             }
403 174644         266903 my $eol = $got eq 'EOL';
404 174644         257515 my $new = $def->{new};
405 174644 100       339095 if ($new) {
    100          
    100          
406 93141         114460 DEBUG and $self->got("NEW: $new");
407 93141         128139 $rule_name = $new;
408 93141         165682 $self->set_rule($rule_name);
409             }
410             elsif ($eol) {
411             }
412             elsif ($def->{return}) {
413 6344 50       16840 $rule_name = $nodetypes{ $event_types->[-1] }
414             or die "Unexpected event type $event_types->[-1]";
415 6344         12079 $self->set_rule($rule_name);
416             }
417             else {
418 58358         112608 $rule_name .= " - $got"; # for debugging
419 58358         78788 $rule = $def;
420 58358         131337 next RULE;
421             }
422 116286 100       205778 if ($eol) {
423 24332 100       46975 unless ($self->lex_next_tokens) {
424 7356 100       15383 if ($rule_name eq 'DIRECTIVE') {
425 1         4 $self->exception("Directive needs document start");
426             }
427 7355         17713 $self->end_document(1);
428 7347         18062 return 0;
429             }
430 16964 100       31847 unless ($self->new_node) {
431 11890 100       20950 if ($self->level > 0) {
432 11013 50       30221 $rule_name = $nodetypes{ $event_types->[-1] }
433             or die "Did not find '$event_types->[-1]'";
434 11013         21605 $self->set_rule( $rule_name );
435             }
436             }
437 16964         31784 $rule_name = $self->rule;
438             }
439 108918 50       305434 $rule = $GRAMMAR->{ $rule_name }
440             or die "Unexpected rule $rule_name";
441              
442             }
443              
444 0         0 die "Unexpected";
445             }
446              
447             sub end_sequence {
448 240     240 0 553 my ($self) = @_;
449 240         487 my $event_types = $self->events;
450 240         350 pop @{ $event_types };
  240         423  
451 240         392 pop @{ $self->offset };
  240         519  
452 240         651 my $info = { name => 'sequence_end_event' };
453 240         610 $self->callback->($self, $info->{name} => $info );
454 240         1073 $event_types->[-1] = $next_event{ $event_types->[-1] };
455             }
456              
457             sub remove_nodes {
458 10897     10897 0 18664 my ($self, $space) = @_;
459 10897         19577 my $offset = $self->offset;
460 10897         17807 my $event_types = $self->events;
461              
462 10897         18184 my $exp = $event_types->[-1];
463 10897         21573 while (@$offset) {
464 19142 100       36418 if ($offset->[ -1 ] <= $space) {
465 10890         16861 last;
466             }
467 8252 100       15562 if ($exp eq 'MAPVALUE') {
468 51         315 $self->scalar_event({ style => YAML_PLAIN_SCALAR_STYLE, value => '' });
469 51         147 $exp = 'MAP';
470             }
471 8252         17362 my $info = { name => $exp };
472 8252         20635 $info->{name} = $event_to_method{ $exp } . '_end_event';
473 8252         11366 pop @{ $event_types };
  8252         11938  
474 8252         11309 pop @{ $offset };
  8252         10969  
475 8252         16603 $self->callback->($self, $info->{name} => $info );
476 8245         27090 $event_types->[-1] = $next_event{ $event_types->[-1] };
477 8245         19658 $exp = $event_types->[-1];
478             }
479 10890         17614 return $exp;
480             }
481              
482             sub start_stream {
483 7571     7571 0 11994 my ($self) = @_;
484 7571         10141 push @{ $self->events }, 'STR';
  7571         13194  
485 7571         11309 push @{ $self->offset }, -1;
  7571         15135  
486 7571         19056 $self->callback->($self, 'stream_start_event', {
487             name => 'stream_start_event',
488             });
489             }
490              
491             sub start_document {
492 8194     8194 0 13784 my ($self, $implicit) = @_;
493 8194         11112 push @{ $self->events }, 'DOC';
  8194         14716  
494 8194         12212 push @{ $self->offset }, -1;
  8194         14151  
495 8194         15706 my $directive = $self->yaml_version_directive;
496 8194         11477 my %directive;
497 8194 100       15776 if ($directive) {
498 154         590 my ($major, $minor) = split m/\./, $self->yaml_version;
499 154         872 %directive = ( version_directive => { major => $major, minor => $minor } );
500             }
501 8194         28478 $self->callback->($self, 'document_start_event', {
502             name => 'document_start_event',
503             implicit => $implicit,
504             %directive,
505             });
506 8194         32359 $self->set_yaml_version_directive(undef);
507 8194         17990 $self->set_rule( 'FULLNODE' );
508 8194         15142 $self->set_new_node(1);
509             }
510              
511             sub start_sequence {
512 3222     3222 0 5647 my ($self, $offset) = @_;
513 3222         5925 my $offsets = $self->offset;
514 3222 100       7002 if ($offsets->[-1] == $offset) {
515 561         863 push @{ $self->events }, 'SEQ0';
  561         1067  
516             }
517             else {
518 2661         3739 push @{ $self->events }, 'SEQ';
  2661         4791  
519             }
520 3222         4566 push @{ $offsets }, $offset;
  3222         4789  
521 3222         6218 my $event_stack = $self->event_stack;
522 3222         7053 my $info = { name => 'sequence_start_event' };
523 3222 100 66     8400 if (@$event_stack and $event_stack->[-1]->[0] eq 'properties') {
524 227         473 my $properties = pop @$event_stack;
525 227         656 $self->node_properties($properties->[1], $info);
526             }
527 3222         6930 $self->callback->($self, 'sequence_start_event', $info);
528             }
529              
530             sub start_flow_sequence {
531 1361     1361 0 2384 my ($self, $offset) = @_;
532 1361         2557 my $offsets = $self->offset;
533 1361         2325 my $new_offset = $offsets->[-1];
534 1361         2436 my $event_types = $self->events;
535 1361 100       3368 if ($new_offset < 0) {
    100          
536 153         284 $new_offset = 0;
537             }
538             elsif ($self->new_node) {
539 1149 100       3408 if ($event_types->[-1] !~ m/^FLOW/) {
540 982         1537 $new_offset++;
541             }
542             }
543 1361         2092 push @{ $self->events }, 'FLOWSEQ';
  1361         2410  
544 1361         1959 push @{ $offsets }, $new_offset;
  1361         2211  
545              
546 1361         2522 my $event_stack = $self->event_stack;
547 1361         3835 my $info = { style => YAML_FLOW_SEQUENCE_STYLE, name => 'sequence_start_event' };
548 1361 100 66     3677 if (@$event_stack and $event_stack->[-1]->[0] eq 'properties') {
549 38         229 $self->fetch_inline_properties($event_stack, $info);
550             }
551 1361         2721 $self->callback->($self, 'sequence_start_event', $info);
552             }
553              
554             sub start_flow_mapping {
555 1118     1118 0 2553 my ($self, $offset, $implicit_flowseq_map) = @_;
556 1118         2153 my $offsets = $self->offset;
557 1118         1877 my $new_offset = $offsets->[-1];
558 1118         2035 my $event_types = $self->events;
559 1118 100       2989 if ($new_offset < 0) {
    100          
560 372         679 $new_offset = 0;
561             }
562             elsif ($self->new_node) {
563 648 100       1897 if ($event_types->[-1] !~ m/^FLOW/) {
564 570         887 $new_offset++;
565             }
566             }
567 1118 100       1720 push @{ $self->events }, $implicit_flowseq_map ? 'IMAP' : 'FLOWMAP';
  1118         1832  
568 1118         1688 push @{ $offsets }, $new_offset;
  1118         1801  
569              
570 1118         2122 my $event_stack = $self->event_stack;
571 1118         3482 my $info = { name => 'mapping_start_event', style => YAML_FLOW_MAPPING_STYLE };
572 1118 100 66     3181 if (@$event_stack and $event_stack->[-1]->[0] eq 'properties') {
573 69         182 $self->fetch_inline_properties($event_stack, $info);
574             }
575 1118         2341 $self->callback->($self, 'mapping_start_event', $info);
576             }
577              
578             sub end_flow_sequence {
579 1349     1349 0 2525 my ($self) = @_;
580 1349         2348 my $event_types = $self->events;
581 1349         1883 pop @{ $event_types };
  1349         2073  
582 1349         1900 pop @{ $self->offset };
  1349         2380  
583 1349         3288 my $info = { name => 'sequence_end_event' };
584 1349         2931 $self->callback->($self, $info->{name}, $info);
585 1349 100       6645 if ($event_types->[-1] =~ m/^FLOW|^IMAP/) {
586 226         710 $event_types->[-1] = $next_event{ $event_types->[-1] };
587             }
588             else {
589 1123         2670 push @$event_types, 'END_FLOW';
590             }
591             }
592              
593             sub end_flow_mapping {
594 1116     1116 0 1992 my ($self) = @_;
595 1116         2032 my $event_types = $self->events;
596 1116         1604 pop @{ $event_types };
  1116         1651  
597 1116         1601 pop @{ $self->offset };
  1116         1975  
598 1116         2574 my $info = { name => 'mapping_end_event' };
599 1116         2420 $self->callback->($self, $info->{name}, $info);
600 1108 100       5276 if ($event_types->[-1] =~ m/^FLOW|^IMAP/) {
601 176         480 $event_types->[-1] = $next_event{ $event_types->[-1] };
602             }
603             else {
604 932         2096 push @$event_types, 'END_FLOW';
605             }
606             }
607              
608             sub cb_end_outer_flow {
609 2049     2049 0 3822 my ($self) = @_;
610 2049         3584 my $event_types = $self->events;
611 2049         3130 pop @$event_types;
612 2049         4423 $event_types->[-1] = $next_event{ $event_types->[-1] };
613             }
614              
615             sub start_mapping {
616 5353     5353 0 9367 my ($self, $offset) = @_;
617 5353         9803 my $offsets = $self->offset;
618 5353         7564 push @{ $self->events }, 'MAP';
  5353         9289  
619 5353         7954 push @{ $offsets }, $offset;
  5353         7869  
620 5353         8779 my $event_stack = $self->event_stack;
621 5353         11283 my $info = { name => 'mapping_start_event' };
622 5353 100 66     13875 if (@$event_stack and $event_stack->[-1]->[0] eq 'properties') {
623 492         887 my $properties = pop @$event_stack;
624 492         1278 $self->node_properties($properties->[1], $info);
625             }
626 5353         10869 $self->callback->($self, 'mapping_start_event', $info);
627             }
628              
629             sub end_document {
630 8556     8556 0 14465 my ($self, $implicit) = @_;
631              
632 8556         15846 my $event_types = $self->events;
633 8556 100       21378 if ($event_types->[-1] =~ m/FLOW/) {
634 1         9 die "Unexpected end of flow context";
635             }
636 8555 100       14554 if ($self->new_node) {
637 499         2150 $self->scalar_event({ style => YAML_PLAIN_SCALAR_STYLE, value => '' });
638             }
639 8555         25269 $self->remove_nodes(-1);
640              
641 8548 100       17887 if ($event_types->[-1] eq 'STR') {
642 470         951 return;
643             }
644 8078         10623 my $last = pop @{ $event_types };
  8078         12953  
645 8078 50 33     30680 if ($last ne 'DOC' and $last ne 'DOC_END') {
646 0         0 $self->exception("Unexpected event type $last");
647             }
648 8078         10880 pop @{ $self->offset };
  8078         13894  
649 8078         24783 $self->callback->($self, 'document_end_event', {
650             name => 'document_end_event',
651             implicit => $implicit,
652             });
653 8078 100       26536 if ($self->yaml_version eq '1.2') {
654             # In YAML 1.2, directives are only for the following
655             # document. In YAML 1.1, they are global
656 8005         20114 $self->set_tagmap({ '!!' => "tag:yaml.org,2002:" });
657             }
658 8078         16845 $event_types->[-1] = $next_event{ $event_types->[-1] };
659 8078         16617 $self->set_rule('STREAM');
660             }
661              
662             sub end_stream {
663 7416     7416 0 11988 my ($self) = @_;
664 7416         10028 my $last = pop @{ $self->events };
  7416         11937  
665 7416 50       17922 $self->exception("Unexpected event type $last") unless $last eq 'STR';
666 7416         9547 pop @{ $self->offset };
  7416         11734  
667 7416         18473 $self->callback->($self, 'stream_end_event', {
668             name => 'stream_end_event',
669             });
670             }
671              
672             sub fetch_inline_properties {
673 3424     3424 0 6368 my ($self, $stack, $info) = @_;
674 3424         5381 my $properties = $stack->[-1];
675              
676 3424         4960 $properties = $properties->[1];
677 3424         4594 my $property_offset;
678 3424 50       6911 if ($properties) {
679 3424         4744 for my $p (@{ $properties->{inline} }) {
  3424         7901  
680 3472         5547 my $type = $p->{type};
681 3472 50       6830 if (exists $info->{ $type }) {
682 0         0 $self->exception("A node can only have one $type");
683             }
684 3472         6978 $info->{ $type } = $p->{value};
685 3472 100       7114 unless (defined $property_offset) {
686 3032         4513 $property_offset = $p->{offset};
687 3032         6115 $info->{offset} = $p->{offset};
688             }
689             }
690 3424         9368 delete $properties->{inline};
691 3424 100       8043 undef $properties unless $properties->{newline};
692             }
693              
694 3424 100       8152 unless ($properties) {
695 2895         5065 pop @$stack;
696             }
697             }
698              
699             sub node_properties {
700 1164     1164 0 2401 my ($self, $properties, $info) = @_;
701 1164 50       2510 if ($properties) {
702 1164         1568 for my $p (@{ $properties->{newline} }) {
  1164         2588  
703 1336         2208 my $type = $p->{type};
704 1336 100       2768 if (exists $info->{ $type }) {
705 1         5 $self->exception("A node can only have one $type");
706             }
707 1335         3250 $info->{ $type } = $p->{value};
708             }
709 1163         4264 undef $properties;
710             }
711             }
712              
713             sub scalar_event {
714 29756     29756 0 49386 my ($self, $info) = @_;
715 29756         52375 my $event_types = $self->events;
716 29756         51414 my $event_stack = $self->event_stack;
717 29756 100 66     64679 if (@$event_stack and $event_stack->[-1]->[0] eq 'properties') {
718 445         803 my $properties = pop @$event_stack;
719 445         1077 $properties = $self->node_properties($properties->[1], $info);
720             }
721              
722 29755         54867 $info->{name} = 'scalar_event';
723 29755         58005 $self->callback->($self, 'scalar_event', $info);
724 29746         110995 $self->set_new_node(0);
725 29746         68206 $event_types->[-1] = $next_event{ $event_types->[-1] };
726             }
727              
728             sub alias_event {
729 550     550 0 1068 my ($self, $info) = @_;
730 550         991 my $event_stack = $self->event_stack;
731 550 100 66     1443 if (@$event_stack and $event_stack->[-1]->[0] eq 'properties') {
732 2         6 $self->exception("Parse error: Alias not allowed in this context");
733             }
734 548         1031 my $event_types = $self->events;
735 548         1089 $info->{name} = 'alias_event';
736 548         1223 $self->callback->($self, 'alias_event', $info);
737 545         2157 $self->set_new_node(0);
738 545         1526 $event_types->[-1] = $next_event{ $event_types->[-1] };
739             }
740              
741             sub yaml_to_tokens {
742 5     5 0 4867 my ($class, $type, $input) = @_;
743 5     38   29 my $yp = YAML::PP::Parser->new( receiver => sub {} );
744 5         10 my @docs = eval {
745 5 50       17 $type eq 'string' ? $yp->parse_string($input) : $yp->parse_file($input);
746             };
747 5         12 my $error = $@;
748              
749 5         9 my $tokens = $yp->tokens;
750 5 100       11 if ($error) {
751 1         6 my $remaining_tokens = $yp->_remaining_tokens;
752 1         3 push @$tokens, map { +{ %$_, name => 'ERROR' } } @$remaining_tokens;
  1         7  
753             }
754 5         85 return $error, $tokens;
755             }
756              
757             sub _remaining_tokens {
758 1     1   6 my ($self) = @_;
759 1         2 my @tokens;
760 1         2 my $next = $self->lexer->next_tokens;
761 1         3 push @tokens, @$next;
762 1         51 my $next_line = $self->lexer->next_line;
763 1         3 my $remaining = '';
764 1 50       4 if ($next_line) {
765 1 50       4 if ($self->lexer->offset > 0) {
766 1         4 $remaining = $next_line->[1] . $next_line->[2];
767             }
768             else {
769 0         0 $remaining = join '', @$next_line;
770             }
771             }
772 1         3 $remaining .= $self->reader->read;
773 1 50       7 $remaining = '' unless defined $remaining;
774 1         6 push @tokens, { name => "ERROR", value => $remaining };
775 1         3 return \@tokens;
776             }
777              
778             # deprecated
779             sub event_to_test_suite {
780             # uncoverable subroutine
781 0     0 0 0 my ($self, $event) = @_; # uncoverable statement
782 0 0       0 if (ref $event eq 'ARRAY') { # uncoverable statement
783 0         0 return YAML::PP::Common::event_to_test_suite($event->[1]); # uncoverable statement
784             }
785 0         0 return YAML::PP::Common::event_to_test_suite($event); # uncoverable statement
786             }
787              
788             sub debug_events {
789             # uncoverable subroutine
790 0     0 0 0 my ($self) = @_; # uncoverable statement
791             $self->note("EVENTS: (" # uncoverable statement
792 0         0 . join (' | ', @{ $_[0]->events }) . ')' # uncoverable statement
  0         0  
793             );
794 0         0 $self->debug_offset; # uncoverable statement
795             }
796              
797             sub debug_offset {
798             # uncoverable subroutine
799 0     0 0 0 my ($self) = @_; # uncoverable statement
800             $self->note(
801             qq{OFFSET: (}
802             # uncoverable statement count:1
803             # uncoverable statement count:2
804             # uncoverable statement count:3
805 0 0       0 . join (' | ', map { defined $_ ? sprintf "%-3d", $_ : '?' } @{ $_[0]->offset })
  0         0  
  0         0  
806             # uncoverable statement
807 0         0 . qq/) level=@{[ $_[0]->level ]}]}/
808             );
809             }
810              
811             sub debug_yaml {
812             # uncoverable subroutine
813 0     0 0 0 my ($self) = @_; # uncoverable statement
814 0         0 my $line = $self->lexer->line; # uncoverable statement
815 0         0 $self->note("LINE NUMBER: $line"); # uncoverable statement
816 0         0 my $next_tokens = $self->lexer->next_tokens; # uncoverable statement
817 0 0       0 if (@$next_tokens) { # uncoverable statement
818 0         0 $self->debug_tokens($next_tokens); # uncoverable statement
819             }
820             }
821              
822             sub debug_next_line {
823 1     1 0 4 my ($self) = @_;
824 1   50     3 my $next_line = $self->lexer->next_line || [];
825 1         2 my $line = $next_line->[0];
826 1 50       10 $line = '' unless defined $line;
827 1         4 $line =~ s/( +)$/'·' x length $1/e;
  0         0  
828 1         2 $line =~ s/\t/â–¸/g;
829 1         6 $self->note("NEXT LINE: >>$line<<");
830             }
831              
832             sub note {
833 1     1 0 3 my ($self, $msg) = @_;
834 1         5 $self->_colorize_warn(["yellow"], "============ $msg");
835             }
836              
837             sub info {
838 28     28 0 41 my ($self, $msg) = @_;
839 28         81 $self->_colorize_warn(["cyan"], "============ $msg");
840             }
841              
842             sub got {
843 14     14 0 24 my ($self, $msg) = @_;
844 14         36 $self->_colorize_warn(["green"], "============ $msg");
845             }
846              
847             sub _colorize_warn {
848             # uncoverable subroutine
849 0     0   0 my ($self, $colors, $text) = @_; # uncoverable statement
850 0         0 require Term::ANSIColor; # uncoverable statement
851 0         0 warn Term::ANSIColor::colored($colors, $text), "\n"; # uncoverable statement
852             }
853              
854             sub debug_event {
855             # uncoverable subroutine
856 0     0 0 0 my ($self, $event) = @_; # uncoverable statement
857 0         0 my $str = YAML::PP::Common::event_to_test_suite($event); # uncoverable statement
858 0         0 require Term::ANSIColor; # uncoverable statement
859 0         0 warn Term::ANSIColor::colored(["magenta"], "============ $str"), "\n"; # uncoverable statement
860             }
861              
862             sub debug_rules {
863             # uncoverable subroutine
864 0     0 0 0 my ($self, $rules) = @_; # uncoverable statement
865 0         0 local $Data::Dumper::Maxdepth = 2; # uncoverable statement
866 0         0 $self->note("RULES:"); # uncoverable statement
867 0         0 for my $rule ($rules) { # uncoverable statement
868 0 0       0 if (ref $rule eq 'ARRAY') { # uncoverable statement
869 0         0 my $first = $rule->[0]; # uncoverable statement
870 0 0       0 if (ref $first eq 'SCALAR') { # uncoverable statement
871 0         0 $self->info("-> $$first"); # uncoverable statement
872             }
873             else { # uncoverable statement
874 0 0       0 if (ref $first eq 'ARRAY') { # uncoverable statement
875 0         0 $first = $first->[0]; # uncoverable statement
876             }
877 0         0 $self->info("TYPE $first"); # uncoverable statement
878             }
879             }
880             else { # uncoverable statement
881 0         0 eval { # uncoverable statement
882 0         0 my @keys = sort keys %$rule; # uncoverable statement
883 0         0 $self->info("@keys"); # uncoverable statement
884             };
885             }
886             }
887             }
888              
889             sub debug_tokens {
890             # uncoverable subroutine
891 0     0 0 0 my ($self, $tokens) = @_; # uncoverable statement
892 0   0     0 $tokens ||= $self->tokens; # uncoverable statement
893 0         0 require Term::ANSIColor; # uncoverable statement
894 0         0 for my $token (@$tokens) { # uncoverable statement
895             my $type = Term::ANSIColor::colored(["green"], # uncoverable statement
896             sprintf "%-22s L %2d C %2d ", # uncoverable statement
897 0         0 $token->{name}, $token->{line}, $token->{column} + 1 # uncoverable statement
898             );
899 0         0 local $Data::Dumper::Useqq = 1; # uncoverable statement
900 0         0 local $Data::Dumper::Terse = 1; # uncoverable statement
901 0         0 require Data::Dumper; # uncoverable statement
902 0         0 my $str = Data::Dumper->Dump([$token->{value}], ['str']); # uncoverable statement
903 0         0 chomp $str; # uncoverable statement
904 0         0 $str =~ s/(^.|.$)/Term::ANSIColor::colored(['blue'], $1)/ge; # uncoverable statement
  0         0  
905 0         0 warn "$type$str\n"; # uncoverable statement
906             }
907              
908             }
909              
910             sub highlight_yaml {
911 0     0 0 0 my ($self) = @_;
912 0         0 require YAML::PP::Highlight;
913 0         0 my $tokens = $self->tokens;
914 0         0 my $highlighted = YAML::PP::Highlight->ansicolored($tokens);
915 0         0 warn $highlighted;
916             }
917              
918             sub exception {
919 63     63 0 178 my ($self, $msg, %args) = @_;
920 63         130 my $next = $self->lexer->next_tokens;
921 63 100       158 my $line = @$next ? $next->[0]->{line} : $self->lexer->line;
922 63 100       129 my $offset = @$next ? $next->[0]->{column} : $self->lexer->offset;
923 63         82 $offset++;
924 63         104 my $next_line = $self->lexer->next_line;
925 63         115 my $remaining = '';
926 63 100       119 if ($next_line) {
927 38 100       77 if ($self->lexer->offset > 0) {
928 36         73 $remaining = $next_line->[1] . $next_line->[2];
929             }
930             else {
931 2         7 $remaining = join '', @$next_line;
932             }
933             }
934 63   100     259 my $caller = $args{caller} || [ caller(0) ];
935             my $e = YAML::PP::Exception->new(
936             got => $args{got},
937             expected => $args{expected},
938 63         324 line => $line,
939             column => $offset,
940             msg => $msg,
941             next => $next,
942             where => $caller->[1] . ' line ' . $caller->[2],
943             yaml => $remaining,
944             );
945 63         1356 croak $e;
946             }
947              
948             sub expected {
949 48     48 0 140 my ($self, %args) = @_;
950 48         78 my $expected = $args{expected};
951 48         98 @$expected = sort grep { m/^[A-Z_]+$/ } @$expected;
  222         792  
952 48         134 my $got = $args{got}->{name};
953 48         391 my @caller = caller(0);
954             $self->exception("Expected (@$expected), but got $got",
955             caller => \@caller,
956             expected => $expected,
957             got => $args{got},
958 48         284 );
959             }
960              
961             sub cb_tag {
962 2729     2729 0 4958 my ($self, $token) = @_;
963 2729         5503 my $stack = $self->event_stack;
964 2729 100 66     8578 if (! @$stack or $stack->[-1]->[0] ne 'properties') {
965 2229         5491 push @$stack, [ properties => {} ];
966             }
967 2729         4666 my $last = $stack->[-1]->[1];
968 2729         6004 my $tag = $self->_read_tag($token->{value}, $self->tagmap);
969 2727   100     12963 $last->{inline} ||= [];
970 2727         11109 push @{ $last->{inline} }, {
971             type => 'tag',
972             value => $tag,
973             offset => $token->{column},
974 2727         3953 };
975             }
976              
977             sub _read_tag {
978 2729     2729   5833 my ($self, $tag, $map) = @_;
979 2729 100       19185 if ($tag eq '!') {
    100          
    50          
980 75         194 return "!";
981             }
982             elsif ($tag =~ m/^!<(.*)>/) {
983 133         552 return $1;
984             }
985             elsif ($tag =~ m/^(![^!]*!|!)(.+)/) {
986 2521         6702 my $alias = $1;
987 2521         4617 my $name = $2;
988 2521         5630 $name =~ s/%([0-9a-fA-F]{2})/chr hex $1/eg;
  18         146  
989 2521 100       6361 if (exists $map->{ $alias }) {
990 2289         6561 $tag = $map->{ $alias }. $name;
991             }
992             else {
993 232 100 66     824 if ($alias ne '!' and $alias ne '!!') {
994 2         22 die "Found undefined tag handle '$alias'";
995             }
996 230         564 $tag = "!$name";
997             }
998             }
999             else {
1000 0         0 die "Invalid tag";
1001             }
1002 2519         5484 return $tag;
1003             }
1004              
1005             sub cb_anchor {
1006 2089     2089 0 4261 my ($self, $token) = @_;
1007 2089         3756 my $anchor = $token->{value};
1008 2089         6080 $anchor = substr($anchor, 1);
1009 2089         4252 my $stack = $self->event_stack;
1010 2089 100 66     6264 if (! @$stack or $stack->[-1]->[0] ne 'properties') {
1011 1840         4567 push @$stack, [ properties => {} ];
1012             }
1013 2089         3536 my $last = $stack->[-1]->[1];
1014 2089   100     9578 $last->{inline} ||= [];
1015 2089         9484 push @{ $last->{inline} }, {
1016             type => 'anchor',
1017             value => $anchor,
1018             offset => $token->{column},
1019 2089         2951 };
1020             }
1021              
1022             sub cb_property_eol {
1023 1191     1191 0 2479 my ($self, $res) = @_;
1024 1191         2236 my $stack = $self->event_stack;
1025 1191         2085 my $last = $stack->[-1]->[1];
1026 1191 50       3139 my $inline = delete $last->{inline} or return;
1027 1191   100     5583 my $newline = $last->{newline} ||= [];
1028 1191         3122 push @$newline, @$inline;
1029             }
1030              
1031             sub cb_mapkey {
1032 3892     3892 0 7346 my ($self, $token) = @_;
1033 3892         7427 my $stack = $self->event_stack;
1034             my $info = {
1035             style => YAML_PLAIN_SCALAR_STYLE,
1036             value => $token->{value},
1037             offset => $token->{column},
1038 3892         13612 };
1039 3892 100 66     10280 if (@$stack and $stack->[-1]->[0] eq 'properties') {
1040 72         208 $self->fetch_inline_properties($stack, $info);
1041             }
1042 3892         5439 push @{ $stack }, [ scalar => $info ];
  3892         9438  
1043             }
1044              
1045             sub cb_send_mapkey {
1046 4263     4263 0 7801 my ($self, $res) = @_;
1047 4263         5781 my $last = pop @{ $self->event_stack };
  4263         7449  
1048 4263         11777 $self->scalar_event($last->[1]);
1049 4263         7904 $self->set_new_node(1);
1050             }
1051              
1052             sub cb_send_scalar {
1053 17727     17727 0 31413 my ($self, $res) = @_;
1054 17727         23284 my $last = pop @{ $self->event_stack };
  17727         29523  
1055 17727 100       36118 return unless $last;
1056 17018         45018 $self->scalar_event($last->[1]);
1057 17008         29240 my $e = $self->events;
1058 17008 100       57301 if ($e->[-1] eq 'IMAP') {
1059 9         27 $self->end_flow_mapping;
1060             }
1061             }
1062              
1063             sub cb_empty_mapkey {
1064 113     113 0 249 my ($self, $token) = @_;
1065 113         257 my $stack = $self->event_stack;
1066             my $info = {
1067             style => YAML_PLAIN_SCALAR_STYLE,
1068             value => '',
1069             offset => $token->{column},
1070 113         441 };
1071 113 100 66     414 if (@$stack and $stack->[-1]->[0] eq 'properties') {
1072 9         28 $self->fetch_inline_properties($stack, $info);
1073             }
1074 113         327 $self->scalar_event($info);
1075 113         299 $self->set_new_node(1);
1076             }
1077              
1078             sub cb_send_flow_alias {
1079 17     17 0 43 my ($self, $token) = @_;
1080 17         50 my $alias = substr($token->{value}, 1);
1081 17         71 $self->alias_event({ value => $alias });
1082             }
1083              
1084             sub cb_send_alias {
1085 291     291 0 646 my ($self, $token) = @_;
1086 291         1916 my $alias = substr($token->{value}, 1);
1087 291         1088 $self->alias_event({ value => $alias });
1088             }
1089              
1090             sub cb_send_alias_key {
1091 62     62 0 166 my ($self, $token) = @_;
1092 62         188 my $alias = substr($token->{value}, 1);
1093 62         312 $self->alias_event({ value => $alias });
1094 61         403 $self->set_new_node(1);
1095             }
1096              
1097             sub cb_send_alias_from_stack {
1098 143     143 0 414 my ($self, $token) = @_;
1099 143         273 my $last = pop @{ $self->event_stack };
  143         274  
1100 143         401 $self->alias_event($last->[1]);
1101             }
1102              
1103             sub cb_alias {
1104 180     180 0 394 my ($self, $token) = @_;
1105 180         508 my $alias = substr($token->{value}, 1);
1106 180         390 push @{ $self->event_stack }, [ alias => {
1107             value => $alias,
1108             offset => $token->{column},
1109 180         307 }];
1110             }
1111              
1112             sub cb_question {
1113 173     173 0 514 my ($self, $res) = @_;
1114 173         448 $self->set_new_node(1);
1115             }
1116              
1117             sub cb_flow_question {
1118 93     93 0 202 my ($self, $res) = @_;
1119 93         217 $self->set_new_node(2);
1120             }
1121              
1122             sub cb_empty_complexvalue {
1123 54     54 0 158 my ($self, $res) = @_;
1124 54         264 $self->scalar_event({ style => YAML_PLAIN_SCALAR_STYLE, value => '' });
1125             }
1126              
1127             sub cb_questionstart {
1128 339     339 0 794 my ($self, $token) = @_;
1129 339         1006 $self->start_mapping($token->{column});
1130             }
1131              
1132             sub cb_complexcolon {
1133 405     405 0 866 my ($self, $res) = @_;
1134 405         962 $self->set_new_node(1);
1135             }
1136              
1137             sub cb_seqstart {
1138 3222     3222 0 5749 my ($self, $token) = @_;
1139 3222         5191 my $column = $token->{column};
1140 3222         7890 $self->start_sequence($column);
1141 3222         10984 $self->set_new_node(1);
1142             }
1143              
1144             sub cb_seqitem {
1145 4235     4235 0 7712 my ($self, $res) = @_;
1146 4235         8008 $self->set_new_node(1);
1147             }
1148              
1149             sub cb_take_quoted {
1150 3992     3992 0 7184 my ($self, $token) = @_;
1151 3992         6161 my $subtokens = $token->{subtokens};
1152 3992         7909 my $stack = $self->event_stack;
1153             my $info = {
1154             style => $subtokens->[0]->{value} eq '"'
1155             ? YAML_DOUBLE_QUOTED_SCALAR_STYLE
1156             : YAML_SINGLE_QUOTED_SCALAR_STYLE,
1157             value => $token->{value},
1158             offset => $token->{column},
1159 3992 100       17382 };
1160 3992 100 66     10596 if (@$stack and $stack->[-1]->[0] eq 'properties') {
1161 236         612 $self->fetch_inline_properties($stack, $info);
1162             }
1163 3992         5502 push @{ $stack }, [ scalar => $info ];
  3992         9963  
1164             }
1165              
1166             sub cb_quoted_multiline {
1167 487     487 0 1165 my ($self, $token) = @_;
1168 487         896 my $subtokens = $token->{subtokens};
1169 487         1068 my $stack = $self->event_stack;
1170             my $info = {
1171             style => $subtokens->[0]->{value} eq '"'
1172             ? YAML_DOUBLE_QUOTED_SCALAR_STYLE
1173             : YAML_SINGLE_QUOTED_SCALAR_STYLE,
1174             value => $token->{value},
1175             offset => $token->{column},
1176 487 100       2503 };
1177 487 100 66     1537 if (@$stack and $stack->[-1]->[0] eq 'properties') {
1178 16         56 $self->fetch_inline_properties($stack, $info);
1179             }
1180 487         719 push @{ $stack }, [ scalar => $info ];
  487         1299  
1181 487         1158 $self->cb_send_scalar;
1182             }
1183              
1184             sub cb_take_quoted_key {
1185 375     375 0 779 my ($self, $token) = @_;
1186 375         1012 $self->cb_take_quoted($token);
1187 375         1002 $self->cb_send_mapkey;
1188             }
1189              
1190             sub cb_send_plain_multi {
1191 238     238 0 643 my ($self, $token) = @_;
1192 238         525 my $stack = $self->event_stack;
1193             my $info = {
1194             style => YAML_PLAIN_SCALAR_STYLE,
1195             value => $token->{value},
1196             offset => $token->{column},
1197 238         1046 };
1198 238 100 66     886 if (@$stack and $stack->[-1]->[0] eq 'properties') {
1199 9         36 $self->fetch_inline_properties($stack, $info);
1200             }
1201 238         429 push @{ $stack }, [ scalar => $info ];
  238         639  
1202 238         656 $self->cb_send_scalar;
1203             }
1204              
1205             sub cb_start_plain {
1206 15525     15525 0 27271 my ($self, $token) = @_;
1207 15525         28104 my $stack = $self->event_stack;
1208             my $info = {
1209             style => YAML_PLAIN_SCALAR_STYLE,
1210             value => $token->{value},
1211             offset => $token->{column},
1212 15525         53233 };
1213 15525 100 66     43709 if (@$stack and $stack->[-1]->[0] eq 'properties') {
1214 2212         5670 $self->fetch_inline_properties($stack, $info);
1215             }
1216 15525         21637 push @{ $stack }, [ scalar => $info ];
  15525         36999  
1217             }
1218              
1219             sub cb_start_flowseq {
1220 1361     1361 0 2701 my ($self, $token) = @_;
1221 1361         3384 $self->start_flow_sequence($token->{column});
1222             }
1223              
1224             sub cb_start_flowmap {
1225 1109     1109 0 2431 my ($self, $token) = @_;
1226 1109         2948 $self->start_flow_mapping($token->{column});
1227             }
1228              
1229             sub cb_end_flowseq {
1230 1349     1349 0 2614 my ($self, $res) = @_;
1231 1349         3422 $self->cb_send_scalar;
1232 1349         4019 $self->end_flow_sequence;
1233 1349         2778 $self->set_new_node(0);
1234             }
1235              
1236             sub cb_flow_comma {
1237 2340     2340 0 4442 my ($self) = @_;
1238 2340         4486 my $event_types = $self->events;
1239 2340         5475 $self->set_new_node(0);
1240 2340 100       9205 if ($event_types->[-1] =~ m/^FLOWSEQ/) {
1241 1682         4359 $self->cb_send_scalar;
1242 1682         3772 $event_types->[-1] = $next_event{ $event_types->[-1] };
1243             }
1244             }
1245              
1246             sub cb_flow_colon {
1247 1101     1101 0 2553 my ($self) = @_;
1248 1101         2080 $self->set_new_node(1);
1249             }
1250              
1251             sub cb_empty_flow_mapkey {
1252 402     402 0 929 my ($self, $token) = @_;
1253 402         756 my $stack = $self->event_stack;
1254             my $info = {
1255             style => YAML_PLAIN_SCALAR_STYLE,
1256             value => '',
1257             offset => $token->{column},
1258 402         1420 };
1259 402 100 66     3000 if (@$stack and $stack->[-1]->[0] eq 'properties') {
1260 243         572 $self->fetch_inline_properties($stack, $info);
1261             }
1262 402         1066 $self->scalar_event($info);
1263             }
1264              
1265             sub cb_end_flowmap {
1266 1001     1001 0 1981 my ($self, $res) = @_;
1267 1001         2744 $self->end_flow_mapping;
1268 993         1976 $self->set_new_node(0);
1269             }
1270              
1271             sub cb_end_flowmap_empty {
1272 106     106 0 251 my ($self, $res) = @_;
1273 106         315 $self->cb_empty_flowmap_value;
1274 106         339 $self->end_flow_mapping;
1275 106         251 $self->set_new_node(0);
1276             }
1277              
1278             sub cb_flowkey_plain {
1279 938     938 0 2056 my ($self, $token) = @_;
1280 938         1905 my $stack = $self->event_stack;
1281             my $info = {
1282             style => YAML_PLAIN_SCALAR_STYLE,
1283             value => $token->{value},
1284             offset => $token->{column},
1285 938         3573 };
1286 938 100 66     2808 if (@$stack and $stack->[-1]->[0] eq 'properties') {
1287 21         71 $self->fetch_inline_properties($stack, $info);
1288             }
1289 938         2317 $self->scalar_event($info);
1290             }
1291              
1292             sub cb_flowkey_quoted {
1293 139     139 0 349 my ($self, $token) = @_;
1294 139         321 my $stack = $self->event_stack;
1295 139         284 my $subtokens = $token->{subtokens};
1296             my $info = {
1297             style => $subtokens->[0]->{value} eq '"'
1298             ? YAML_DOUBLE_QUOTED_SCALAR_STYLE
1299             : YAML_SINGLE_QUOTED_SCALAR_STYLE,
1300             value => $token->{value},
1301             offset => $token->{column},
1302 139 100       768 };
1303 139 100 66     513 if (@$stack and $stack->[-1]->[0] eq 'properties') {
1304 2         6 $self->fetch_inline_properties($stack, $info);
1305             }
1306 139         400 $self->scalar_event($info);
1307             }
1308              
1309             sub cb_empty_flowmap_key_value {
1310 136     136 0 263 my ($self, $token) = @_;
1311 136         363 $self->cb_empty_flow_mapkey($token);
1312 136         388 $self->cb_empty_flowmap_value;
1313 136         297 $self->cb_flow_comma;
1314             }
1315              
1316             sub cb_end_empty_flowmap_key_value {
1317 124     124 0 284 my ($self, $token) = @_;
1318 124         350 $self->cb_empty_flow_mapkey($token);
1319 124         431 $self->cb_empty_flowmap_value;
1320 124         373 $self->cb_flow_comma;
1321 124         358 $self->cb_end_flowmap;
1322             }
1323              
1324             sub cb_empty_flowmap_value {
1325 569     569 0 1069 my ($self, $token) = @_;
1326 569         1038 my $stack = $self->event_stack;
1327             my $info = {
1328             style => YAML_PLAIN_SCALAR_STYLE,
1329             value => '',
1330             offset => $token->{column},
1331 569         1958 };
1332 569 100 66     1884 if (@$stack and $stack->[-1]->[0] eq 'properties') {
1333 167         495 $self->fetch_inline_properties($stack, $info);
1334             }
1335 569         1223 $self->scalar_event($info);
1336             }
1337              
1338             sub cb_empty_flowseq_comma {
1339 90     90 0 169 my ($self, $token) = @_;
1340 90         249 $self->cb_empty_flowmap_value($token);
1341 90         216 $self->cb_flow_comma;
1342             }
1343              
1344             sub cb_empty_flowseq_end {
1345 72     72 0 141 my ($self, $token) = @_;
1346 72         211 $self->cb_empty_flowmap_value($token);
1347 72         163 $self->cb_end_flowseq;
1348             }
1349              
1350             sub cb_insert_map_alias {
1351 37     37 0 83 my ($self, $res) = @_;
1352 37         83 my $stack = $self->event_stack;
1353 37         83 my $scalar = pop @$stack;
1354 37         66 my $info = $scalar->[1];
1355 37         118 $self->start_mapping($info->{offset});
1356 37         199 $self->alias_event($info);
1357 37         77 $self->set_new_node(1);
1358             }
1359              
1360             sub cb_insert_map {
1361 4547     4547 0 8320 my ($self, $res) = @_;
1362 4547         7727 my $stack = $self->event_stack;
1363 4547         7601 my $scalar = pop @$stack;
1364 4547         7108 my $info = $scalar->[1];
1365 4547         11981 $self->start_mapping($info->{offset});
1366 4547         18132 $self->scalar_event($info);
1367 4547         7870 $self->set_new_node(1);
1368             }
1369              
1370             sub cb_insert_implicit_flowseq_map {
1371 7     7 0 23 my ($self, $res) = @_;
1372 7         18 my $stack = $self->event_stack;
1373 7         23 my $scalar = pop @$stack;
1374 7         14 my $info = $scalar->[1];
1375 7         34 $self->start_flow_mapping($info->{offset}, 1);
1376 7         28 $self->scalar_event($info);
1377 7         22 $self->set_new_node(1);
1378             }
1379              
1380             sub cb_insert_empty_implicit_flowseq_map {
1381 2     2 0 6 my ($self, $res) = @_;
1382 2         6 my $stack = $self->event_stack;
1383 2         4 my $scalar = pop @$stack;
1384 2         5 my $info = $scalar->[1];
1385 2         8 $self->start_flow_mapping($info->{offset}, 1);
1386 2         17 $self->cb_empty_flowmap_value;
1387 2         5 $self->set_new_node(2);
1388             }
1389              
1390             sub cb_insert_empty_map {
1391 430     430 0 840 my ($self, $token) = @_;
1392 430         864 my $stack = $self->event_stack;
1393             my $info = {
1394             style => YAML_PLAIN_SCALAR_STYLE,
1395             value => '',
1396             offset => $token->{column},
1397 430         1545 };
1398 430 100 66     1700 if (@$stack and $stack->[-1]->[0] eq 'properties') {
1399 248         591 $self->fetch_inline_properties($stack, $info);
1400             }
1401 430         1399 $self->start_mapping($info->{offset});
1402 430         1704 $self->scalar_event($info);
1403 430         861 $self->set_new_node(1);
1404             }
1405              
1406             sub cb_send_block_scalar {
1407 1710     1710 0 3264 my ($self, $token) = @_;
1408 1710         3914 my $type = $token->{subtokens}->[0]->{value};
1409 1710         3390 my $stack = $self->event_stack;
1410             my $info = {
1411             style => $type eq '|'
1412             ? YAML_LITERAL_SCALAR_STYLE
1413             : YAML_FOLDED_SCALAR_STYLE,
1414             value => $token->{value},
1415             offset => $token->{column},
1416 1710 100       7410 };
1417 1710 100 66     5140 if (@$stack and $stack->[-1]->[0] eq 'properties') {
1418 82         237 $self->fetch_inline_properties($stack, $info);
1419             }
1420 1710         2545 push @{ $self->event_stack }, [ scalar => $info ];
  1710         3076  
1421 1710         3957 $self->cb_send_scalar;
1422             }
1423              
1424             sub cb_end_document {
1425 578     578 0 1268 my ($self, $token) = @_;
1426 578         1379 $self->end_document(0);
1427             }
1428              
1429             sub cb_end_document_empty {
1430 30     30 0 107 my ($self, $token) = @_;
1431 30         104 $self->end_document(0);
1432             }
1433              
1434             sub cb_doc_start_implicit {
1435 3910     3910 0 8001 my ($self, $token) = @_;
1436 3910         8566 $self->start_document(1);
1437             }
1438              
1439             sub cb_doc_start_explicit {
1440 3760     3760 0 7213 my ($self, $token) = @_;
1441 3760         8491 $self->start_document(0);
1442             }
1443              
1444             sub cb_end_doc_start_document {
1445 524     524 0 1167 my ($self, $token) = @_;
1446 524         1417 $self->end_document(1);
1447 524         1259 $self->start_document(0);
1448             }
1449              
1450             sub cb_tag_directive {
1451 117     117 0 383 my ($self, $token) = @_;
1452 117         647 my ($name, $tag_alias, $tag_url) = split ' ', $token->{value};
1453 117         387 $self->tagmap->{ $tag_alias } = $tag_url;
1454             }
1455              
1456       45 0   sub cb_reserved_directive {
1457             }
1458              
1459             sub cb_set_yaml_version_directive {
1460 159     159 0 466 my ($self, $token) = @_;
1461 159 100       372 if ($self->yaml_version_directive) {
1462 1         94 croak "Found duplicate YAML directive";
1463             }
1464 158         1004 my ($version) = $token->{value} =~ m/^%YAML[ \t]+(1\.[12])/;
1465 158   100     727 $self->set_yaml_version($version || '1.2');
1466 158         409 $self->set_yaml_version_directive(1);
1467             }
1468              
1469             1;