package YAML::Parser; use strict; use warnings; # The following YAML grammar is LL(1) and is parsed by a recursive descent # parser. # # stream ::= STREAM-START implicit_document? explicit_document* STREAM-END # implicit_document ::= block_node DOCUMENT-END* # explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* # block_node_or_indentless_sequence ::= # ALIAS # | properties (block_content | indentless_block_sequence)? # | block_content # | indentless_block_sequence # block_node ::= ALIAS # | properties block_content? # | block_content # flow_node ::= ALIAS # | properties flow_content? # | flow_content # properties ::= TAG ANCHOR? | ANCHOR TAG? # block_content ::= block_collection | flow_collection | SCALAR # flow_content ::= flow_collection | SCALAR # block_collection ::= block_sequence | block_mapping # flow_collection ::= flow_sequence | flow_mapping # block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END # indentless_sequence ::= (BLOCK-ENTRY block_node?)+ # block_mapping ::= BLOCK-MAPPING_START # ((KEY block_node_or_indentless_sequence?)? # (VALUE block_node_or_indentless_sequence?)?)* # BLOCK-END # flow_sequence ::= FLOW-SEQUENCE-START # (flow_sequence_entry FLOW-ENTRY)* # flow_sequence_entry? # FLOW-SEQUENCE-END # flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? # flow_mapping ::= FLOW-MAPPING-START # (flow_mapping_entry FLOW-ENTRY)* # flow_mapping_entry? # FLOW-MAPPING-END # flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? # # FIRST sets: # # stream: { STREAM-START } # explicit_document: { DIRECTIVE DOCUMENT-START } # implicit_document: FIRST(block_node) # block_node: { ALIAS TAG ANCHOR SCALAR BLOCK-SEQUENCE-START BLOCK-MAPPING-START FLOW-SEQUENCE-START FLOW-MAPPING-START } # flow_node: { ALIAS ANCHOR TAG SCALAR FLOW-SEQUENCE-START FLOW-MAPPING-START } # block_content: { BLOCK-SEQUENCE-START BLOCK-MAPPING-START FLOW-SEQUENCE-START FLOW-MAPPING-START SCALAR } # flow_content: { FLOW-SEQUENCE-START FLOW-MAPPING-START SCALAR } # block_collection: { BLOCK-SEQUENCE-START BLOCK-MAPPING-START } # flow_collection: { FLOW-SEQUENCE-START FLOW-MAPPING-START } # block_sequence: { BLOCK-SEQUENCE-START } # block_mapping: { BLOCK-MAPPING-START } # block_node_or_indentless_sequence: { ALIAS ANCHOR TAG SCALAR BLOCK-SEQUENCE-START BLOCK-MAPPING-START FLOW-SEQUENCE-START FLOW-MAPPING-START BLOCK-ENTRY } # indentless_sequence: { ENTRY } # flow_collection: { FLOW-SEQUENCE-START FLOW-MAPPING-START } # flow_sequence: { FLOW-SEQUENCE-START } # flow_mapping: { FLOW-MAPPING-START } # flow_sequence_entry: { ALIAS ANCHOR TAG SCALAR FLOW-SEQUENCE-START FLOW-MAPPING-START KEY } # flow_mapping_entry: { ALIAS ANCHOR TAG SCALAR FLOW-SEQUENCE-START FLOW-MAPPING-START KEY } #> __all__ = ['Parser', 'ParserError'] #> #> from error import MarkedYAMLError #> from tokens import * #> from events import * #> from scanner import * use YAML::Error; use YAML::Events; #> class ParserError(MarkedYAMLError): #> pass package YAML::Parser::Error; use YAML::Error::Marked -base; #> class Parser(object): #> # Since writing a recursive-descendant parser is a straightforward #> # task, we do not give many comments here. package YAML::Parser; use YAML::Processor -base; field 'next_layer' => 'scanner'; field 'scanner_class', -init => '"YAML::Scanner"'; field 'scanner', -init => '$self->create("scanner")'; #> DEFAULT_TAGS = { #> u'!': u'!', #> u'!!': u'tag:yaml.org,2002:', #> } #> def __init__(self): #> self.current_event = None #> self.yaml_version = None #> self.tag_handles = {} #> self.states = [] #> self.marks = [] #> self.state = self.parse_stream_start field 'current_event'; field 'yaml_version'; field 'tag_handles'; field 'states' => []; field 'marks' => []; field 'state' => 'parse_stream_start'; #> def check_event(self, *choices): #> # Check the type of the next event. #> if self.current_event is None: #> if self.state: #> self.current_event = self.state() #> if self.current_event is not None: #> if not choices: #> return True #> for choice in choices: #> if isinstance(self.current_event, choice): #> return True #> return False sub check_event { my $self = shift; my @choices = @_; if (not defined $self->current_event) { if ($self->state) { my $state = $self->state; $self->{current_event} = $self->$state(); } } if (defined $self->current_event) { return 1 unless @choices; for my $choice (@choices) { return 1 if $self->current_event->isa($choice); } } return 0; } #> def peek_event(self): #> # Get the next event. #> if self.current_event is None: #> if self.state: #> self.current_event = self.state() #> return self.current_event sub peek_event { my $self = shift; if (not defined $self->current_event) { if (my $state = $self->state) { XXX $state; $self->{current_event} = $self->$state; } } return $self->current_event; } #> def get_event(self): #> # Get the next event and proceed further. #> if self.current_event is None: #> if self.state: #> self.current_event = self.state() #> value = self.current_event #> self.current_event = None #> return value sub get_event { my $self = shift; if (not defined $self->current_event) { if (my $state = $self->state) { $self->{current_event} = $self->$state; } } my $value = $self->current_event; $self->{current_event} = undef; return $value; } # stream ::= STREAM-START implicit_document? explicit_document* STREAM-END # implicit_document ::= block_node DOCUMENT-END* # explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* #> def parse_stream_start(self): #> #> # Parse the stream start. #> token = self.get_token() #> event = StreamStartEvent(token.start_mark, token.end_mark, #> encoding=token.encoding) #> #> # Prepare the next state. #> self.state = self.parse_implicit_document_start #> #> return event sub parse_stream_start { my $self = shift; my $token = $self->scanner->get_token(); assert(ref($token) eq 'YAML::Token::StreamStart'); my $event = YAML::Event::StreamStart->new( start_mark => $token->start_mark, end_mark => $token->end_mark, encoding => $token->encoding, ); $self->{state} = 'parse_implicit_document_start'; return $event; } #> def parse_implicit_document_start(self): #> #> # Parse an implicit document. #> if not self.check_token(DirectiveToken, DocumentStartToken, #> StreamEndToken): #> self.tag_handles = self.DEFAULT_TAGS #> token = self.peek_token() #> start_mark = end_mark = token.start_mark #> event = DocumentStartEvent(start_mark, end_mark, #> explicit=False) #> #> # Prepare the next state. #> self.states.append(self.parse_document_end) #> self.state = self.parse_block_node #> #> return event #> #> else: #> return self.parse_document_start() sub parse_implicit_document_start { my $self = shift; if (not $self->scanner->check_token(qw( YAML::Token::Directive YAML::Token::DocumentStart YAML::Token::StreamEnd ))) { $self->{tag_handles} = $self->DEFAULT_TAGS; my $token = $self->scanner->peek_token(); my $start_mark = $token->start_mark; my $end_mark = $start_mark; my $event = YAML::Event::DocumentStart->new( start_mark => $start_mark, end_mark => $end_mark, explicit => 0, ); push @{$self->states}, 'parse_document_end'; $self->{state} = 'parse_block_node'; return $event; } return $self->parse_document_start(); } #> def parse_document_start(self): #> #> # Parse an explicit document. #> if not self.check_token(StreamEndToken): #> token = self.peek_token() #> start_mark = token.start_mark #> version, tags = self.process_directives() #> if not self.check_token(DocumentStartToken): #> raise ParserError(None, None, #> "expected '', but found %r" #> % self.peek_token().id, #> self.peek_token().start_mark) #> token = self.get_token() #> end_mark = token.end_mark #> event = DocumentStartEvent(start_mark, end_mark, #> explicit=True, version=version, tags=tags) #> self.states.append(self.parse_document_end) #> self.state = self.parse_document_content #> else: #> # Parse the end of the stream. #> token = self.get_token() #> event = StreamEndEvent(token.start_mark, token.end_mark) #> assert not self.states #> assert not self.marks #> self.state = None #> return event sub parse_document_start { my $self = shift; my $event; if (not $self->scanner->check_token('YAML::Token::StreamEnd')) { my $token = $self->scanner->peek_token(); my $start_mark = $token->start_mark; my ($version, $tags) = $self->process_directives(); if (not $self->scanner->check_token('YAML::Token::DocumentStart')) { throw YAML::Parser::Error->new( undef, undef, "expected 'scanner->peek_token->id, self->scanner->peek_token->start_mark ); } $token = $self->scanner->get_token(); my $end_mark = $token->end_mark; $event = YAML::Event::DocumentStart->new( start_mark => $start_mark, end_mark => $end_mark, explicit => 1, version => $version, tags => $tags, ); push @{$self->states}, 'parse_document_end'; $self->{state} = 'parse_document_content'; } else { my $token = $self->scanner->get_token(); $event = YAML::Event::StreamEnd->new( start_mark => $token->start_mark, end_mark => $token->end_mark, ); assert not scalar @{$self->states}; assert not scalar @{$self->marks}; $self->{state} = undef; } return $event; } #> def parse_document_end(self): #> # Parse the document end. #> token = self.peek_token() #> start_mark = end_mark = token.start_mark #> explicit = False #> while self.check_token(DocumentEndToken): #> token = self.get_token() #> end_mark = token.end_mark #> explicit = True #> event = DocumentEndEvent(start_mark, end_mark, #> explicit=explicit) #> # Prepare the next state. #> self.state = self.parse_document_start #> return event sub parse_document_end { my $self = shift; my $token = $self->scanner->peek_token(); my $start_mark = $token->start_mark; my $end_mark = $start_mark; my $explicit = 0; while ($self->scanner->check_token('YAML::Token::DocumentEnd')) { $token = $self->scanner->get_token(); $end_mark = $token->end_mark; $explicit = 1; } my $event = YAML::Event::DocumentEnd->new( start_mark => $start_mark, end_mark => $end_mark, explicit => $explicit, ); $self->{state} = 'parse_document_start'; return $event; } #> def parse_document_content(self): #> if self.check_token(DirectiveToken, #> DocumentStartToken, DocumentEndToken, StreamEndToken): #> event = self.process_empty_scalar(self.peek_token().start_mark) #> self.state = self.states.pop() #> return event #> else: #> return self.parse_block_node() sub parse_document_content { my $self = shift; if ( $self->scanner->check_token( map "YAML::Token::${_}", qw/ DocumentStart DocumentEnd StreamEnd / ) ) { my $event = $self->process_empty_scalar( $self->scanner->peek_token()->start_mark() ); $self->state( pop @{ $self->states() } ); return $event; } else { return $self->parse_block_node(); } } #> def process_directives(self): #> self.yaml_version = None #> self.tag_handles = {} #> while self.check_token(DirectiveToken): #> token = self.get_token() #> if token.name == u'YAML': #> if self.yaml_version is not None: #> raise ParserError(None, None, #> "found duplicate YAML directive", token.start_mark) #> major, minor = token.value #> if major != 1: #> raise ParserError(None, None, #> "found incompatible YAML document (version 1.* is required)", #> token.start_mark) #> self.yaml_version = token.value #> elif token.name == u'TAG': #> handle, prefix = token.value #> if handle in self.tag_handles: #> raise ParserError(None, None, #> "duplicate tag handle %r" % handle.encode('utf-8'), #> token.start_mark) #> self.tag_handles[handle] = prefix #> if self.tag_handles: #> value = self.yaml_version, self.tag_handles.copy() #> else: #> value = self.yaml_version, None #> for key in self.DEFAULT_TAGS: #> if key not in self.tag_handles: #> self.tag_handles[key] = self.DEFAULT_TAGS[key] #> return value sub process_directives { my $self = shift; $self->{yaml_version} = undef; $self->{tag_handles} = {}; while ($self->scanner->check_token('YAML::Token::Directive')) { XXX my $token = $self->get_token(); } } #> def process_empty_scalar(self, mark): #> return ScalarEvent(None, None, (True, False), u'', mark, mark) sub process_empty_scalar { my ( $self, $mark ) = @_; return YAML::Event::Scalar->new( anchor => undef, tag => undef, implicit => 1, # what does (True, False) mean?? value => '', start_mark => $mark, end_mark => $mark ); } #> # block_node_or_indentless_sequence ::= ALIAS #> # | properties (block_content | indentless_block_sequence)? #> # | block_content #> # | indentless_block_sequence #> # block_node ::= ALIAS #> # | properties block_content? #> # | block_content #> # flow_node ::= ALIAS #> # | properties flow_content? #> # | flow_content #> # properties ::= TAG ANCHOR? | ANCHOR TAG? #> # block_content ::= block_collection | flow_collection | SCALAR #> # flow_content ::= flow_collection | SCALAR #> # block_collection ::= block_sequence | block_mapping #> # flow_collection ::= flow_sequence | flow_mapping #> def parse_block_node(self): #> return self.parse_node(block=True) sub parse_block_node { my $self = shift; return $self->parse_node(1, 0); } #> def parse_flow_node(self): #> return self.parse_node() sub parse_flow_node { my $self = shift; return $self->parse_node(0, 0); } #> def parse_block_node_or_indentless_sequence(self): #> return self.parse_node(block=True, indentless_sequence=True) sub parse_block_node_or_indentless_sequence { my $self = shift; return $self->parse_node(1, 1); } #> def parse_node(self, block=False, indentless_sequence=False): sub parse_node { my $self = shift; assert @_ == 2; my $block = shift; my $indentless_sequence = shift; #> if self.check_token(AliasToken): #> token = self.get_token() #> event = AliasEvent(token.value, token.start_mark, token.end_mark) #> self.state = self.states.pop() my $event; if ($self->scanner->check_token('YAML::Token::Alias')) { my $token = $self->get_token(); $event = YAML::Event::Alias->new( value => $token->value, start_mark => $token->start_mark, end_mark => $token->end_mark, ); } #> else: #> anchor = None #> tag = None #> start_mark = end_mark = tag_mark = None else { my $anchor = undef; my $tag = undef; my $implicit = undef; my ($start_mark, $end_mark, $tag_mark) = (undef, undef, undef); #> if self.check_token(AnchorToken): #> token = self.get_token() #> start_mark = token.start_mark #> end_mark = token.end_mark #> anchor = token.value if ($self->scanner->check_token('YAML::Token::Anchor')) { my $token = $self->scanner->get_token(); $start_mark = $token->start_mark; $end_mark = $token->end_mark; $anchor = $token->value; #> if self.check_token(TagToken): #> token = self.get_token() #> tag_mark = token.start_mark #> end_mark = token.end_mark #> tag = token.value if ($self->scanner->check_token('YAML::Token::Tag')) { my $token = $self->scanner->get_token(); $tag_mark = $token->start_mark; $end_mark = $token->end_mark; $tag = $token->value; } } #> elif self.check_token(TagToken): #> token = self.get_token() #> start_mark = tag_mark = token.start_mark #> end_mark = token.end_mark elsif ($self->scanner->check_token('YAML::Token::Tag')) { my $token = $self->scanner->get_token(); $start_mark = $token->start_mark; $tag_mark = $start_mark; $end_mark = $token->end_mark; #> if self.check_token(AnchorToken): #> token = self.get_token() #> end_mark = token.end_mark #> anchor = token.value if ($self->scanner->check_token('YAML::Token::Anchor')) { my $token = $self->scanner->get_token(); $end_mark = $token->end_mark; $anchor = $token->value; } } #> if tag is not None and tag != u'!': #> handle, suffix = tag if (defined $tag) { my ($handle, $suffix) = @$tag; #> if handle is not None: if (defined $handle) { #> if handle not in self.tag_handles: #> raise ParserError("while parsing a node", start_mark, #> "found undefined tag handle %r" % handle.encode('utf-8'), #> tag_mark) #> tag = self.tag_handles[handle]+suffix if (not exists $self->tag_handles->{$handle}) { throw "while parsing a node... XXX finish this error msg"; } $tag = $self->tag_handles->{$handle}; } #> else: #> tag = suffix else { $tag = $suffix; } } #> #if tag == u'!': #> # raise ParserError("while parsing a node", start_mark, #> # "found non-specific tag '!'", tag_mark, #> # "Please check 'http://pyyaml.org/wiki/YAMLNonSpecificTag' and share your opinion.") #> if start_mark is None: #> start_mark = end_mark = self.peek_token().start_mark if (not defined $start_mark) { $start_mark = $self->scanner->peek_token()->start_mark; $end_mark = $start_mark; } #> event = None #> implicit = (tag is None or tag == u'!') $event = undef; $implicit = (not defined $tag) || ($tag eq '!'); #> if indentless_sequence and self.check_token(BlockEntryToken): #> end_mark = self.peek_token().end_mark #> event = SequenceStartEvent(anchor, tag, implicit, #> start_mark, end_mark) #> self.state = self.parse_indentless_sequence_entry if ($indentless_sequence and $self->scanner->check_token('YAML::Token::BlockEntry') ) { $end_mark = $self->scanner->peek_token()->end_mark; $event = YAML::Event::SequenceStart->new( anchor => $anchor, tag => $tag, implicit => $implicit, start_mark => $start_mark, end_mark => $end_mark, ); } #> else: else { #> if self.check_token(ScalarToken): #> token = self.get_token() #> end_mark = token.end_mark if ($self->scanner->check_token('YAML::Token::Scalar')) { my $token = $self->scanner->get_token(); $end_mark = $token->end_mark; #> if (token.plain and tag is None) or tag == u'!': #> implicit = (True, False) if (($token->plain and not defined $tag) or $tag eq '!') { $implicit = [1, 0]; } #> elif tag is None: #> implicit = (False, True) elsif (not defined $tag) { $implicit = [0, 1]; } #> else: #> implicit = (False, False) else { $implicit = [0, 0]; } #> event = ScalarEvent(anchor, tag, implicit, token.value, #> start_mark, end_mark, style=token.style) #> self.state = self.states.pop() $event = YAML::Event::Scalar->new( anchor => $anchor, tag => $tag, implicit => $implicit, value => $token->value, start_mark => $start_mark, end_mark => $end_mark, style => $token->style, ); $self->{state} = pop @{$self->states}; } #> elif self.check_token(FlowSequenceStartToken): #> end_mark = self.peek_token().end_mark #> event = SequenceStartEvent(anchor, tag, implicit, #> start_mark, end_mark, flow_style=True) #> self.state = self.parse_flow_sequence_first_entry elsif ($self->scanner->check_token('YAML::Token::FlowSequenceStart')) { $end_mark = $self->scanner->peek_token()->end_mark; $event = YAML::Event::SequenceStart->new( anchor => $anchor, tag => $tag, implicit => $implicit, start_mark => $start_mark, end_mark => $end_mark, flow_style => 1, ); $self->{state} = 'parse_flow_sequence_first_entry'; } #> elif self.check_token(FlowMappingStartToken): #> end_mark = self.peek_token().end_mark #> event = MappingStartEvent(anchor, tag, implicit, #> start_mark, end_mark, flow_style=True) #> self.state = self.parse_flow_mapping_first_key elsif ($self->scanner->check_token('YAML::Token::FlowMappingStart')) { $end_mark = $self->scanner->peek_token()->end_mark; $event = YAML::Event::MappingStart->new( anchor => $anchor, tag => $tag, implicit => $implicit, start_mark => $start_mark, end_mark => $end_mark, flow_style => 1, ); $self->{state} = 'parse_flow_mapping_first_entry'; } #> elif block and self.check_token(BlockSequenceStartToken): #> end_mark = self.peek_token().start_mark #> event = SequenceStartEvent(anchor, tag, implicit, #> start_mark, end_mark, flow_style=False) #> self.state = self.parse_block_sequence_first_entry elsif ($self->scanner->check_token('YAML::Token::BlockSequenceStart')) { $end_mark = $self->scanner->peek_token()->end_mark; $event = YAML::Event::SequenceStart->new( anchor => $anchor, tag => $tag, implicit => $implicit, start_mark => $start_mark, end_mark => $end_mark, flow_style => 0, ); $self->{state} = 'parse_block_sequence_first_entry'; } #> elif block and self.check_token(BlockMappingStartToken): #> end_mark = self.peek_token().start_mark #> event = MappingStartEvent(anchor, tag, implicit, #> start_mark, end_mark, flow_style=False) #> self.state = self.parse_block_mapping_first_key elsif ($self->scanner->check_token('YAML::Token::BlockMappingStart')) { $end_mark = $self->scanner->peek_token()->end_mark; $event = YAML::Event::MappingStart->new( anchor => $anchor, tag => $tag, implicit => $implicit, start_mark => $start_mark, end_mark => $end_mark, flow_style => 0, ); $self->{state} = 'parse_block_mapping_first_entry'; } #> elif anchor is not None or tag is not None: #> # Empty scalars are allowed even if a tag or an anchor is #> # specified. #> event = ScalarEvent(anchor, tag, (implicit, False), u'', #> start_mark, end_mark) #> self.state = self.states.pop() elsif (defined $anchor or defined $tag) { $event = YAML::Event::Scalar->new( anchor => $anchor, tag => $tag, implicit => [$implicit, 0], value => '', start_mark => $start_mark, end_mark => $end_mark, ); $self->{state} = pop @{$self->states}; } #> else: #> if block: #> node = 'block' #> else: #> node = 'flow' #> token = self.peek_token() #> raise ParserError("while parsing a %s node" % node, start_mark, #> "expected the node content, but found %r" % token.id, #> token.start_mark) else { my $node = $block ? 'block' : 'flow'; my $token = $self->scanner->peek_token(); throw "while parsing a $node node, XXX - finish error msg"; } } } #> return event return $event; } #> # block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END #> def parse_block_sequence_first_entry(self): #> token = self.get_token() #> self.marks.append(token.start_mark) #> return self.parse_block_sequence_entry() sub parse_block_sequence_entry { my $self = shift; my $token = $self->scanner->get_token(); push @{$self->marks}, $token->start_mark; return $self->parse_block_sequence_entry(); } #> def parse_block_sequence_entry(self): #> if self.check_token(BlockEntryToken): #> token = self.get_token() #> if not self.check_token(BlockEntryToken, BlockEndToken): #> self.states.append(self.parse_block_sequence_entry) #> return self.parse_block_node() #> else: #> self.state = self.parse_block_sequence_entry #> return self.process_empty_scalar(token.end_mark) #> if not self.check_token(BlockEndToken): #> token = self.peek_token() #> raise ParserError("while parsing a block collection", self.marks[-1], #> "expected , but found %r" % token.id, token.start_mark) #> token = self.get_token() #> event = SequenceEndEvent(token.start_mark, token.end_mark) #> self.state = self.states.pop() #> self.marks.pop() #> return event #> # indentless_sequence ::= (BLOCK-ENTRY block_node?)+ #> def parse_indentless_sequence_entry(self): #> if self.check_token(BlockEntryToken): #> token = self.get_token() #> if not self.check_token(BlockEntryToken, #> KeyToken, ValueToken, BlockEndToken): #> self.states.append(self.parse_indentless_sequence_entry) #> return self.parse_block_node() #> else: #> self.state = self.parse_indentless_sequence_entry #> return self.process_empty_scalar(token.end_mark) #> token = self.peek_token() #> event = SequenceEndEvent(token.start_mark, token.start_mark) #> self.state = self.states.pop() #> return event #> # block_mapping ::= BLOCK-MAPPING_START #> # ((KEY block_node_or_indentless_sequence?)? #> # (VALUE block_node_or_indentless_sequence?)?)* #> # BLOCK-END #> def parse_block_mapping_first_key(self): #> token = self.get_token() #> self.marks.append(token.start_mark) #> return self.parse_block_mapping_key() #> def parse_block_mapping_key(self): #> if self.check_token(KeyToken): #> token = self.get_token() #> if not self.check_token(KeyToken, ValueToken, BlockEndToken): #> self.states.append(self.parse_block_mapping_value) #> return self.parse_block_node_or_indentless_sequence() #> else: #> self.state = self.parse_block_mapping_value #> return self.process_empty_scalar(token.end_mark) #> if not self.check_token(BlockEndToken): #> token = self.peek_token() #> raise ParserError("while parsing a block mapping", self.marks[-1], #> "expected , but found %r" % token.id, token.start_mark) #> token = self.get_token() #> event = MappingEndEvent(token.start_mark, token.end_mark) #> self.state = self.states.pop() #> self.marks.pop() #> return event #> def parse_block_mapping_value(self): #> if self.check_token(ValueToken): #> token = self.get_token() #> if not self.check_token(KeyToken, ValueToken, BlockEndToken): #> self.states.append(self.parse_block_mapping_key) #> return self.parse_block_node_or_indentless_sequence() #> else: #> self.state = self.parse_block_mapping_key #> return self.process_empty_scalar(token.end_mark) #> else: #> self.state = self.parse_block_mapping_key #> token = self.peek_token() #> return self.process_empty_scalar(token.start_mark) #> # flow_sequence ::= FLOW-SEQUENCE-START #> # (flow_sequence_entry FLOW-ENTRY)* #> # flow_sequence_entry? #> # FLOW-SEQUENCE-END #> # flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? #> # #> # Note that while production rules for both flow_sequence_entry and #> # flow_mapping_entry are equal, their interpretations are different. #> # For `flow_sequence_entry`, the part `KEY flow_node? (VALUE flow_node?)?` #> # generate an inline mapping (set syntax). #> def parse_flow_sequence_first_entry(self): #> token = self.get_token() #> self.marks.append(token.start_mark) #> return self.parse_flow_sequence_entry(first=True) #> def parse_flow_sequence_entry(self, first=False): #> if not self.check_token(FlowSequenceEndToken): #> if not first: #> if self.check_token(FlowEntryToken): #> self.get_token() #> else: #> token = self.peek_token() #> raise ParserError("while parsing a flow sequence", self.marks[-1], #> "expected ',' or ']', but got %r" % token.id, token.start_mark) #> #> if self.check_token(KeyToken): #> token = self.peek_token() #> event = MappingStartEvent(None, None, True, #> token.start_mark, token.end_mark, #> flow_style=True) #> self.state = self.parse_flow_sequence_entry_mapping_key #> return event #> elif not self.check_token(FlowSequenceEndToken): #> self.states.append(self.parse_flow_sequence_entry) #> return self.parse_flow_node() #> token = self.get_token() #> event = SequenceEndEvent(token.start_mark, token.end_mark) #> self.state = self.states.pop() #> self.marks.pop() #> return event #> def parse_flow_sequence_entry_mapping_key(self): #> token = self.get_token() #> if not self.check_token(ValueToken, #> FlowEntryToken, FlowSequenceEndToken): #> self.states.append(self.parse_flow_sequence_entry_mapping_value) #> return self.parse_flow_node() #> else: #> self.state = self.parse_flow_sequence_entry_mapping_value #> return self.process_empty_scalar(token.end_mark) #> def parse_flow_sequence_entry_mapping_value(self): #> if self.check_token(ValueToken): #> token = self.get_token() #> if not self.check_token(FlowEntryToken, FlowSequenceEndToken): #> self.states.append(self.parse_flow_sequence_entry_mapping_end) #> return self.parse_flow_node() #> else: #> self.state = self.parse_flow_sequence_entry_mapping_end #> return self.process_empty_scalar(token.end_mark) #> else: #> self.state = self.parse_flow_sequence_entry_mapping_end #> token = self.peek_token() #> return self.process_empty_scalar(token.start_mark) #> def parse_flow_sequence_entry_mapping_end(self): #> self.state = self.parse_flow_sequence_entry #> token = self.peek_token() #> return MappingEndEvent(token.start_mark, token.start_mark) #> # flow_mapping ::= FLOW-MAPPING-START #> # (flow_mapping_entry FLOW-ENTRY)* #> # flow_mapping_entry? #> # FLOW-MAPPING-END #> # flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? #> def parse_flow_mapping_first_key(self): #> token = self.get_token() #> self.marks.append(token.start_mark) #> return self.parse_flow_mapping_key(first=True) #> def parse_flow_mapping_key(self, first=False): #> if not self.check_token(FlowMappingEndToken): #> if not first: #> if self.check_token(FlowEntryToken): #> self.get_token() #> else: #> token = self.peek_token() #> raise ParserError("while parsing a flow mapping", self.marks[-1], #> "expected ',' or '}', but got %r" % token.id, token.start_mark) #> if self.check_token(KeyToken): #> token = self.get_token() #> if not self.check_token(ValueToken, #> FlowEntryToken, FlowMappingEndToken): #> self.states.append(self.parse_flow_mapping_value) #> return self.parse_flow_node() #> else: #> self.state = self.parse_flow_mapping_value #> return self.process_empty_scalar(token.end_mark) #> elif not self.check_token(FlowMappingEndToken): #> self.states.append(self.parse_flow_mapping_empty_value) #> return self.parse_flow_node() #> token = self.get_token() #> event = MappingEndEvent(token.start_mark, token.end_mark) #> self.state = self.states.pop() #> self.marks.pop() #> return event #> def parse_flow_mapping_value(self): #> if self.check_token(ValueToken): #> token = self.get_token() #> if not self.check_token(FlowEntryToken, FlowMappingEndToken): #> self.states.append(self.parse_flow_mapping_key) #> return self.parse_flow_node() #> else: #> self.state = self.parse_flow_mapping_key #> return self.process_empty_scalar(token.end_mark) #> else: #> self.state = self.parse_flow_mapping_key #> token = self.peek_token() #> return self.process_empty_scalar(token.start_mark) #> def parse_flow_mapping_empty_value(self): #> self.state = self.parse_flow_mapping_key #> return self.process_empty_scalar(self.peek_token().start_mark) 1;