private static void AddTagDirectives(TagDirectiveCollection directives, IEnumerable <TagDirective> source) { foreach (var directive in source) { if (!directives.Contains(directive)) { directives.Add(directive); } } }
/// <summary> /// Parse directives. /// </summary> private VersionDirective ProcessDirectives(TagDirectiveCollection tags) { VersionDirective version = null; bool hasOwnDirectives = false; while (true) { VersionDirective currentVersion; TagDirective tag; if ((currentVersion = GetCurrentToken() as VersionDirective) != null) { if (version != null) { throw new SemanticErrorException(currentVersion.Start, currentVersion.End, "Found duplicate %YAML directive."); } if (currentVersion.Version.Major != Constants.MajorVersion || currentVersion.Version.Minor != Constants.MinorVersion) { throw new SemanticErrorException(currentVersion.Start, currentVersion.End, "Found incompatible YAML document."); } version = currentVersion; hasOwnDirectives = true; } else if ((tag = GetCurrentToken() as TagDirective) != null) { if (tags.Contains(tag.Handle)) { throw new SemanticErrorException(tag.Start, tag.End, "Found duplicate %TAG directive."); } tags.Add(tag); hasOwnDirectives = true; } else { break; } Skip(); } AddTagDirectives(tags, Constants.DefaultTagDirectives); if (hasOwnDirectives) { tagDirectives.Clear(); } AddTagDirectives(tagDirectives, tags); return(version); }
/// <summary> /// Parse the productions: /// implicit_document ::= block_node DOCUMENT-END* /// * /// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* /// ************************* /// </summary> private ParsingEvent ParseDocumentStart(bool isImplicit) { // Parse extra document end indicators. if (!isImplicit) { while (GetCurrentToken() is DocumentEnd) { Skip(); } } // Parse an isImplicit document. if (isImplicit && !(GetCurrentToken() is VersionDirective || GetCurrentToken() is TagDirective || GetCurrentToken() is DocumentStart || GetCurrentToken() is StreamEnd)) { TagDirectiveCollection directives = new TagDirectiveCollection(); ProcessDirectives(directives); states.Push(ParserState.DocumentEnd); state = ParserState.BlockNode; return(new Events.DocumentStart(null, directives, true, GetCurrentToken().Start, GetCurrentToken().End)); } // Parse an explicit document. else if (!(GetCurrentToken() is StreamEnd)) { Mark start = GetCurrentToken().Start; TagDirectiveCollection directives = new TagDirectiveCollection(); VersionDirective versionDirective = ProcessDirectives(directives); var current = GetCurrentToken(); if (!(current is DocumentStart)) { throw new SemanticErrorException(current.Start, current.End, "Did not find expected <document start>."); } states.Push(ParserState.DocumentEnd); state = ParserState.DocumentContent; ParsingEvent evt = new Events.DocumentStart(versionDirective, directives, false, start, current.End); Skip(); return(evt); } // Parse the stream end. else { state = ParserState.StreamEnd; ParsingEvent evt = new Events.StreamEnd(GetCurrentToken().Start, GetCurrentToken().End); // Do not call skip here because that would throw an exception if (scanner.MoveNextWithoutConsuming()) { throw new InvalidOperationException("The scanner should contain no more tokens."); } return(evt); } }