Class ParserImpl

  • All Implemented Interfaces:
    Parser

    public class ParserImpl
    extends java.lang.Object
    implements Parser
     # 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 }
     
    Since writing a recursive-descendant parser is a straightforward task, we do not give many comments here.
    • Method Detail

      • checkEvent

        public boolean checkEvent​(Event.ID choice)
        Check the type of the next event.
        Specified by:
        checkEvent in interface Parser
        Parameters:
        choice - Event ID.
        Returns:
        true if the next event can be assigned to a variable of the given type. Returns false if no more events are available.
      • peekEvent

        public Event peekEvent()
        Peek the next event (keeping it in the stream)
        Specified by:
        peekEvent in interface Parser
        Returns:
        The event that will be returned on the next call to Parser.getEvent()
      • getEvent

        public Event getEvent()
        Get the next event and proceed further.
        Specified by:
        getEvent in interface Parser
        Returns:
        the next parsed event
      • processDirectives

        private VersionTagsTuple processDirectives()
        https://yaml.org/spec/1.1/#id898785 says "If the document specifies no directives, it is parsed using the same settings as the previous document. If the document does specify any directives, all directives of previous documents, if any, are ignored." TODO the last statement is not respected (as in PyYAML, to work the same)
        Returns:
        directives to be applied for the current document
      • parseFlowNode

        private Event parseFlowNode()
      • parseBlockNodeOrIndentlessSequence

        private Event parseBlockNodeOrIndentlessSequence()
      • parseNode

        private Event parseNode​(boolean block,
                                boolean indentlessSequence)
      • processEmptyScalar

        private Event processEmptyScalar​(Mark mark)
         block_mapping     ::= BLOCK-MAPPING_START
                   ((KEY block_node_or_indentless_sequence?)?
                   (VALUE block_node_or_indentless_sequence?)?)*
                   BLOCK-END