File Coverage

blib/lib/YAML/Perl/Parser.pm
Criterion Covered Total %
statement 337 405 83.2
branch 96 138 69.5
condition 12 17 70.5
subroutine 37 39 94.8
pod 0 30 0.0
total 482 629 76.6


line stmt bran cond sub pod time code
1             # pyyaml/lib/yaml/parser.py
2              
3             # The following YAML grammar is LL(1) and is parsed by a recursive descent
4             # parser.
5             #
6             # stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
7             # implicit_document ::= block_node DOCUMENT-END*
8             # explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
9             # block_node_or_indentless_sequence ::=
10             # ALIAS
11             # | properties (block_content | indentless_block_sequence)?
12             # | block_content
13             # | indentless_block_sequence
14             # block_node ::= ALIAS
15             # | properties block_content?
16             # | block_content
17             # flow_node ::= ALIAS
18             # | properties flow_content?
19             # | flow_content
20             # properties ::= TAG ANCHOR? | ANCHOR TAG?
21             # block_content ::= block_collection | flow_collection | SCALAR
22             # flow_content ::= flow_collection | SCALAR
23             # block_collection ::= block_sequence | block_mapping
24             # flow_collection ::= flow_sequence | flow_mapping
25             # block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
26             # indentless_sequence ::= (BLOCK-ENTRY block_node?)+
27             # block_mapping ::= BLOCK-MAPPING_START
28             # ((KEY block_node_or_indentless_sequence?)?
29             # (VALUE block_node_or_indentless_sequence?)?)*
30             # BLOCK-END
31             # flow_sequence ::= FLOW-SEQUENCE-START
32             # (flow_sequence_entry FLOW-ENTRY)*
33             # flow_sequence_entry?
34             # FLOW-SEQUENCE-END
35             # flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
36             # flow_mapping ::= FLOW-MAPPING-START
37             # (flow_mapping_entry FLOW-ENTRY)*
38             # flow_mapping_entry?
39             # FLOW-MAPPING-END
40             # flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
41             #
42             # FIRST sets:
43             #
44             # stream: { STREAM-START }
45             # explicit_document: { DIRECTIVE DOCUMENT-START }
46             # implicit_document: FIRST(block_node)
47             # block_node: { ALIAS TAG ANCHOR SCALAR BLOCK-SEQUENCE-START BLOCK-MAPPING-START FLOW-SEQUENCE-START FLOW-MAPPING-START }
48             # flow_node: { ALIAS ANCHOR TAG SCALAR FLOW-SEQUENCE-START FLOW-MAPPING-START }
49             # block_content: { BLOCK-SEQUENCE-START BLOCK-MAPPING-START FLOW-SEQUENCE-START FLOW-MAPPING-START SCALAR }
50             # flow_content: { FLOW-SEQUENCE-START FLOW-MAPPING-START SCALAR }
51             # block_collection: { BLOCK-SEQUENCE-START BLOCK-MAPPING-START }
52             # flow_collection: { FLOW-SEQUENCE-START FLOW-MAPPING-START }
53             # block_sequence: { BLOCK-SEQUENCE-START }
54             # block_mapping: { BLOCK-MAPPING-START }
55             # block_node_or_indentless_sequence: { ALIAS ANCHOR TAG SCALAR BLOCK-SEQUENCE-START BLOCK-MAPPING-START FLOW-SEQUENCE-START FLOW-MAPPING-START BLOCK-ENTRY }
56             # indentless_sequence: { ENTRY }
57             # flow_collection: { FLOW-SEQUENCE-START FLOW-MAPPING-START }
58             # flow_sequence: { FLOW-SEQUENCE-START }
59             # flow_mapping: { FLOW-MAPPING-START }
60             # flow_sequence_entry: { ALIAS ANCHOR TAG SCALAR FLOW-SEQUENCE-START FLOW-MAPPING-START KEY }
61             # flow_mapping_entry: { ALIAS ANCHOR TAG SCALAR FLOW-SEQUENCE-START FLOW-MAPPING-START KEY }
62              
63             package YAML::Perl::Parser;
64 8     8   3523 use strict;
  8         16  
  8         448  
65 8     8   46 use warnings;
  8         18  
  8         260  
66              
67 8     8   1892 use YAML::Perl::Error;
  8         19  
  8         69  
68 8     8   4008 use YAML::Perl::Tokens;
  8         28  
  8         112  
69 8     8   1455 use YAML::Perl::Events;
  8         19  
  8         219  
