Represents an alias event.
Наследование: ParsingEvent, IAnchorAlias
Пример #1
0
        /// <summary>
        /// Parse the productions:
        /// 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
        ///                                            ******
        /// </summary>
        private ParsingEvent ParseNode(bool isBlock, bool isIndentlessSequence)
        {
            if (GetCurrentToken() is Error errorToken)
            {
                throw new SemanticErrorException(errorToken.Start, errorToken.End, errorToken.Value);
            }

            var current = GetCurrentToken() ?? throw new SemanticErrorException("Reached the end of the stream while parsing a node");

            if (current is AnchorAlias alias)
            {
                state = states.Pop();
                ParsingEvent evt = new Events.AnchorAlias(alias.Value, alias.Start, alias.End);
                Skip();
                return(evt);
            }

            var start = current.Start;

            string?anchorName = null;
            string?tagName    = null;
            Anchor?lastAnchor = null;
            Tag?   lastTag    = null;

            // The anchor and the tag can be in any order. This loop repeats at most twice.
            while (true)
            {
                if (anchorName == null && current is Anchor anchor)
                {
                    lastAnchor = anchor;
                    anchorName = string.IsNullOrEmpty(anchor.Value) ? null : anchor.Value;
                    Skip();
                }
                else if (tagName == null && current is Tag tag)
                {
                    lastTag = tag;
                    if (string.IsNullOrEmpty(tag.Handle))
                    {
                        tagName = tag.Suffix;
                    }
                    else if (tagDirectives.Contains(tag.Handle))
                    {
                        tagName = string.Concat(tagDirectives[tag.Handle].Prefix, tag.Suffix);
                    }
                    else
                    {
                        throw new SemanticErrorException(tag.Start, tag.End, "While parsing a node, found undefined tag handle.");
                    }
                    if (string.IsNullOrEmpty(tagName))
                    {
                        tagName = null;
                    }

                    Skip();
                }
                else if (current is Anchor secondAnchor)
                {
                    throw new SemanticErrorException(secondAnchor.Start, secondAnchor.End, "While parsing a node, found more than one anchor.");
                }
                else if (current is AnchorAlias anchorAlias)
                {
                    throw new SemanticErrorException(anchorAlias.Start, anchorAlias.End, "While parsing a node, did not find expected token.");
                }
                else if (current is Error error)
                {
                    if (lastTag != null && lastAnchor != null && !string.IsNullOrEmpty(anchorName))
                    {
                        return(new Events.Scalar(anchorName, default, string.Empty, default, false, false, lastAnchor.Start, lastAnchor.End));
Пример #2
0
        /// <summary>
        /// Parse the productions:
        /// 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
        ///                                            ******
        /// </summary>
        private ParsingEvent ParseNode(bool isBlock, bool isIndentlessSequence)
        {
            var alias = GetCurrentToken() as AnchorAlias;
            if (alias != null)
            {
                state = states.Pop();
                ParsingEvent evt = new Events.AnchorAlias(alias.Value, alias.Start, alias.End);
                Skip();
                return evt;
            }

            Mark start = GetCurrentToken().Start;

            Anchor anchor = null;
            Tag tag = null;

            // The anchor and the tag can be in any order. This loop repeats at most twice.
            while (true)
            {
                if (anchor == null && (anchor = GetCurrentToken() as Anchor) != null)
                {
                    Skip();
                }
                else if (tag == null && (tag = GetCurrentToken() as Tag) != null)
                {
                    Skip();
                }
                else
                {
                    break;
                }
            }

            string tagName = null;
            if (tag != null)
            {
                if (string.IsNullOrEmpty(tag.Handle))
                {
                    tagName = tag.Suffix;
                }
                else if (tagDirectives.Contains(tag.Handle))
                {
                    tagName = string.Concat(tagDirectives[tag.Handle].Prefix, tag.Suffix);
                }
                else
                {
                    throw new SemanticErrorException(tag.Start, tag.End, "While parsing a node, find undefined tag handle.");
                }
            }
            if (string.IsNullOrEmpty(tagName))
            {
                tagName = null;
            }

            string anchorName = anchor != null ? string.IsNullOrEmpty(anchor.Value) ? null : anchor.Value : null;

            var isImplicit = string.IsNullOrEmpty(tagName);

            if (isIndentlessSequence && GetCurrentToken() is BlockEntry)
            {
                state = ParserState.IndentlessSequenceEntry;

                return new Events.SequenceStart(
                           anchorName,
                           tagName,
                           isImplicit,
                           SequenceStyle.Block,
                           start,
                           GetCurrentToken().End
                       );
            }
            else
            {
                var scalar = GetCurrentToken() as Scalar;
                if (scalar != null)
                {
                    bool isPlainImplicit = false;
                    bool isQuotedImplicit = false;
                    if ((scalar.Style == ScalarStyle.Plain && tagName == null) || tagName == Constants.DefaultHandle)
                    {
                        isPlainImplicit = true;
                    }
                    else if (tagName == null)
                    {
                        isQuotedImplicit = true;
                    }

                    state = states.Pop();
                    ParsingEvent evt = new Events.Scalar(anchorName, tagName, scalar.Value, scalar.Style, isPlainImplicit, isQuotedImplicit, start, scalar.End);

                    Skip();
                    return evt;
                }

                var flowSequenceStart = GetCurrentToken() as FlowSequenceStart;
                if (flowSequenceStart != null)
                {
                    state = ParserState.FlowSequenceFirstEntry;
                    return new Events.SequenceStart(anchorName, tagName, isImplicit, SequenceStyle.Flow, start, flowSequenceStart.End);
                }

                var flowMappingStart = GetCurrentToken() as FlowMappingStart;
                if (flowMappingStart != null)
                {
                    state = ParserState.FlowMappingFirstKey;
                    return new Events.MappingStart(anchorName, tagName, isImplicit, MappingStyle.Flow, start, flowMappingStart.End);
                }

                if (isBlock)
                {
                    var blockSequenceStart = GetCurrentToken() as BlockSequenceStart;
                    if (blockSequenceStart != null)
                    {
                        state = ParserState.BlockSequenceFirstEntry;
                        return new Events.SequenceStart(anchorName, tagName, isImplicit, SequenceStyle.Block, start, blockSequenceStart.End);
                    }

                    var blockMappingStart = GetCurrentToken() as BlockMappingStart;
                    if (blockMappingStart != null)
                    {
                        state = ParserState.BlockMappingFirstKey;
                        return new Events.MappingStart(anchorName, tagName, isImplicit, MappingStyle.Block, start, GetCurrentToken().End);
                    }
                }

                if (anchorName != null || tag != null)
                {
                    state = states.Pop();
                    return new Events.Scalar(anchorName, tagName, string.Empty, ScalarStyle.Plain, isImplicit, false, start, GetCurrentToken().End);
                }

                var current = GetCurrentToken();
                throw new SemanticErrorException(current.Start, current.End, "While parsing a node, did not find expected node content.");
            }
        }
Пример #3
0
        /// <summary>
        /// Parse the productions:
        /// 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
        ///                                            ******
        /// </summary>
        private Event ParseNode(bool isBlock, bool isIndentlessSequence)
        {
            AnchorAlias alias = GetCurrentToken() as AnchorAlias;

            if (alias != null)
            {
                state = states.Pop();
                Event evt = new Events.AnchorAlias(alias.Value, alias.Start, alias.End);
                Skip();
                return(evt);
            }

            Mark start = GetCurrentToken().Start;

            Anchor anchor = null;
            Tag    tag    = null;

            // The anchor and the tag can be in any order. This loop repeats at most twice.
            while (true)
            {
                if (anchor == null && (anchor = GetCurrentToken() as Anchor) != null)
                {
                    Skip();
                }
                else if (tag == null && (tag = GetCurrentToken() as Tag) != null)
                {
                    Skip();
                }
                else
                {
                    break;
                }
            }

            string tagName = null;

            if (tag != null)
            {
                if (string.IsNullOrEmpty(tag.Handle))
                {
                    tagName = tag.Suffix;
                }
                else if (tagDirectives.Contains(tag.Handle))
                {
                    tagName = string.Concat(tagDirectives[tag.Handle].Prefix, tag.Suffix);
                }
                else
                {
                    throw new SemanticErrorException(tag.Start, tag.End, "While parsing a node, find undefined tag handle.");
                }
            }
            if (string.IsNullOrEmpty(tagName))
            {
                tagName = null;
            }

            string anchorName = anchor != null?string.IsNullOrEmpty(anchor.Value) ? null : anchor.Value : null;

            bool isImplicit = string.IsNullOrEmpty(tagName);

            if (isIndentlessSequence && GetCurrentToken() is BlockEntry)
            {
                state = ParserState.YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE;

                return(new Events.SequenceStart(
                           anchorName,
                           tagName,
                           isImplicit,
                           SequenceStyle.Block,
                           start,
                           GetCurrentToken().End
                           ));
            }
            else
            {
                Scalar scalar = GetCurrentToken() as Scalar;
                if (scalar != null)
                {
                    bool isPlainImplicit  = false;
                    bool isQuotedImplicit = false;
                    if ((scalar.Style == ScalarStyle.Plain && tagName == null) || tagName == Constants.DefaultHandle)
                    {
                        isPlainImplicit = true;
                    }
                    else if (tagName == null)
                    {
                        isQuotedImplicit = true;
                    }

                    state = states.Pop();
                    Event evt = new Events.Scalar(anchorName, tagName, scalar.Value, scalar.Style, isPlainImplicit, isQuotedImplicit, start, scalar.End);

                    Skip();
                    return(evt);
                }

                FlowSequenceStart flowSequenceStart = GetCurrentToken() as FlowSequenceStart;
                if (flowSequenceStart != null)
                {
                    state = ParserState.YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE;
                    return(new Events.SequenceStart(anchorName, tagName, isImplicit, SequenceStyle.Flow, start, flowSequenceStart.End));
                }

                FlowMappingStart flowMappingStart = GetCurrentToken() as FlowMappingStart;
                if (flowMappingStart != null)
                {
                    state = ParserState.YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE;
                    return(new Events.MappingStart(anchorName, tagName, isImplicit, MappingStyle.Flow, start, flowMappingStart.End));
                }

                if (isBlock)
                {
                    BlockSequenceStart blockSequenceStart = GetCurrentToken() as BlockSequenceStart;
                    if (blockSequenceStart != null)
                    {
                        state = ParserState.YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE;
                        return(new Events.SequenceStart(anchorName, tagName, isImplicit, SequenceStyle.Block, start, blockSequenceStart.End));
                    }

                    BlockMappingStart blockMappingStart = GetCurrentToken() as BlockMappingStart;
                    if (blockMappingStart != null)
                    {
                        state = ParserState.YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE;
                        return(new Events.MappingStart(anchorName, tagName, isImplicit, MappingStyle.Block, start, GetCurrentToken().End));
                    }
                }

                if (anchorName != null || tag != null)
                {
                    state = states.Pop();
                    return(new Events.Scalar(anchorName, tagName, string.Empty, ScalarStyle.Plain, isImplicit, false, start, GetCurrentToken().End));
                }

                var current = GetCurrentToken();
                throw new SemanticErrorException(current.Start, current.End, "While parsing a node, did not find expected node content.");
            }
        }
Пример #4
0
			void IParsingEventVisitor.Visit(AnchorAlias e)
			{
				clonedEvent = new AnchorAlias(e.Value, e.Start, e.End);
			}
Пример #5
0
        /// <summary>
        /// Parse the productions:
        /// 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
        ///                                            ******
        /// </summary>
        private ParsingEvent ParseNode(bool isBlock, bool isIndentlessSequence)
        {
            var current = GetCurrentToken() ?? throw new SemanticErrorException("Reached the end of the stream while parsing a node");

            if (current is AnchorAlias alias)
            {
                state = states.Pop();
                ParsingEvent evt = new Events.AnchorAlias(alias.Value, alias.Start, alias.End);
                Skip();
                return(evt);
            }

            var start = current.Start;

            string?anchorName = null;
            string?tagName    = null;

            // The anchor and the tag can be in any order. This loop repeats at most twice.
            while (true)
            {
                if (anchorName == null && current is Anchor anchor)
                {
                    anchorName = string.IsNullOrEmpty(anchor.Value) ? null : anchor.Value;
                    Skip();
                }
                else if (tagName == null && current is Tag tag)
                {
                    if (string.IsNullOrEmpty(tag.Handle))
                    {
                        tagName = tag.Suffix;
                    }
                    else if (tagDirectives.Contains(tag.Handle))
                    {
                        tagName = string.Concat(tagDirectives[tag.Handle].Prefix, tag.Suffix);
                    }
                    else
                    {
                        throw new SemanticErrorException(tag.Start, tag.End, "While parsing a node, found undefined tag handle.");
                    }
                    if (string.IsNullOrEmpty(tagName))
                    {
                        tagName = null;
                    }

                    Skip();
                }
                else if (current is AnchorAlias anchorAlias)
                {
                    throw new SemanticErrorException(anchorAlias.Start, anchorAlias.End, "While parsing a node, did not find expected token.");
                }
                else
                {
                    break;
                }

                current = GetCurrentToken() ?? throw new SemanticErrorException("Reached the end of the stream while parsing a node");
            }

            var isImplicit = string.IsNullOrEmpty(tagName);

            if (isIndentlessSequence && GetCurrentToken() is BlockEntry)
            {
                state = ParserState.IndentlessSequenceEntry;

                return(new Events.SequenceStart(
                           anchorName,
                           tagName,
                           isImplicit,
                           SequenceStyle.Block,
                           start,
                           current.End
                           ));
            }
            else
            {
                if (current is Scalar scalar)
                {
                    var isPlainImplicit  = false;
                    var isQuotedImplicit = false;
                    if ((scalar.Style == ScalarStyle.Plain && tagName == null) || tagName == Constants.DefaultHandle)
                    {
                        isPlainImplicit = true;
                    }
                    else if (tagName == null)
                    {
                        isQuotedImplicit = true;
                    }

                    state = states.Pop();
                    Skip();
                    return(new Events.Scalar(anchorName, tagName, scalar.Value, scalar.Style, isPlainImplicit, isQuotedImplicit, start, scalar.End));
                }

                if (current is FlowSequenceStart flowSequenceStart)
                {
                    state = ParserState.FlowSequenceFirstEntry;
                    return(new Events.SequenceStart(anchorName, tagName, isImplicit, SequenceStyle.Flow, start, flowSequenceStart.End));
                }

                if (current is FlowMappingStart flowMappingStart)
                {
                    state = ParserState.FlowMappingFirstKey;
                    return(new Events.MappingStart(anchorName, tagName, isImplicit, MappingStyle.Flow, start, flowMappingStart.End));
                }

                if (isBlock)
                {
                    if (current is BlockSequenceStart blockSequenceStart)
                    {
                        state = ParserState.BlockSequenceFirstEntry;
                        return(new Events.SequenceStart(anchorName, tagName, isImplicit, SequenceStyle.Block, start, blockSequenceStart.End));
                    }

                    if (current is BlockMappingStart blockMappingStart)
                    {
                        state = ParserState.BlockMappingFirstKey;
                        return(new Events.MappingStart(anchorName, tagName, isImplicit, MappingStyle.Block, start, blockMappingStart.End));
                    }
                }

                if (anchorName != null || tagName != null)
                {
                    state = states.Pop();
                    return(new Events.Scalar(anchorName, tagName, string.Empty, ScalarStyle.Plain, isImplicit, false, start, current.End));
                }

                throw new SemanticErrorException(current.Start, current.End, "While parsing a node, did not find expected node content.");
            }
        }
        private ParsingEvent ParseNode(bool isBlock, bool isIndentlessSequence)
        {
            YamlDotNet.Core.Tokens.AnchorAlias anchorAlias = GetCurrentToken() as YamlDotNet.Core.Tokens.AnchorAlias;
            if (anchorAlias != null)
            {
                state = states.Pop();
                ParsingEvent result = new YamlDotNet.Core.Events.AnchorAlias(anchorAlias.Value, anchorAlias.Start, anchorAlias.End);
                Skip();
                return(result);
            }
            Mark   start  = GetCurrentToken().Start;
            Anchor anchor = null;

            YamlDotNet.Core.Tokens.Tag tag = null;
            while (true)
            {
                if (anchor == null && (anchor = (GetCurrentToken() as Anchor)) != null)
                {
                    Skip();
                }
                else
                {
                    if (tag != null || (tag = (GetCurrentToken() as YamlDotNet.Core.Tokens.Tag)) == null)
                    {
                        break;
                    }
                    Skip();
                }
            }
            string text = null;

            if (tag != null)
            {
                if (string.IsNullOrEmpty(tag.Handle))
                {
                    text = tag.Suffix;
                }
                else
                {
                    if (!tagDirectives.Contains(tag.Handle))
                    {
                        throw new SemanticErrorException(tag.Start, tag.End, "While parsing a node, find undefined tag handle.");
                    }
                    text = tagDirectives[tag.Handle].Prefix + tag.Suffix;
                }
            }
            if (string.IsNullOrEmpty(text))
            {
                text = null;
            }
            string text2 = (anchor == null) ? null : ((!string.IsNullOrEmpty(anchor.Value)) ? anchor.Value : null);
            bool   flag  = string.IsNullOrEmpty(text);

            if (isIndentlessSequence && GetCurrentToken() is BlockEntry)
            {
                state = ParserState.IndentlessSequenceEntry;
                return(new SequenceStart(text2, text, flag, SequenceStyle.Block, start, GetCurrentToken().End));
            }
            YamlDotNet.Core.Tokens.Scalar scalar = GetCurrentToken() as YamlDotNet.Core.Tokens.Scalar;
            if (scalar != null)
            {
                bool isPlainImplicit  = false;
                bool isQuotedImplicit = false;
                if ((scalar.Style == ScalarStyle.Plain && text == null) || text == "!")
                {
                    isPlainImplicit = true;
                }
                else if (text == null)
                {
                    isQuotedImplicit = true;
                }
                state = states.Pop();
                ParsingEvent result2 = new YamlDotNet.Core.Events.Scalar(text2, text, scalar.Value, scalar.Style, isPlainImplicit, isQuotedImplicit, start, scalar.End);
                Skip();
                return(result2);
            }
            FlowSequenceStart flowSequenceStart = GetCurrentToken() as FlowSequenceStart;

            if (flowSequenceStart != null)
            {
                state = ParserState.FlowSequenceFirstEntry;
                return(new SequenceStart(text2, text, flag, SequenceStyle.Flow, start, flowSequenceStart.End));
            }
            FlowMappingStart flowMappingStart = GetCurrentToken() as FlowMappingStart;

            if (flowMappingStart != null)
            {
                state = ParserState.FlowMappingFirstKey;
                return(new MappingStart(text2, text, flag, MappingStyle.Flow, start, flowMappingStart.End));
            }
            if (isBlock)
            {
                BlockSequenceStart blockSequenceStart = GetCurrentToken() as BlockSequenceStart;
                if (blockSequenceStart != null)
                {
                    state = ParserState.BlockSequenceFirstEntry;
                    return(new SequenceStart(text2, text, flag, SequenceStyle.Block, start, blockSequenceStart.End));
                }
                BlockMappingStart blockMappingStart = GetCurrentToken() as BlockMappingStart;
                if (blockMappingStart != null)
                {
                    state = ParserState.BlockMappingFirstKey;
                    return(new MappingStart(text2, text, flag, MappingStyle.Block, start, GetCurrentToken().End));
                }
            }
            if (text2 != null || tag != null)
            {
                state = states.Pop();
                return(new YamlDotNet.Core.Events.Scalar(text2, text, string.Empty, ScalarStyle.Plain, flag, false, start, GetCurrentToken().End));
            }
            Token token = GetCurrentToken();

            throw new SemanticErrorException(token.Start, token.End, "While parsing a node, did not find expected node content.");
        }
Пример #7
0
        /// <summary>
        /// Parse the productions:
        /// 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
        ///                                            ******
        /// </summary>
        private ParsingEvent ParseNode(bool isBlock, bool isIndentlessSequence)
        {
            if (GetCurrentToken() is Error errorToken)
            {
                throw new SemanticErrorException(errorToken.Start, errorToken.End, errorToken.Value);
            }

            var current = GetCurrentToken() ?? throw new SemanticErrorException("Reached the end of the stream while parsing a node");

            if (current is AnchorAlias alias)
            {
                state = states.Pop();
                ParsingEvent evt = new Events.AnchorAlias(alias.Value, alias.Start, alias.End);
                Skip();
                return(evt);
            }

            var start = current.Start;

            string?anchorName = null;
            string?tagName    = null;

            // The anchor and the tag can be in any order. This loop repeats at most twice.
            while (true)
            {
                if (anchorName == null && current is Anchor anchor)
                {
                    anchorName = string.IsNullOrEmpty(anchor.Value) ? null : anchor.Value;
                    Skip();
                }
                else if (tagName == null && current is Tag tag)
                {
                    if (string.IsNullOrEmpty(tag.Handle))
                    {
                        tagName = tag.Suffix;
                    }
                    else if (tagDirectives.Contains(tag.Handle))
                    {
                        tagName = string.Concat(tagDirectives[tag.Handle].Prefix, tag.Suffix);
                    }
                    else
                    {
                        throw new SemanticErrorException(tag.Start, tag.End, "While parsing a node, found undefined tag handle.");
                    }
                    if (string.IsNullOrEmpty(tagName))
                    {
                        tagName = null;
                    }

                    Skip();
                }
                else if (current is Anchor secondAnchor)
                {
                    throw new SemanticErrorException(secondAnchor.Start, secondAnchor.End, "While parsing a node, found more than one anchor.");
                }
                else if (current is AnchorAlias anchorAlias)
                {
                    throw new SemanticErrorException(anchorAlias.Start, anchorAlias.End, "While parsing a node, did not find expected token.");
                }
                else if (current is Error)
                {
                    errorToken = (current as Error) !;
                    throw new SemanticErrorException(errorToken.Start, errorToken.End, errorToken.Value);
                }
                else
                {
                    break;
                }

                current = GetCurrentToken() ?? throw new SemanticErrorException("Reached the end of the stream while parsing a node");
            }

            var isImplicit = string.IsNullOrEmpty(tagName);

            if (isIndentlessSequence && GetCurrentToken() is BlockEntry)
            {
                state = ParserState.IndentlessSequenceEntry;

                return(new Events.SequenceStart(
                           anchorName,
                           tagName,
                           isImplicit,
                           SequenceStyle.Block,
                           start,
                           current.End
                           ));
            }
            else
            {
                if (current is Scalar scalar)
                {
                    var isPlainImplicit  = false;
                    var isQuotedImplicit = false;
                    if ((scalar.Style == ScalarStyle.Plain && tagName == null) || tagName == Constants.DefaultHandle)
                    {
                        isPlainImplicit = true;
                    }
                    else if (tagName == null)
                    {
                        isQuotedImplicit = true;
                    }

                    state = states.Pop();
                    Skip();

                    ParsingEvent evt = new Events.Scalar(anchorName, tagName, scalar.Value, scalar.Style, isPlainImplicit, isQuotedImplicit, start, scalar.End);

                    // Read next token to ensure the error case spec test 'CXX2':
                    // "Mapping with anchor on document start line".

                    if (anchorName != null && scanner.MoveNextWithoutConsuming())
                    {
                        currentToken = scanner.Current;
                        if (currentToken is Error)
                        {
                            errorToken = (currentToken as Error) !;
                            throw new SemanticErrorException(errorToken.Start, errorToken.End, errorToken.Value);
                        }
                    }

                    // Read next token to ensure the error case spec test 'T833':
                    // "Flow mapping missing a separating comma".

                    if (state == ParserState.FlowMappingKey && scanner.MoveNextWithoutConsuming())
                    {
                        currentToken = scanner.Current;
                        if (currentToken != null && !(currentToken is FlowEntry) && !(currentToken is FlowMappingEnd))
                        {
                            throw new SemanticErrorException(currentToken.Start, currentToken.End, "While parsing a flow mapping, did not find expected ',' or '}'.");
                        }
                    }

                    return(evt);
                }

                if (current is FlowSequenceStart flowSequenceStart)
                {
                    state = ParserState.FlowSequenceFirstEntry;
                    return(new Events.SequenceStart(anchorName, tagName, isImplicit, SequenceStyle.Flow, start, flowSequenceStart.End));
                }

                if (current is FlowMappingStart flowMappingStart)
                {
                    state = ParserState.FlowMappingFirstKey;
                    return(new Events.MappingStart(anchorName, tagName, isImplicit, MappingStyle.Flow, start, flowMappingStart.End));
                }

                if (isBlock)
                {
                    if (current is BlockSequenceStart blockSequenceStart)
                    {
                        state = ParserState.BlockSequenceFirstEntry;
                        return(new Events.SequenceStart(anchorName, tagName, isImplicit, SequenceStyle.Block, start, blockSequenceStart.End));
                    }

                    if (current is BlockMappingStart blockMappingStart)
                    {
                        state = ParserState.BlockMappingFirstKey;
                        return(new Events.MappingStart(anchorName, tagName, isImplicit, MappingStyle.Block, start, blockMappingStart.End));
                    }
                }

                if (anchorName != null || tagName != null)
                {
                    state = states.Pop();
                    return(new Events.Scalar(anchorName, tagName, string.Empty, ScalarStyle.Plain, isImplicit, false, start, current.End));
                }

                throw new SemanticErrorException(current.Start, current.End, "While parsing a node, did not find expected node content.");
            }
        }