YAMLParser.h revision 288943
1234285Sdim//===--- YAMLParser.h - Simple YAML parser --------------------------------===// 2234285Sdim// 3234285Sdim// The LLVM Compiler Infrastructure 4234285Sdim// 5234285Sdim// This file is distributed under the University of Illinois Open Source 6234285Sdim// License. See LICENSE.TXT for details. 7234285Sdim// 8234285Sdim//===----------------------------------------------------------------------===// 9234285Sdim// 10234285Sdim// This is a YAML 1.2 parser. 11234285Sdim// 12234285Sdim// See http://www.yaml.org/spec/1.2/spec.html for the full standard. 13234285Sdim// 14234285Sdim// This currently does not implement the following: 15234285Sdim// * Multi-line literal folding. 16234285Sdim// * Tag resolution. 17234285Sdim// * UTF-16. 18234285Sdim// * BOMs anywhere other than the first Unicode scalar value in the file. 19234285Sdim// 20234285Sdim// The most important class here is Stream. This represents a YAML stream with 21234285Sdim// 0, 1, or many documents. 22234285Sdim// 23234285Sdim// SourceMgr sm; 24234285Sdim// StringRef input = getInput(); 25234285Sdim// yaml::Stream stream(input, sm); 26234285Sdim// 27234285Sdim// for (yaml::document_iterator di = stream.begin(), de = stream.end(); 28234285Sdim// di != de; ++di) { 29234285Sdim// yaml::Node *n = di->getRoot(); 30234285Sdim// if (n) { 31234285Sdim// // Do something with n... 32234285Sdim// } else 33234285Sdim// break; 34234285Sdim// } 35234285Sdim// 36234285Sdim//===----------------------------------------------------------------------===// 37234285Sdim 38249423Sdim#ifndef LLVM_SUPPORT_YAMLPARSER_H 39249423Sdim#define LLVM_SUPPORT_YAMLPARSER_H 40234285Sdim 41234285Sdim#include "llvm/ADT/StringRef.h" 42234285Sdim#include "llvm/Support/Allocator.h" 43234285Sdim#include "llvm/Support/SMLoc.h" 44276479Sdim#include <limits> 45261991Sdim#include <map> 46234285Sdim#include <utility> 47234285Sdim 48234285Sdimnamespace llvm { 49288943Sdimclass MemoryBufferRef; 50234285Sdimclass SourceMgr; 51288943Sdimclass Twine; 52234285Sdimclass raw_ostream; 53234285Sdim 54234285Sdimnamespace yaml { 55234285Sdim 56234285Sdimclass document_iterator; 57234285Sdimclass Document; 58234285Sdimclass Node; 59234285Sdimclass Scanner; 60234285Sdimstruct Token; 61234285Sdim 62276479Sdim/// \brief Dump all the tokens in this stream to OS. 63276479Sdim/// \returns true if there was an error, false otherwise. 64234285Sdimbool dumpTokens(StringRef Input, raw_ostream &); 65234285Sdim 66276479Sdim/// \brief Scans all tokens in input without outputting anything. This is used 67234285Sdim/// for benchmarking the tokenizer. 68276479Sdim/// \returns true if there was an error, false otherwise. 69234285Sdimbool scanTokens(StringRef Input); 70234285Sdim 71276479Sdim/// \brief Escape \a Input for a double quoted scalar. 72234285Sdimstd::string escape(StringRef Input); 73234285Sdim 74276479Sdim/// \brief This class represents a YAML stream potentially containing multiple 75234285Sdim/// documents. 76234285Sdimclass Stream { 77234285Sdimpublic: 78276479Sdim /// \brief This keeps a reference to the string referenced by \p Input. 79288943Sdim Stream(StringRef Input, SourceMgr &, bool ShowColors = true); 80249423Sdim 81288943Sdim Stream(MemoryBufferRef InputBuffer, SourceMgr &, bool ShowColors = true); 82234285Sdim ~Stream(); 83234285Sdim 84234285Sdim document_iterator begin(); 85234285Sdim document_iterator end(); 86234285Sdim void skip(); 87234285Sdim bool failed(); 88234285Sdim bool validate() { 89234285Sdim skip(); 90234285Sdim return !failed(); 91234285Sdim } 92234285Sdim 93234285Sdim void printError(Node *N, const Twine &Msg); 94234285Sdim 95234285Sdimprivate: 96276479Sdim std::unique_ptr<Scanner> scanner; 97276479Sdim std::unique_ptr<Document> CurrentDoc; 98234285Sdim 99234285Sdim friend class Document; 100234285Sdim}; 101234285Sdim 102276479Sdim/// \brief Abstract base class for all Nodes. 103234285Sdimclass Node { 104276479Sdim virtual void anchor(); 105276479Sdim 106234285Sdimpublic: 107234285Sdim enum NodeKind { 108234285Sdim NK_Null, 109234285Sdim NK_Scalar, 110288943Sdim NK_BlockScalar, 111234285Sdim NK_KeyValue, 112234285Sdim NK_Mapping, 113234285Sdim NK_Sequence, 114234285Sdim NK_Alias 115234285Sdim }; 116234285Sdim 117276479Sdim Node(unsigned int Type, std::unique_ptr<Document> &, StringRef Anchor, 118261991Sdim StringRef Tag); 119234285Sdim 120276479Sdim /// \brief Get the value of the anchor attached to this node. If it does not 121234285Sdim /// have one, getAnchor().size() will be 0. 122234285Sdim StringRef getAnchor() const { return Anchor; } 123234285Sdim 124261991Sdim /// \brief Get the tag as it was written in the document. This does not 125261991Sdim /// perform tag resolution. 126261991Sdim StringRef getRawTag() const { return Tag; } 127261991Sdim 128261991Sdim /// \brief Get the verbatium tag for a given Node. This performs tag resoluton 129261991Sdim /// and substitution. 130261991Sdim std::string getVerbatimTag() const; 131261991Sdim 132234285Sdim SMRange getSourceRange() const { return SourceRange; } 133234285Sdim void setSourceRange(SMRange SR) { SourceRange = SR; } 134234285Sdim 135234285Sdim // These functions forward to Document and Scanner. 136234285Sdim Token &peekNext(); 137234285Sdim Token getNext(); 138234285Sdim Node *parseBlockNode(); 139234285Sdim BumpPtrAllocator &getAllocator(); 140234285Sdim void setError(const Twine &Message, Token &Location) const; 141234285Sdim bool failed() const; 142234285Sdim 143239462Sdim virtual void skip() {} 144234285Sdim 145234285Sdim unsigned int getType() const { return TypeID; } 146234285Sdim 147276479Sdim void *operator new(size_t Size, BumpPtrAllocator &Alloc, 148276479Sdim size_t Alignment = 16) throw() { 149234285Sdim return Alloc.Allocate(Size, Alignment); 150234285Sdim } 151234285Sdim 152276479Sdim void operator delete(void *Ptr, BumpPtrAllocator &Alloc, size_t Size) throw() { 153276479Sdim Alloc.Deallocate(Ptr, Size); 154234285Sdim } 155234285Sdim 156234285Sdimprotected: 157276479Sdim std::unique_ptr<Document> &Doc; 158234285Sdim SMRange SourceRange; 159234285Sdim 160234285Sdim void operator delete(void *) throw() {} 161234285Sdim 162288943Sdim ~Node() = default; 163234285Sdim 164234285Sdimprivate: 165234285Sdim unsigned int TypeID; 166234285Sdim StringRef Anchor; 167261991Sdim /// \brief The tag as typed in the document. 168261991Sdim StringRef Tag; 169234285Sdim}; 170234285Sdim 171276479Sdim/// \brief A null value. 172234285Sdim/// 173234285Sdim/// Example: 174234285Sdim/// !!null null 175288943Sdimclass NullNode final : public Node { 176276479Sdim void anchor() override; 177276479Sdim 178234285Sdimpublic: 179276479Sdim NullNode(std::unique_ptr<Document> &D) 180261991Sdim : Node(NK_Null, D, StringRef(), StringRef()) {} 181234285Sdim 182276479Sdim static inline bool classof(const Node *N) { return N->getType() == NK_Null; } 183234285Sdim}; 184234285Sdim 185276479Sdim/// \brief A scalar node is an opaque datum that can be presented as a 186234285Sdim/// series of zero or more Unicode scalar values. 187234285Sdim/// 188234285Sdim/// Example: 189234285Sdim/// Adena 190288943Sdimclass ScalarNode final : public Node { 191276479Sdim void anchor() override; 192276479Sdim 193234285Sdimpublic: 194276479Sdim ScalarNode(std::unique_ptr<Document> &D, StringRef Anchor, StringRef Tag, 195261991Sdim StringRef Val) 196261991Sdim : Node(NK_Scalar, D, Anchor, Tag), Value(Val) { 197234285Sdim SMLoc Start = SMLoc::getFromPointer(Val.begin()); 198249423Sdim SMLoc End = SMLoc::getFromPointer(Val.end()); 199234285Sdim SourceRange = SMRange(Start, End); 200234285Sdim } 201234285Sdim 202234285Sdim // Return Value without any escaping or folding or other fun YAML stuff. This 203234285Sdim // is the exact bytes that are contained in the file (after conversion to 204234285Sdim // utf8). 205234285Sdim StringRef getRawValue() const { return Value; } 206234285Sdim 207276479Sdim /// \brief Gets the value of this node as a StringRef. 208234285Sdim /// 209276479Sdim /// \param Storage is used to store the content of the returned StringRef iff 210234285Sdim /// it requires any modification from how it appeared in the source. 211234285Sdim /// This happens with escaped characters and multi-line literals. 212234285Sdim StringRef getValue(SmallVectorImpl<char> &Storage) const; 213234285Sdim 214234285Sdim static inline bool classof(const Node *N) { 215234285Sdim return N->getType() == NK_Scalar; 216234285Sdim } 217234285Sdim 218234285Sdimprivate: 219234285Sdim StringRef Value; 220234285Sdim 221276479Sdim StringRef unescapeDoubleQuoted(StringRef UnquotedValue, 222276479Sdim StringRef::size_type Start, 223276479Sdim SmallVectorImpl<char> &Storage) const; 224234285Sdim}; 225234285Sdim 226288943Sdim/// \brief A block scalar node is an opaque datum that can be presented as a 227288943Sdim/// series of zero or more Unicode scalar values. 228288943Sdim/// 229288943Sdim/// Example: 230288943Sdim/// | 231288943Sdim/// Hello 232288943Sdim/// World 233288943Sdimclass BlockScalarNode final : public Node { 234288943Sdim void anchor() override; 235288943Sdim 236288943Sdimpublic: 237288943Sdim BlockScalarNode(std::unique_ptr<Document> &D, StringRef Anchor, StringRef Tag, 238288943Sdim StringRef Value, StringRef RawVal) 239288943Sdim : Node(NK_BlockScalar, D, Anchor, Tag), Value(Value) { 240288943Sdim SMLoc Start = SMLoc::getFromPointer(RawVal.begin()); 241288943Sdim SMLoc End = SMLoc::getFromPointer(RawVal.end()); 242288943Sdim SourceRange = SMRange(Start, End); 243288943Sdim } 244288943Sdim 245288943Sdim /// \brief Gets the value of this node as a StringRef. 246288943Sdim StringRef getValue() const { return Value; } 247288943Sdim 248288943Sdim static inline bool classof(const Node *N) { 249288943Sdim return N->getType() == NK_BlockScalar; 250288943Sdim } 251288943Sdim 252288943Sdimprivate: 253288943Sdim StringRef Value; 254288943Sdim}; 255288943Sdim 256276479Sdim/// \brief A key and value pair. While not technically a Node under the YAML 257234285Sdim/// representation graph, it is easier to treat them this way. 258234285Sdim/// 259234285Sdim/// TODO: Consider making this not a child of Node. 260234285Sdim/// 261234285Sdim/// Example: 262234285Sdim/// Section: .text 263288943Sdimclass KeyValueNode final : public Node { 264276479Sdim void anchor() override; 265276479Sdim 266234285Sdimpublic: 267276479Sdim KeyValueNode(std::unique_ptr<Document> &D) 268276479Sdim : Node(NK_KeyValue, D, StringRef(), StringRef()), Key(nullptr), 269276479Sdim Value(nullptr) {} 270234285Sdim 271276479Sdim /// \brief Parse and return the key. 272234285Sdim /// 273234285Sdim /// This may be called multiple times. 274234285Sdim /// 275276479Sdim /// \returns The key, or nullptr if failed() == true. 276234285Sdim Node *getKey(); 277234285Sdim 278276479Sdim /// \brief Parse and return the value. 279234285Sdim /// 280234285Sdim /// This may be called multiple times. 281234285Sdim /// 282276479Sdim /// \returns The value, or nullptr if failed() == true. 283234285Sdim Node *getValue(); 284234285Sdim 285276479Sdim void skip() override { 286234285Sdim getKey()->skip(); 287288943Sdim if (Node *Val = getValue()) 288288943Sdim Val->skip(); 289234285Sdim } 290234285Sdim 291234285Sdim static inline bool classof(const Node *N) { 292234285Sdim return N->getType() == NK_KeyValue; 293234285Sdim } 294234285Sdim 295234285Sdimprivate: 296234285Sdim Node *Key; 297234285Sdim Node *Value; 298234285Sdim}; 299234285Sdim 300276479Sdim/// \brief This is an iterator abstraction over YAML collections shared by both 301234285Sdim/// sequences and maps. 302234285Sdim/// 303234285Sdim/// BaseT must have a ValueT* member named CurrentEntry and a member function 304234285Sdim/// increment() which must set CurrentEntry to 0 to create an end iterator. 305234285Sdimtemplate <class BaseT, class ValueT> 306234285Sdimclass basic_collection_iterator 307276479Sdim : public std::iterator<std::forward_iterator_tag, ValueT> { 308234285Sdimpublic: 309276479Sdim basic_collection_iterator() : Base(nullptr) {} 310234285Sdim basic_collection_iterator(BaseT *B) : Base(B) {} 311234285Sdim 312276479Sdim ValueT *operator->() const { 313234285Sdim assert(Base && Base->CurrentEntry && "Attempted to access end iterator!"); 314234285Sdim return Base->CurrentEntry; 315234285Sdim } 316234285Sdim 317276479Sdim ValueT &operator*() const { 318234285Sdim assert(Base && Base->CurrentEntry && 319234285Sdim "Attempted to dereference end iterator!"); 320234285Sdim return *Base->CurrentEntry; 321234285Sdim } 322234285Sdim 323276479Sdim operator ValueT *() const { 324234285Sdim assert(Base && Base->CurrentEntry && "Attempted to access end iterator!"); 325234285Sdim return Base->CurrentEntry; 326234285Sdim } 327234285Sdim 328276479Sdim bool operator!=(const basic_collection_iterator &Other) const { 329276479Sdim if (Base != Other.Base) 330234285Sdim return true; 331276479Sdim return (Base && Other.Base) && 332276479Sdim Base->CurrentEntry != Other.Base->CurrentEntry; 333234285Sdim } 334234285Sdim 335234285Sdim basic_collection_iterator &operator++() { 336234285Sdim assert(Base && "Attempted to advance iterator past end!"); 337234285Sdim Base->increment(); 338234285Sdim // Create an end iterator. 339276479Sdim if (!Base->CurrentEntry) 340276479Sdim Base = nullptr; 341234285Sdim return *this; 342234285Sdim } 343234285Sdim 344234285Sdimprivate: 345234285Sdim BaseT *Base; 346234285Sdim}; 347234285Sdim 348234285Sdim// The following two templates are used for both MappingNode and Sequence Node. 349234285Sdimtemplate <class CollectionType> 350234285Sdimtypename CollectionType::iterator begin(CollectionType &C) { 351234285Sdim assert(C.IsAtBeginning && "You may only iterate over a collection once!"); 352234285Sdim C.IsAtBeginning = false; 353234285Sdim typename CollectionType::iterator ret(&C); 354234285Sdim ++ret; 355234285Sdim return ret; 356234285Sdim} 357234285Sdim 358276479Sdimtemplate <class CollectionType> void skip(CollectionType &C) { 359234285Sdim // TODO: support skipping from the middle of a parsed collection ;/ 360234285Sdim assert((C.IsAtBeginning || C.IsAtEnd) && "Cannot skip mid parse!"); 361234285Sdim if (C.IsAtBeginning) 362276479Sdim for (typename CollectionType::iterator i = begin(C), e = C.end(); i != e; 363276479Sdim ++i) 364234285Sdim i->skip(); 365234285Sdim} 366234285Sdim 367276479Sdim/// \brief Represents a YAML map created from either a block map for a flow map. 368234285Sdim/// 369234285Sdim/// This parses the YAML stream as increment() is called. 370234285Sdim/// 371234285Sdim/// Example: 372234285Sdim/// Name: _main 373234285Sdim/// Scope: Global 374288943Sdimclass MappingNode final : public Node { 375276479Sdim void anchor() override; 376276479Sdim 377234285Sdimpublic: 378234285Sdim enum MappingType { 379234285Sdim MT_Block, 380234285Sdim MT_Flow, 381239462Sdim MT_Inline ///< An inline mapping node is used for "[key: value]". 382234285Sdim }; 383234285Sdim 384276479Sdim MappingNode(std::unique_ptr<Document> &D, StringRef Anchor, StringRef Tag, 385261991Sdim MappingType MT) 386261991Sdim : Node(NK_Mapping, D, Anchor, Tag), Type(MT), IsAtBeginning(true), 387276479Sdim IsAtEnd(false), CurrentEntry(nullptr) {} 388234285Sdim 389234285Sdim friend class basic_collection_iterator<MappingNode, KeyValueNode>; 390234285Sdim typedef basic_collection_iterator<MappingNode, KeyValueNode> iterator; 391234285Sdim template <class T> friend typename T::iterator yaml::begin(T &); 392234285Sdim template <class T> friend void yaml::skip(T &); 393234285Sdim 394276479Sdim iterator begin() { return yaml::begin(*this); } 395234285Sdim 396234285Sdim iterator end() { return iterator(); } 397234285Sdim 398276479Sdim void skip() override { yaml::skip(*this); } 399234285Sdim 400234285Sdim static inline bool classof(const Node *N) { 401234285Sdim return N->getType() == NK_Mapping; 402234285Sdim } 403234285Sdim 404234285Sdimprivate: 405234285Sdim MappingType Type; 406234285Sdim bool IsAtBeginning; 407234285Sdim bool IsAtEnd; 408234285Sdim KeyValueNode *CurrentEntry; 409234285Sdim 410234285Sdim void increment(); 411234285Sdim}; 412234285Sdim 413276479Sdim/// \brief Represents a YAML sequence created from either a block sequence for a 414234285Sdim/// flow sequence. 415234285Sdim/// 416234285Sdim/// This parses the YAML stream as increment() is called. 417234285Sdim/// 418234285Sdim/// Example: 419234285Sdim/// - Hello 420234285Sdim/// - World 421288943Sdimclass SequenceNode final : public Node { 422276479Sdim void anchor() override; 423276479Sdim 424234285Sdimpublic: 425234285Sdim enum SequenceType { 426234285Sdim ST_Block, 427234285Sdim ST_Flow, 428234285Sdim // Use for: 429234285Sdim // 430234285Sdim // key: 431234285Sdim // - val1 432234285Sdim // - val2 433234285Sdim // 434234285Sdim // As a BlockMappingEntry and BlockEnd are not created in this case. 435234285Sdim ST_Indentless 436234285Sdim }; 437234285Sdim 438276479Sdim SequenceNode(std::unique_ptr<Document> &D, StringRef Anchor, StringRef Tag, 439261991Sdim SequenceType ST) 440261991Sdim : Node(NK_Sequence, D, Anchor, Tag), SeqType(ST), IsAtBeginning(true), 441261991Sdim IsAtEnd(false), 442261991Sdim WasPreviousTokenFlowEntry(true), // Start with an imaginary ','. 443276479Sdim CurrentEntry(nullptr) {} 444234285Sdim 445234285Sdim friend class basic_collection_iterator<SequenceNode, Node>; 446234285Sdim typedef basic_collection_iterator<SequenceNode, Node> iterator; 447234285Sdim template <class T> friend typename T::iterator yaml::begin(T &); 448234285Sdim template <class T> friend void yaml::skip(T &); 449234285Sdim 450234285Sdim void increment(); 451234285Sdim 452276479Sdim iterator begin() { return yaml::begin(*this); } 453234285Sdim 454234285Sdim iterator end() { return iterator(); } 455234285Sdim 456276479Sdim void skip() override { yaml::skip(*this); } 457234285Sdim 458234285Sdim static inline bool classof(const Node *N) { 459234285Sdim return N->getType() == NK_Sequence; 460234285Sdim } 461234285Sdim 462234285Sdimprivate: 463234285Sdim SequenceType SeqType; 464234285Sdim bool IsAtBeginning; 465234285Sdim bool IsAtEnd; 466234285Sdim bool WasPreviousTokenFlowEntry; 467234285Sdim Node *CurrentEntry; 468234285Sdim}; 469234285Sdim 470276479Sdim/// \brief Represents an alias to a Node with an anchor. 471234285Sdim/// 472234285Sdim/// Example: 473234285Sdim/// *AnchorName 474288943Sdimclass AliasNode final : public Node { 475276479Sdim void anchor() override; 476276479Sdim 477234285Sdimpublic: 478276479Sdim AliasNode(std::unique_ptr<Document> &D, StringRef Val) 479276479Sdim : Node(NK_Alias, D, StringRef(), StringRef()), Name(Val) {} 480234285Sdim 481234285Sdim StringRef getName() const { return Name; } 482234285Sdim Node *getTarget(); 483234285Sdim 484276479Sdim static inline bool classof(const Node *N) { return N->getType() == NK_Alias; } 485234285Sdim 486234285Sdimprivate: 487234285Sdim StringRef Name; 488234285Sdim}; 489234285Sdim 490276479Sdim/// \brief A YAML Stream is a sequence of Documents. A document contains a root 491234285Sdim/// node. 492234285Sdimclass Document { 493234285Sdimpublic: 494276479Sdim /// \brief Root for parsing a node. Returns a single node. 495234285Sdim Node *parseBlockNode(); 496234285Sdim 497234285Sdim Document(Stream &ParentStream); 498234285Sdim 499276479Sdim /// \brief Finish parsing the current document and return true if there are 500234285Sdim /// more. Return false otherwise. 501234285Sdim bool skip(); 502234285Sdim 503276479Sdim /// \brief Parse and return the root level node. 504234285Sdim Node *getRoot() { 505234285Sdim if (Root) 506234285Sdim return Root; 507234285Sdim return Root = parseBlockNode(); 508234285Sdim } 509234285Sdim 510276479Sdim const std::map<StringRef, StringRef> &getTagMap() const { return TagMap; } 511261991Sdim 512234285Sdimprivate: 513234285Sdim friend class Node; 514234285Sdim friend class document_iterator; 515234285Sdim 516276479Sdim /// \brief Stream to read tokens from. 517234285Sdim Stream &stream; 518234285Sdim 519276479Sdim /// \brief Used to allocate nodes to. All are destroyed without calling their 520234285Sdim /// destructor when the document is destroyed. 521234285Sdim BumpPtrAllocator NodeAllocator; 522234285Sdim 523276479Sdim /// \brief The root node. Used to support skipping a partially parsed 524234285Sdim /// document. 525234285Sdim Node *Root; 526234285Sdim 527261991Sdim /// \brief Maps tag prefixes to their expansion. 528261991Sdim std::map<StringRef, StringRef> TagMap; 529261991Sdim 530234285Sdim Token &peekNext(); 531234285Sdim Token getNext(); 532234285Sdim void setError(const Twine &Message, Token &Location) const; 533234285Sdim bool failed() const; 534234285Sdim 535276479Sdim /// \brief Parse %BLAH directives and return true if any were encountered. 536234285Sdim bool parseDirectives(); 537234285Sdim 538261991Sdim /// \brief Parse %YAML 539261991Sdim void parseYAMLDirective(); 540261991Sdim 541261991Sdim /// \brief Parse %TAG 542261991Sdim void parseTAGDirective(); 543261991Sdim 544276479Sdim /// \brief Consume the next token and error if it is not \a TK. 545234285Sdim bool expectToken(int TK); 546234285Sdim}; 547234285Sdim 548276479Sdim/// \brief Iterator abstraction for Documents over a Stream. 549234285Sdimclass document_iterator { 550234285Sdimpublic: 551276479Sdim document_iterator() : Doc(nullptr) {} 552276479Sdim document_iterator(std::unique_ptr<Document> &D) : Doc(&D) {} 553234285Sdim 554276479Sdim bool operator==(const document_iterator &Other) { 555239462Sdim if (isAtEnd() || Other.isAtEnd()) 556239462Sdim return isAtEnd() && Other.isAtEnd(); 557239462Sdim 558261991Sdim return Doc == Other.Doc; 559234982Sdim } 560276479Sdim bool operator!=(const document_iterator &Other) { return !(*this == Other); } 561234285Sdim 562276479Sdim document_iterator operator++() { 563276479Sdim assert(Doc && "incrementing iterator past the end."); 564239462Sdim if (!(*Doc)->skip()) { 565276479Sdim Doc->reset(nullptr); 566234285Sdim } else { 567239462Sdim Stream &S = (*Doc)->stream; 568239462Sdim Doc->reset(new Document(S)); 569234285Sdim } 570234285Sdim return *this; 571234285Sdim } 572234285Sdim 573276479Sdim Document &operator*() { return *Doc->get(); } 574234285Sdim 575276479Sdim std::unique_ptr<Document> &operator->() { return *Doc; } 576234285Sdim 577234285Sdimprivate: 578276479Sdim bool isAtEnd() const { return !Doc || !*Doc; } 579239462Sdim 580276479Sdim std::unique_ptr<Document> *Doc; 581234285Sdim}; 582234285Sdim 583276479Sdim} // End namespace yaml. 584234285Sdim 585276479Sdim} // End namespace llvm. 586276479Sdim 587234285Sdim#endif 588