70 8     8   7014 use YAML::Perl::Scanner;
  8         36  
  8         133  
71              
72             package YAML::Perl::Error::Parser;
73 8     8   57 use YAML::Perl::Error::Marked -base;
  8         16  
  8         62  
74              
75             package YAML::Perl::Parser;
76 8     8   49 use YAML::Perl::Processor -base;
  8         15  
  8         49  
77              
78 8         48400 use constant DEFAULT_TAGS => {
79             '!' => '!',
80             '!!' => 'tag:yaml.org,2002:',
81 8     8   50 };
  8         18  
82              
83             field 'next_layer' => 'scanner';
84              
85             field 'scanner_class', -init => '"YAML::Perl::Scanner"';
86             field 'scanner', -init => '$self->create("scanner")';
87              
88             field 'current_event';
89             field 'yaml_version';
90             field 'tag_handles' => {};
91             field 'states' => [];
92             field 'marks' => [];
93             field 'state' => 'parse_stream_start';
94              
95             sub parse {
96 11     11 0 72 my $self = shift;
97 11 50       27 if (wantarray) {
98 11         449 my @events = ();
99 11         35 while ($self->check_event()) {
100 87         246 push @events, $self->get_event();
101             }
102 10         291 return @events;
103             }
104             else {
105 0 0       0 return $self->check_event() ? $self->get_event() : ();
106             }
107             }
108              
109             sub check_event {
110 484     484 0 660 my $self = shift;
111 484         898 my @choices = @_;
112 484 100       15234 if (not defined $self->current_event) {
113 256 100       6606 if ($self->state) {
114 246         7997 my $state = $self->state;
115 246         1130 $self->current_event($self->$state());
116             }
117             }
118 483 100       12828 if (defined $self->current_event) {
119 473 100       1048 if (not @choices) {
120 87         280 return True;
121             }
122 386         631 for my $choice (@choices) {
123 386 100       11033 if ($self->current_event->isa($choice)) {
124 139         1282 return True;
125             }
126             }
127             }
128 257         2538 return False;
129             }
130              
131             sub peek_event {
132 74     74 0 137 my $self = shift;
133 74 50       1974 if (not defined $self->current_event) {
134 0 0       0 if (my $state = $self->state) {
135 0         0 $self->current_event($self->$state());
136             }
137             }
138 74         1856 return $self->current_event;
139             }
140              
141             sub get_event {
142 245     245 0 519 my $self = shift;
143 245 100       10620 if (not defined $self->current_event) {
144 19 50       557 if (my $state = $self->state) {
145 19         99 $self->current_event($self->$state());
146             }
147             }
148 245         6816 my $value = $self->current_event;
149 245         6070 $self->current_event(undef);
150 245         833 return $value;
151             }
152              
153             # stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
154             # implicit_document ::= block_node DOCUMENT-END*
155             # explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
156              
157             sub parse_stream_start {
158 30     30 0 63 my $self = shift;
159 30         1189 my $token = $self->scanner->get_token();
160 30         832 my $event = YAML::Perl::Event::StreamStart->new(
161             start_mark => $token->start_mark,
162             end_mark => $token->end_mark,
163             encoding => $token->encoding,
164             );
165 30         833 $self->state('parse_implicit_document_start');
166 30         831 return $event;
167             }
168              
169             sub parse_implicit_document_start {
170 30     30 0 61 my $self = shift;
171 30 100       823 if (not $self->scanner->check_token(qw(
172             YAML::Perl::Token::Directive
173             YAML::Perl::Token::DocumentStart
174             YAML::Perl::Token::StreamEnd
175             ))) {
176 2         56 $self->tag_handles(DEFAULT_TAGS);
177 2         46 my $token = $self->scanner->peek_token();
178 2         46 my $start_mark = $token->start_mark;
179 2         6 my $end_mark = $start_mark;
180 2         21 my $event = YAML::Perl::Event::DocumentStart->new(
181             start_mark => $start_mark,
182             end_mark => $end_mark,
183             explicit => False,
184             );
185              
186 2         5 push @{$self->states}, 'parse_document_end';
  2         50  
187 2         47 $self->state('parse_block_node');
188 2         44 return $event;
189             }
190 28         116 return $self->parse_document_start();
191             }
192              
193             sub parse_document_start {
194 57     57 0 111 my $self = shift;
195 57         83 my $event;
196 57         1447 while ($self->scanner->check_token('YAML::Perl::Token::DocumentEnd')) {
197 0         0 $self->scanner->get_token();
198             }
199              
200 57 100       1379 if (not $self->scanner->check_token('YAML::Perl::Token::StreamEnd')) {
201 28         700 my $token = $self->scanner->peek_token();
202 28         801 my $start_mark = $token->start_mark;
203 28         119 my ($version, $tags) = $self->process_directives();
204 28 50       830 if (not $self->scanner->check_token('YAML::Perl::Token::DocumentStart')) {
205 0         0 throw YAML::Perl::Error::Parser(
206             "expected '', but found " .
207             $self->scanner->peek_token->id,
208             );
209             }
210 28         691 $token = $self->scanner->get_token();
211 28         735 my $end_mark = $token->end_mark;
212 28         314 $event = YAML::Perl::Event::DocumentStart->new(
213             start_mark => $start_mark,
214             end_mark => $end_mark,
215             explicit => 1,
216             version => $version,
217             tags => $tags,
218             );
219 28         40 push @{$self->states}, 'parse_document_end';
  28         708  
220 28         835 $self->state('parse_document_content');
221             }
222             else {
223 29         913 my $token = $self->scanner->get_token();
224 29         995 $event = YAML::Perl::Event::StreamEnd->new(
225             start_mark => $token->start_mark,
226             end_mark => $token->end_mark,
227             );
228 29         61 assert not scalar @{$self->states};
  29         840  
229 29         60 assert not scalar @{$self->marks};
  29         905  
230 29         800 $self->state(undef);
231             }
232 57         1602 return $event;
233             }
234              
235             sub parse_document_end {
236 29     29 0 74 my $self = shift;
237 29         924 my $token = $self->scanner->peek_token();
238 29         723 my $start_mark = $token->start_mark;
239 29         52 my $end_mark = $start_mark;
240 29         49 my $explicit = 0;
241 29         719 while ($self->scanner->check_token('YAML::Perl::Token::DocumentEnd')) {
242 1         23 $token = $self->scanner->get_token();
243 1         24 $end_mark = $token->end_mark;
244 1         24 $explicit = 1;
245             }
246 29         214 my $event = YAML::Perl::Event::DocumentEnd->new(
247             start_mark => $start_mark,
248             end_mark => $end_mark,
249             explicit => $explicit,
250             );
251 29         801 $self->state('parse_document_start');
252 29         731 return $event;
253             }
254              
255             sub parse_document_content {
256 28     28 0 62 my $self = shift;
257 28 50       717 if ( $self->scanner->check_token(
258             'YAML::Perl::Token::Directive',
259             'YAML::Perl::Token::DocumentStart',
260             'YAML::Perl::Token::DocumentEnd',
261             'YAML::Perl::Token::StreamEnd',
262             ) ) {
263 0         0 my $event = $self->process_empty_scalar( $self->scanner->peek_token()->start_mark() );
264 0         0 $self->state( pop @{ $self->states() } );
  0         0  
265 0         0 return $event;
266             }
267             else {
268 28         134 return $self->parse_block_node();
269             }
270             }
271              
272             sub process_directives {
273 28     28 0 60 my $self = shift;
274 28         750 $self->yaml_version(undef);
275 28         753 $self->tag_handles({});
276 28         1154 while ($self->scanner->check_token('YAML::Perl::Token::Directive')) {
277 2         51 my $token = $self->scanner->get_token();
278 2 100       50 if ($token->name eq 'YAML') {
    50          
279 1 50       22 if (defined($self->yaml_version)) {
280 0         0 throw YAML::Perl::Error::Parser(
281             "found duplicate YAML directive", $token->start_mark);
282             }
283 1         23 my ($major, $minor) = split('\.', $token->value);
284 1 50       5 if ($major != 1) {
285 0         0 throw YAML::Perl::Error::Parser(
286             "found incompatible YAML document (version 1.* is required)",
287             $token->start_mark);
288             }
289 1         23 $self->yaml_version($token->value);
290             }
291             elsif ($token->name eq 'TAG') {
292 1         2 my ($handle, $prefix) = @{$token->value};
  1         30  
293 1 50       29 if (defined $self->tag_handles->{$handle}) {
294 0         0 throw YAML::Perl::Error::Parser(
295             undef,
296             undef,
297             "duplicate tag handle %r",
298             $handle->encode('utf-8'),
299             $token->start_mark,
300             );
301             }
302 1         29 $self->tag_handles->{$handle} = $prefix;
303             }
304             }
305 28         59 my @value;
306 28 100       38 if (keys(%{$self->tag_handles})) {
  28         700  
307 1         26 @value = ($self->yaml_version, {%{$self->tag_handles}});
  1         26  
308             }
309             else {
310 27         798 @value = ($self->yaml_version, undef);
311             }
312 28         56 for my $key (keys %{$self->DEFAULT_TAGS}) {
  28         202  
313 56 100       2139 if (not exists $self->tag_handles->{$key}) {
314 55         1416 $self->tag_handles->{$key} = $self->DEFAULT_TAGS->{$key};
315             }
316             }
317 28         105 return @value;
318             }
319              
320             sub parse_block_node {
321 50     50 0 110 my $self = shift;
322 50         221 return $self->parse_node(block => True);
323             }
324              
325             sub parse_flow_node {
326 18     18 0 43 my $self = shift;
327 18         58 return $self->parse_node();
328             }
329              
330             sub parse_block_node_or_indentless_sequence {
331 40     40 0 76 my $self = shift;
332 40         145 return $self->parse_node(block => True, indentless_sequence => True);
333             }
334              
335             sub parse_node {
336 108     108 0 292 my $self = shift;
337 108         280 my ($block, $indentless_sequence) = @{{@_}}{qw(block indentless_sequence)};
  108         478  
338            
339 108         240 my $event;
340 108 100       3812 if ($self->scanner->check_token('YAML::Perl::Token::Alias')) {
341 3         89 my $token = $self->scanner->get_token();
342 3         91 $event = YAML::Perl::Event::Alias->new(
343             anchor => $token->value,
344             start_mark => $token->start_mark,
345             end_mark => $token->end_mark,
346             );
347 3         12 $self->state(pop @{$self->states});
  3         87  
348             }
349             else {
350 105         172 my $anchor = undef;
351 105         162 my $tag = undef;
352 105         164 my $implicit = undef;
353 105         212 my ($start_mark, $end_mark, $tag_mark) = (undef, undef, undef);
354 105 100       2668 if ($self->scanner->check_token('YAML::Perl::Token::Anchor')) {
    100          
355 3         79 my $token = $self->scanner->get_token();
356 3         86 $start_mark = $token->start_mark;
357 3         105 $end_mark = $token->end_mark;
358 3         77 $anchor = $token->value;
359              
360 3 50       78 if ($self->scanner->check_token('YAML::Perl::Token::Tag')) {
361 0         0 my $token = $self->scanner->get_token();
362 0         0 $tag_mark = $token->start_mark;
363 0         0 $end_mark = $token->end_mark;
364 0         0 $tag = $token->value;
365             }
366             }
367             elsif ($self->scanner->check_token('YAML::Perl::Token::Tag')) {
368 8         224 my $token = $self->scanner->get_token();
369 8         217 $start_mark = $token->start_mark;
370 8         21 $tag_mark = $start_mark;
371 8         226 $end_mark = $token->end_mark;
372 8         210 $tag = $token->value;
373 8 50       194 if ($self->scanner->check_token('YAML::Perl::Token::Anchor')) {
374 0         0 my $token = $self->scanner->get_token();
375 0         0 $end_mark = $token->end_mark;
376 0         0 $anchor = $token->value;
377             }
378             }
379 105 100       316 if (defined $tag) {
380 8         30 my ($handle, $suffix) = @$tag;
381 8 50       33 if (defined $handle) {
382 8 50       233 if (not exists $self->tag_handles->{$handle}) {
383 0         0 throw "while parsing a node... XXX finish this error msg";
384             }
385 8         207 $tag = $self->tag_handles->{$handle} . $suffix;
386             }
387             else {
388 0         0 $tag = $suffix;
389             }
390             }
391 105 100       286 if (not defined $start_mark) {
392 94         6634 $start_mark = $self->scanner->peek_token()->start_mark;
393 94         210 $end_mark = $start_mark;
394             }
395 105         1322 $event = undef;
396 105   66     361 $implicit = (not defined $tag) || ($tag eq '!');
397 105 100 100     1215 if ($indentless_sequence and
398             $self->scanner->check_token('YAML::Perl::Token::BlockEntry')
399             ) {
400 1         24 $end_mark = $self->scanner->peek_token()->end_mark;
401 1         7 $event = YAML::Perl::Event::SequenceStart->new(
402             anchor => $anchor,
403             tag => $tag,
404             implicit => $implicit,
405             start_mark => $start_mark,
406             end_mark => $end_mark,
407             );
408 1         26 $self->state('parse_indentless_sequence_entry');
409             }
410             else {
411 104 100 0     2505 if ($self->scanner->check_token('YAML::Perl::Token::Scalar')) {
    100          
    100          
    100          
    50          
    0          
412 74         9776 my $token = $self->scanner->get_token();
413 74         1906 $end_mark = $token->end_mark;
414 74 100 100     2259 if (($token->plain and not defined $tag) or ($tag || '') eq '!') {
    100 100        
      66        
415 59         184 $implicit = [True, False];
416             }
417             elsif (not defined $tag) {
418 11         37 $implicit = [False, True];
419             }
420             else {
421 4         14 $implicit = [False, False];
422             }
423 74         2324 $event = YAML::Perl::Event::Scalar->new(
424             anchor => $anchor,
425             tag => $tag,
426             implicit => $implicit,
427             value => $token->value,
428             start_mark => $start_mark,
429             end_mark => $end_mark,
430             style => $token->style,
431             );
432 74         141 $self->state(pop @{$self->states});
  74         2090  
433             }
434             elsif ($self->scanner->check_token('YAML::Perl::Token::FlowSequenceStart')) {
435 6         156 $end_mark = $self->scanner->peek_token()->end_mark;
436 6         69 $event = YAML::Perl::Event::SequenceStart->new(
437             anchor => $anchor,
438             tag => $tag,
439             implicit => $implicit,
440             start_mark => $start_mark,
441             end_mark => $end_mark,
442             flow_style => True,
443             );
444 6         147 $self->state('parse_flow_sequence_first_entry');
445             }
446             elsif ($self->scanner->check_token('YAML::Perl::Token::FlowMappingStart')) {
447 4         105 $end_mark = $self->scanner->peek_token()->end_mark;
448 4         38 $event = YAML::Perl::Event::MappingStart->new(
449             anchor => $anchor,
450             tag => $tag,
451             implicit => $implicit,
452             start_mark => $start_mark,
453             end_mark => $end_mark,
454             flow_style => True,
455             );
456 4         178 $self->state('parse_flow_mapping_first_key');
457             }
458             elsif ($self->scanner->check_token('YAML::Perl::Token::BlockSequenceStart')) {
459 6         159 $end_mark = $self->scanner->peek_token()->end_mark;
460 6         127 $event = YAML::Perl::Event::SequenceStart->new(
461             anchor => $anchor,
462             tag => $tag,
463             implicit => $implicit,
464             start_mark => $start_mark,
465             end_mark => $end_mark,
466             flow_style => False,
467             );
468 6         154 $self->state('parse_block_sequence_first_entry');
469             }
470             elsif ($self->scanner->check_token('YAML::Perl::Token::BlockMappingStart')) {
471 14         370 $end_mark = $self->scanner->peek_token()->end_mark;
472 14         178 $event = YAML::Perl::Event::MappingStart->new(
473             anchor => $anchor,
474             tag => $tag,
475             implicit => $implicit,
476             start_mark => $start_mark,
477             end_mark => $end_mark,
478             flow_style => False,
479             );
480 14         388 $self->state('parse_block_mapping_first_key');
481             }
482             elsif (defined $anchor or defined $tag) {
483 0         0 $event = YAML::Perl::Event::Scalar->new(
484             anchor => $anchor,
485             tag => $tag,
486             implicit => [$implicit, False],
487             value => '',
488             start_mark => $start_mark,
489             end_mark => $end_mark,
490             );
491 0         0 $self->state(pop @{$self->states});
  0         0  
492             }
493             else {
494 0 0       0 my $node = $block ? 'block' : 'flow';
495 0         0 my $token = $self->scanner->peek_token();
496 0         0 throw YAML::Perl::Error::Parser(
497             "while parsing a $node node, XXX - finish error msg"
498             );
499             }
500             }
501             }
502 108         4154 return $event;
503             }
504              
505             sub parse_block_sequence_first_entry {
506 6     6 0 49 my $self = shift;
507 6         166 my $token = $self->scanner->get_token();
508 6         16 push @{$self->marks}, $token->start_mark;
  6         166  
509 6         32 return $self->parse_block_sequence_entry();
510             }
511              
512             sub parse_block_sequence_entry {
513 24     24 0 44 my $self = shift;
514 24 100       604 if ($self->scanner->check_token('YAML::Perl::Token::BlockEntry')) {
515 18         453 my $token = $self->scanner->get_token();
516 18 50       469 if (not $self->scanner->check_token(qw(
517             YAML::Perl::Token::BlockEntry
518             YAML::Perl::Token::BlockEnd
519             ))) {
520 18         34 push @{$self->states}, 'parse_block_sequence_entry';
  18         516  
521 18         75 return $self->parse_block_node();
522             }
523             else {
524 0         0 $self->state('parse_block_sequence_entry');
525 0         0 return $self->process_empty_scalar($token->end_mark);
526             }
527             }
528 6 50       163 if (not $self->scanner->check_token('YAML::Perl::Token::BlockEnd')) {
529 0         0 my $token = $self->scanner->peek_token();
530 0         0 throw YAML::Perl::Error::Parser(
531             "while parsing a block collection", $self->marks->[-1],
532             "expected , but found ", $token->id, $token->start_mark
533             );
534             }
535 6         196 my $token = $self->scanner->get_token();
536 6         226 my $event = YAML::Perl::Event::SequenceEnd->new(
537             start_mark => $token->start_mark,
538             end_mark => $token->end_mark,
539             );
540 6         12 $self->state(pop @{$self->states});
  6         229  
541 6         10 pop @{$self->marks};
  6         169  
542 6         168 return $event;
543             }
544              
545             sub parse_indentless_sequence_entry {
546 3     3 0 6 my $self = shift;
547 3         5 my $token;
548 3 100       102 if ($self->scanner->check_token('YAML::Perl::Token::BlockEntry')) {
549 2         46 $token = $self->scanner->get_token();
550 2 50       1085 if (not $self->scanner->check_token(
551             'YAML::Perl::Token::BlockEntry',
552             'YAML::Perl::Token::Key',
553             'YAML::Perl::Token::Value',
554             'YAML::Perl::Token::BlockEnd',
555             )) {
556 2         3 push @{$self->states}, 'parse_indentless_sequence_entry';
  2         53  
557 2         8 return $self->parse_block_node();
558             }
559             else {
560 0         0 $self->state('parse_indentless_sequence_entry');
561 0         0 return $self->process_empty_scalar($token->end_mark);
562             }
563             }
564 1         26 $token = $self->scanner->peek_token();
565 1         25 my $event = YAML::Perl::Event::SequenceEnd->new(
566             start_mark => $token->start_mark,
567             end_mark => $token->end_mark,
568             );
569 1         2 $self->state(pop @{$self->states});
  1         24  
570 1         23 return $event;
571             }
572              
573             sub parse_block_mapping_first_key {
574 14     14 0 29 my $self = shift;
575 14         347 my $token = $self->scanner->get_token();
576 14         29 push @{$self->marks}, $token->start_mark;
  14         424  
577 14         66 return $self->parse_block_mapping_key();
578             }
579              
580             sub parse_block_mapping_key {
581 34     34 0 68 my $self = shift;
582 34 100       1008 if ($self->scanner->check_token('YAML::Perl::Token::Key')) {
583 20         491 my $token = $self->scanner->get_token();
584 20 50       711 if (not $self->scanner->check_token(qw(
585             YAML::Perl::Token::Key
586             YAML::Perl::Token::Value
587             YAML::Perl::Token::BlockEnd
588             ))) {
589 20         35 push @{$self->states}, 'parse_block_mapping_value';
  20         573  
590 20         199 return $self->parse_block_node_or_indentless_sequence();
591             }
592             else {
593 0         0 $self->state('parse_block_mapping_value');
594 0         0 return $self->process_empty_scalar($token->end_mark);
595             }
596             }
597 14 100       380 if (not $self->scanner->check_token('YAML::Perl::Token::BlockEnd')) {
598 1         31 my $token = $self->scanner->peek_token();
599 1         24 throw YAML::Perl::Error::Parser(
600             "while parsing a block mapping", $self->marks->[-1],
601             "expected , but found ", $token->id, $token->start_mark
602             );
603             }
604 13         321 my $token = $self->scanner->get_token();
605 13         337 my $event = YAML::Perl::Event::MappingEnd->new(
606             start_mark => $token->start_mark,
607             end_mark => $token->end_mark,
608             );
609 13         29 $self->state(pop @{$self->states});
  13         360  
610 13         27 pop @{$self->marks};
  13         339  
611 13         398 return $event;
612             }
613              
614             sub parse_block_mapping_value {
615 20     20 0 40 my $self = shift;
616 20 50       538 if ($self->scanner->check_token('YAML::Perl::Token::Value')) {
617 20         820 my $token = $self->scanner->get_token();
618 20 50       605 if (not $self->scanner->check_token(qw(
619             YAML::Perl::Token::Key
620             YAML::Perl::Token::Value
621             YAML::Perl::Token::BlockEnd
622             ))) {
623 20         46 push @{$self->states}, 'parse_block_mapping_key';
  20         589  
624 20         152 return $self->parse_block_node_or_indentless_sequence();
625             }
626             else {
627 0         0 $self->state('parse_block_mapping_key');
628 0         0 return $self->process_empty_scalar($token->end_mark);
629             }
630             }
631             else {
632 0         0 $self->state($self->parse_block_mapping_key);
633 0         0 my $token = $self->scanner->peek_token();
634 0         0 return $self->process_empty_scalar($token->start_mark);
635             }
636             }
637              
638             sub parse_flow_sequence_first_entry {
639 6     6 0 13 my $self = shift;
640 6         145 my $token = $self->scanner->get_token();
641 6         12 push @{$self->marks}, $token->start_mark;
  6         149  
642 6         41 return $self->parse_flow_sequence_entry(True);
643             }
644              
645             sub parse_flow_sequence_entry {
646 16     16 0 28 my $self = shift;
647 16 100       48 my $first = @_ ? shift : False;
648 16 100       376 if (not $self->scanner->check_token('YAML::Perl::Token::FlowSequenceEnd')) {
649 10 100       30 if (not $first) {
650 6 50       145 if ($self->scanner->check_token('YAML::Perl::Token::FlowEntry')) {
651 6         222 $self->scanner->get_token();
652             }
653             else {
654 0         0 my $token = $self->scanner->peek_token();
655 0         0 throw YAML::Perl::Error::Parser(
656             "while parsing a flow sequence",
657             $self->marks->[-1],
658             "expected ',' or ']', but got %r",
659             $token->id,
660             $token->start_mark
661             );
662             }
663             }
664            
665 10 100       289 if ($self->scanner->check_token('YAML::Perl::Token::Key')) {
    50          
666 4         112 my $token = $self->scanner->peek_token();
667 4         111 my $event = YAML::Perl::Event::MappingStart->new(
668             anchor => undef,
669             tag => undef,
670             implicit => True,
671             start_mark => $token->start_mark,
672             end_mark => $token->end_mark,
673             flow_style => True,
674             );
675 4         147 $self->state('parse_flow_sequence_entry_mapping_key');
676 4         114 return $event;
677             }
678             elsif (not $self->scanner->check_token('YAML::Perl::Token::FlowSequenceEnd')) {
679 6         9 push @{$self->states}, 'parse_flow_sequence_entry';
  6         175  
680 6         27 return $self->parse_flow_node();
681             }
682             }
683 6         166 my $token = $self->scanner->get_token();
684 6         155 my $event = YAML::Perl::Event::SequenceEnd->new(
685             start_mark => $token->start_mark,
686             end_mark => $token->end_mark,
687             );
688 6         14 $self->state(pop @{$self->states});
  6         151  
689 6         13 pop @{$self->marks};
  6         159  
690 6         193 return $event;
691             }
692              
693             sub parse_flow_sequence_entry_mapping_key {
694 4     4 0 9 my $self = shift;
695 4         93 my $token = $self->scanner->get_token();
696 4 50       93 if (not $self->scanner->check_token(
697             'YAML::Perl::Token::Value',
698             'YAML::Perl::Token::FlowEntry',
699             'YAML::Perl::Token::FlowSequenceEnd',
700             )) {
701 4         8 push @{$self->states}, 'parse_flow_sequence_entry_mapping_value';
  4         123  
702 4         21 return $self->parse_flow_node();
703             }
704             else {
705 0         0 $self->state('parse_flow_sequence_entry_mapping_value');
706 0         0 return $self->process_empty_scalar($token->end_mark);
707             }
708             }
709              
710             sub parse_flow_sequence_entry_mapping_value {
711 4     4 0 9 my $self = shift;
712 4 50       103 if ($self->scanner->check_token('YAML::Perl::Token::Value')) {
713 4         105 my $token = $self->scanner->get_token();
714 4 50       104 if (not $self->scanner->check_token(
715             'YAML::Perl::Token::FlowEntry',
716             'YAML::Perl::Token::FlowSequenceEnd'
717             )) {
718 4         6 push @{$self->states}, 'parse_flow_sequence_entry_mapping_end';
  4         104  
719 4         13 return $self->parse_flow_node();
720             }
721             else {
722 0         0 $self->state('parse_flow_sequence_entry_mapping_end');
723 0         0 return $self->process_empty_scalar($token->end_mark);
724             }
725             }
726             else {
727 0         0 $self->state('parse_flow_sequence_entry_mapping_end');
728 0         0 my $token = $self->scanner->peek_token();
729 0         0 return $self->process_empty_scalar($token->start_mark);
730             }
731             }
732              
733             sub parse_flow_sequence_entry_mapping_end {
734 4     4 0 10 my $self = shift;
735 4         107 $self->state('parse_flow_sequence_entry');
736 4         95 my $token = $self->scanner->peek_token();
737 4         108 return YAML::Perl::Event::MappingEnd->new(
738             start_mark => $token->start_mark,
739             end_mark => $token->start_mark,
740             );
741             }
742              
743             sub parse_flow_mapping_first_key {
744 4     4 0 8 my $self = shift;
745 4         107 my $token = $self->scanner->get_token();
746 4         9 push @{$self->marks}, $token->start_mark;
  4         103  
747 4         18 return $self->parse_flow_mapping_key(True)
748             }
749              
750             sub parse_flow_mapping_key {
751 6     6 0 13 my $self = shift;
752 6 100       23 my $first = @_ ? shift : False;
753              
754 6 100       151 if (not $self->scanner->check_token('YAML::Perl::Token::FlowMappingEnd')) {
755 2 50       8 if (not $first) {
756 0 0       0 if ($self->scanner->check_token('YAML::Perl::Token::FlowEntry')) {
757 0         0 $self->scanner->get_token();
758             }
759             else {
760 0         0 my $token = $self->scanner->peek_token();
761 0         0 throw YAML::Perl::Error::Parser(
762             "while parsing a flow mapping",
763             $self->marks->[-1],
764             "expected ',' or '}', but got %r",
765             $token->id,
766             $token->start_mark
767             );
768             }
769             }
770 2 50       62 if ($self->scanner->check_token('YAML::Perl::Token::Key')) {
    0          
771 2         52 my $token = $self->scanner->get_token();
772 2 50       53 if (not $self->scanner->check_token(
773             'YAML::Perl::Token::Value',
774             'YAML::Perl::Token::FlowEntry',
775             'YAML::Perl::Token::FlowMappingEnd',
776             )) {
777 2         5 push @{$self->states}, 'parse_flow_mapping_value';
  2         61  
778 2         11 return $self->parse_flow_node();
779             }
780             else {
781 0         0 $self->state('parse_flow_mapping_value');
782 0         0 return $self->process_empty_scalar($token->end_mark);
783             }
784             }
785             elsif (not $self->scanner->check_token('YAML::Perl::Token::FlowMappingEnd')) {
786 0         0 push @{$self->states}, 'parse_flow_mapping_empty_value';
  0         0  
787 0         0 return $self->parse_flow_node();
788             }
789             }
790 4         111 my $token = $self->scanner->get_token();
791 4         117 my $event = YAML::Perl::Event::MappingEnd->new(
792             start_mark => $token->start_mark,
793             end_mark => $token->end_mark,
794             );
795 4         10 $self->state(pop @{$self->states});
  4         116  
796 4         8 pop @{$self->marks};
  4         294  
797 4         137 return $event;
798             }
799              
800             sub parse_flow_mapping_value {
801 2     2 0 5 my $self = shift;
802              
803 2 50       50 if ($self->scanner->check_token('YAML::Perl::Token::Value')) {
804 2         48 my $token = $self->scanner->get_token();
805 2 50       50 if (not $self->scanner->check_token(
806             'YAML::Perl::Token::FlowEntry',
807             'YAML::Perl::Token::FlowMappingEnd',
808             )) {
809 2         5 push @{$self->states}, 'parse_flow_mapping_key';
  2         50  
810 2         10 return $self->parse_flow_node();
811             }
812             else {
813 0           $self->state('parse_flow_mapping_key');
814 0           return $self->process_empty_scalar($token->end_mark);
815             }
816             }
817             else {
818 0           $self->state('parse_flow_mapping_key');
819 0           my $token = $self->scanner->peek_token();
820 0           return $self->process_empty_scalar($token->start_mark);
821             }
822             }
823              
824             sub parse_flow_mapping_empty_value {
825 0     0 0   my $self = shift;
826 0           $self->state('parse_flow_mapping_key');
827 0           return $self->process_empty_scalar($self->scanner->peek_token()->start_mark);
828             }
829              
830             sub process_empty_scalar {
831 0     0 0   my ( $self, $mark ) = @_;
832 0           return YAML::Perl::Event::Scalar->new(
833             anchor => undef,
834             tag => undef,
835             implicit => [True, False],
836             value => '',
837             start_mark => $mark,
838             end_mark => $mark
839             );
840             }
841              
842             1;