1321369Sdim//===- YAMLParser.h - Simple YAML parser ------------------------*- C++ -*-===// 2234285Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6234285Sdim// 7234285Sdim//===----------------------------------------------------------------------===// 8234285Sdim// 9234285Sdim// This is a YAML 1.2 parser. 10234285Sdim// 11234285Sdim// See http://www.yaml.org/spec/1.2/spec.html for the full standard. 12234285Sdim// 13234285Sdim// This currently does not implement the following: 14234285Sdim// * Multi-line literal folding. 15234285Sdim// * Tag resolution. 16234285Sdim// * UTF-16. 17234285Sdim// * BOMs anywhere other than the first Unicode scalar value in the file. 18234285Sdim// 19234285Sdim// The most important class here is Stream. This represents a YAML stream with 20234285Sdim// 0, 1, or many documents. 21234285Sdim// 22234285Sdim// SourceMgr sm; 23234285Sdim// StringRef input = getInput(); 24234285Sdim// yaml::Stream stream(input, sm); 25234285Sdim// 26234285Sdim// for (yaml::document_iterator di = stream.begin(), de = stream.end(); 27234285Sdim// di != de; ++di) { 28234285Sdim// yaml::Node *n = di->getRoot(); 29234285Sdim// if (n) { 30234285Sdim// // Do something with n... 31234285Sdim// } else 32234285Sdim// break; 33234285Sdim// } 34234285Sdim// 35234285Sdim//===----------------------------------------------------------------------===// 36234285Sdim 37249423Sdim#ifndef LLVM_SUPPORT_YAMLPARSER_H 38249423Sdim#define LLVM_SUPPORT_YAMLPARSER_H 39234285Sdim 40234285Sdim#include "llvm/ADT/StringRef.h" 41234285Sdim#include "llvm/Support/Allocator.h" 42234285Sdim#include "llvm/Support/SMLoc.h" 43321369Sdim#include <cassert> 44321369Sdim#include <cstddef> 45321369Sdim#include <iterator> 46261991Sdim#include <map> 47321369Sdim#include <memory> 48321369Sdim#include <string> 49314564Sdim#include <system_error> 50234285Sdim 51234285Sdimnamespace llvm { 52321369Sdim 53288943Sdimclass MemoryBufferRef; 54234285Sdimclass SourceMgr; 55321369Sdimclass raw_ostream; 56288943Sdimclass Twine; 57234285Sdim 58234285Sdimnamespace yaml { 59234285Sdim 60321369Sdimclass Document; 61234285Sdimclass document_iterator; 62234285Sdimclass Node; 63234285Sdimclass Scanner; 64234285Sdimstruct Token; 65234285Sdim 66341825Sdim/// Dump all the tokens in this stream to OS. 67276479Sdim/// \returns true if there was an error, false otherwise. 68234285Sdimbool dumpTokens(StringRef Input, raw_ostream &); 69234285Sdim 70341825Sdim/// Scans all tokens in input without outputting anything. This is used 71234285Sdim/// for benchmarking the tokenizer. 72276479Sdim/// \returns true if there was an error, false otherwise. 73234285Sdimbool scanTokens(StringRef Input); 74234285Sdim 75341825Sdim/// Escape \a Input for a double quoted scalar; if \p EscapePrintable 76341825Sdim/// is true, all UTF8 sequences will be escaped, if \p EscapePrintable is 77341825Sdim/// false, those UTF8 sequences encoding printable unicode scalars will not be 78341825Sdim/// escaped, but emitted verbatim. 79341825Sdimstd::string escape(StringRef Input, bool EscapePrintable = true); 80234285Sdim 81341825Sdim/// This class represents a YAML stream potentially containing multiple 82234285Sdim/// documents. 83234285Sdimclass Stream { 84234285Sdimpublic: 85341825Sdim /// This keeps a reference to the string referenced by \p Input. 86314564Sdim Stream(StringRef Input, SourceMgr &, bool ShowColors = true, 87314564Sdim std::error_code *EC = nullptr); 88249423Sdim 89314564Sdim Stream(MemoryBufferRef InputBuffer, SourceMgr &, bool ShowColors = true, 90314564Sdim std::error_code *EC = nullptr); 91234285Sdim ~Stream(); 92234285Sdim 93234285Sdim document_iterator begin(); 94234285Sdim document_iterator end(); 95234285Sdim void skip(); 96234285Sdim bool failed(); 97321369Sdim 98234285Sdim bool validate() { 99234285Sdim skip(); 100234285Sdim return !failed(); 101234285Sdim } 102234285Sdim 103234285Sdim void printError(Node *N, const Twine &Msg); 104234285Sdim 105234285Sdimprivate: 106321369Sdim friend class Document; 107321369Sdim 108276479Sdim std::unique_ptr<Scanner> scanner; 109276479Sdim std::unique_ptr<Document> CurrentDoc; 110234285Sdim}; 111234285Sdim 112341825Sdim/// Abstract base class for all Nodes. 113234285Sdimclass Node { 114276479Sdim virtual void anchor(); 115276479Sdim 116234285Sdimpublic: 117234285Sdim enum NodeKind { 118234285Sdim NK_Null, 119234285Sdim NK_Scalar, 120288943Sdim NK_BlockScalar, 121234285Sdim NK_KeyValue, 122234285Sdim NK_Mapping, 123234285Sdim NK_Sequence, 124234285Sdim NK_Alias 125234285Sdim }; 126234285Sdim 127276479Sdim Node(unsigned int Type, std::unique_ptr<Document> &, StringRef Anchor, 128261991Sdim StringRef Tag); 129234285Sdim 130341825Sdim // It's not safe to copy YAML nodes; the document is streamed and the position 131341825Sdim // is part of the state. 132341825Sdim Node(const Node &) = delete; 133341825Sdim void operator=(const Node &) = delete; 134341825Sdim 135321369Sdim void *operator new(size_t Size, BumpPtrAllocator &Alloc, 136321369Sdim size_t Alignment = 16) noexcept { 137321369Sdim return Alloc.Allocate(Size, Alignment); 138321369Sdim } 139321369Sdim 140321369Sdim void operator delete(void *Ptr, BumpPtrAllocator &Alloc, 141321369Sdim size_t Size) noexcept { 142321369Sdim Alloc.Deallocate(Ptr, Size); 143321369Sdim } 144321369Sdim 145321369Sdim void operator delete(void *) noexcept = delete; 146321369Sdim 147341825Sdim /// Get the value of the anchor attached to this node. If it does not 148234285Sdim /// have one, getAnchor().size() will be 0. 149234285Sdim StringRef getAnchor() const { return Anchor; } 150234285Sdim 151341825Sdim /// Get the tag as it was written in the document. This does not 152261991Sdim /// perform tag resolution. 153261991Sdim StringRef getRawTag() const { return Tag; } 154261991Sdim 155341825Sdim /// Get the verbatium tag for a given Node. This performs tag resoluton 156261991Sdim /// and substitution. 157261991Sdim std::string getVerbatimTag() const; 158261991Sdim 159234285Sdim SMRange getSourceRange() const { return SourceRange; } 160234285Sdim void setSourceRange(SMRange SR) { SourceRange = SR; } 161234285Sdim 162234285Sdim // These functions forward to Document and Scanner. 163234285Sdim Token &peekNext(); 164234285Sdim Token getNext(); 165234285Sdim Node *parseBlockNode(); 166234285Sdim BumpPtrAllocator &getAllocator(); 167234285Sdim void setError(const Twine &Message, Token &Location) const; 168234285Sdim bool failed() const; 169234285Sdim 170239462Sdim virtual void skip() {} 171234285Sdim 172234285Sdim unsigned int getType() const { return TypeID; } 173234285Sdim 174234285Sdimprotected: 175276479Sdim std::unique_ptr<Document> &Doc; 176234285Sdim SMRange SourceRange; 177234285Sdim 178288943Sdim ~Node() = default; 179234285Sdim 180234285Sdimprivate: 181234285Sdim unsigned int TypeID; 182234285Sdim StringRef Anchor; 183341825Sdim /// The tag as typed in the document. 184261991Sdim StringRef Tag; 185234285Sdim}; 186234285Sdim 187341825Sdim/// A null value. 188234285Sdim/// 189234285Sdim/// Example: 190234285Sdim/// !!null null 191288943Sdimclass NullNode final : public Node { 192276479Sdim void anchor() override; 193276479Sdim 194234285Sdimpublic: 195276479Sdim NullNode(std::unique_ptr<Document> &D) 196261991Sdim : Node(NK_Null, D, StringRef(), StringRef()) {} 197234285Sdim 198321369Sdim static bool classof(const Node *N) { return N->getType() == NK_Null; } 199234285Sdim}; 200234285Sdim 201341825Sdim/// A scalar node is an opaque datum that can be presented as a 202234285Sdim/// series of zero or more Unicode scalar values. 203234285Sdim/// 204234285Sdim/// Example: 205234285Sdim/// Adena 206288943Sdimclass ScalarNode final : public Node { 207276479Sdim void anchor() override; 208276479Sdim 209234285Sdimpublic: 210276479Sdim ScalarNode(std::unique_ptr<Document> &D, StringRef Anchor, StringRef Tag, 211261991Sdim StringRef Val) 212261991Sdim : Node(NK_Scalar, D, Anchor, Tag), Value(Val) { 213234285Sdim SMLoc Start = SMLoc::getFromPointer(Val.begin()); 214249423Sdim SMLoc End = SMLoc::getFromPointer(Val.end()); 215234285Sdim SourceRange = SMRange(Start, End); 216234285Sdim } 217234285Sdim 218234285Sdim // Return Value without any escaping or folding or other fun YAML stuff. This 219234285Sdim // is the exact bytes that are contained in the file (after conversion to 220234285Sdim // utf8). 221234285Sdim StringRef getRawValue() const { return Value; } 222234285Sdim 223341825Sdim /// Gets the value of this node as a StringRef. 224234285Sdim /// 225276479Sdim /// \param Storage is used to store the content of the returned StringRef iff 226234285Sdim /// it requires any modification from how it appeared in the source. 227234285Sdim /// This happens with escaped characters and multi-line literals. 228234285Sdim StringRef getValue(SmallVectorImpl<char> &Storage) const; 229234285Sdim 230321369Sdim static bool classof(const Node *N) { 231234285Sdim return N->getType() == NK_Scalar; 232234285Sdim } 233234285Sdim 234234285Sdimprivate: 235234285Sdim StringRef Value; 236234285Sdim 237276479Sdim StringRef unescapeDoubleQuoted(StringRef UnquotedValue, 238276479Sdim StringRef::size_type Start, 239276479Sdim SmallVectorImpl<char> &Storage) const; 240234285Sdim}; 241234285Sdim 242341825Sdim/// A block scalar node is an opaque datum that can be presented as a 243288943Sdim/// series of zero or more Unicode scalar values. 244288943Sdim/// 245288943Sdim/// Example: 246288943Sdim/// | 247288943Sdim/// Hello 248288943Sdim/// World 249288943Sdimclass BlockScalarNode final : public Node { 250288943Sdim void anchor() override; 251288943Sdim 252288943Sdimpublic: 253288943Sdim BlockScalarNode(std::unique_ptr<Document> &D, StringRef Anchor, StringRef Tag, 254288943Sdim StringRef Value, StringRef RawVal) 255288943Sdim : Node(NK_BlockScalar, D, Anchor, Tag), Value(Value) { 256288943Sdim SMLoc Start = SMLoc::getFromPointer(RawVal.begin()); 257288943Sdim SMLoc End = SMLoc::getFromPointer(RawVal.end()); 258288943Sdim SourceRange = SMRange(Start, End); 259288943Sdim } 260288943Sdim 261341825Sdim /// Gets the value of this node as a StringRef. 262288943Sdim StringRef getValue() const { return Value; } 263288943Sdim 264321369Sdim static bool classof(const Node *N) { 265288943Sdim return N->getType() == NK_BlockScalar; 266288943Sdim } 267288943Sdim 268288943Sdimprivate: 269288943Sdim StringRef Value; 270288943Sdim}; 271288943Sdim 272341825Sdim/// A key and value pair. While not technically a Node under the YAML 273234285Sdim/// representation graph, it is easier to treat them this way. 274234285Sdim/// 275234285Sdim/// TODO: Consider making this not a child of Node. 276234285Sdim/// 277234285Sdim/// Example: 278234285Sdim/// Section: .text 279288943Sdimclass KeyValueNode final : public Node { 280276479Sdim void anchor() override; 281276479Sdim 282234285Sdimpublic: 283276479Sdim KeyValueNode(std::unique_ptr<Document> &D) 284321369Sdim : Node(NK_KeyValue, D, StringRef(), StringRef()) {} 285234285Sdim 286341825Sdim /// Parse and return the key. 287234285Sdim /// 288234285Sdim /// This may be called multiple times. 289234285Sdim /// 290276479Sdim /// \returns The key, or nullptr if failed() == true. 291234285Sdim Node *getKey(); 292234285Sdim 293341825Sdim /// Parse and return the value. 294234285Sdim /// 295234285Sdim /// This may be called multiple times. 296234285Sdim /// 297276479Sdim /// \returns The value, or nullptr if failed() == true. 298234285Sdim Node *getValue(); 299234285Sdim 300276479Sdim void skip() override { 301327952Sdim if (Node *Key = getKey()) { 302327952Sdim Key->skip(); 303327952Sdim if (Node *Val = getValue()) 304327952Sdim Val->skip(); 305327952Sdim } 306234285Sdim } 307234285Sdim 308321369Sdim static bool classof(const Node *N) { 309234285Sdim return N->getType() == NK_KeyValue; 310234285Sdim } 311234285Sdim 312234285Sdimprivate: 313321369Sdim Node *Key = nullptr; 314321369Sdim Node *Value = nullptr; 315234285Sdim}; 316234285Sdim 317341825Sdim/// This is an iterator abstraction over YAML collections shared by both 318234285Sdim/// sequences and maps. 319234285Sdim/// 320234285Sdim/// BaseT must have a ValueT* member named CurrentEntry and a member function 321234285Sdim/// increment() which must set CurrentEntry to 0 to create an end iterator. 322234285Sdimtemplate <class BaseT, class ValueT> 323234285Sdimclass basic_collection_iterator 324296417Sdim : public std::iterator<std::input_iterator_tag, ValueT> { 325234285Sdimpublic: 326321369Sdim basic_collection_iterator() = default; 327234285Sdim basic_collection_iterator(BaseT *B) : Base(B) {} 328234285Sdim 329276479Sdim ValueT *operator->() const { 330234285Sdim assert(Base && Base->CurrentEntry && "Attempted to access end iterator!"); 331234285Sdim return Base->CurrentEntry; 332234285Sdim } 333234285Sdim 334276479Sdim ValueT &operator*() const { 335234285Sdim assert(Base && Base->CurrentEntry && 336234285Sdim "Attempted to dereference end iterator!"); 337234285Sdim return *Base->CurrentEntry; 338234285Sdim } 339234285Sdim 340276479Sdim operator ValueT *() const { 341234285Sdim assert(Base && Base->CurrentEntry && "Attempted to access end iterator!"); 342234285Sdim return Base->CurrentEntry; 343234285Sdim } 344234285Sdim 345296417Sdim /// Note on EqualityComparable: 346296417Sdim /// 347296417Sdim /// The iterator is not re-entrant, 348296417Sdim /// it is meant to be used for parsing YAML on-demand 349296417Sdim /// Once iteration started - it can point only to one entry at a time 350296417Sdim /// hence Base.CurrentEntry and Other.Base.CurrentEntry are equal 351296417Sdim /// iff Base and Other.Base are equal. 352296417Sdim bool operator==(const basic_collection_iterator &Other) const { 353296417Sdim if (Base && (Base == Other.Base)) { 354296417Sdim assert((Base->CurrentEntry == Other.Base->CurrentEntry) 355296417Sdim && "Equal Bases expected to point to equal Entries"); 356296417Sdim } 357296417Sdim 358296417Sdim return Base == Other.Base; 359296417Sdim } 360296417Sdim 361276479Sdim bool operator!=(const basic_collection_iterator &Other) const { 362296417Sdim return !(Base == Other.Base); 363234285Sdim } 364234285Sdim 365234285Sdim basic_collection_iterator &operator++() { 366234285Sdim assert(Base && "Attempted to advance iterator past end!"); 367234285Sdim Base->increment(); 368234285Sdim // Create an end iterator. 369276479Sdim if (!Base->CurrentEntry) 370276479Sdim Base = nullptr; 371234285Sdim return *this; 372234285Sdim } 373234285Sdim 374234285Sdimprivate: 375321369Sdim BaseT *Base = nullptr; 376234285Sdim}; 377234285Sdim 378234285Sdim// The following two templates are used for both MappingNode and Sequence Node. 379234285Sdimtemplate <class CollectionType> 380234285Sdimtypename CollectionType::iterator begin(CollectionType &C) { 381234285Sdim assert(C.IsAtBeginning && "You may only iterate over a collection once!"); 382234285Sdim C.IsAtBeginning = false; 383234285Sdim typename CollectionType::iterator ret(&C); 384234285Sdim ++ret; 385234285Sdim return ret; 386234285Sdim} 387234285Sdim 388276479Sdimtemplate <class CollectionType> void skip(CollectionType &C) { 389234285Sdim // TODO: support skipping from the middle of a parsed collection ;/ 390234285Sdim assert((C.IsAtBeginning || C.IsAtEnd) && "Cannot skip mid parse!"); 391234285Sdim if (C.IsAtBeginning) 392276479Sdim for (typename CollectionType::iterator i = begin(C), e = C.end(); i != e; 393276479Sdim ++i) 394234285Sdim i->skip(); 395234285Sdim} 396234285Sdim 397341825Sdim/// Represents a YAML map created from either a block map for a flow map. 398234285Sdim/// 399234285Sdim/// This parses the YAML stream as increment() is called. 400234285Sdim/// 401234285Sdim/// Example: 402234285Sdim/// Name: _main 403234285Sdim/// Scope: Global 404288943Sdimclass MappingNode final : public Node { 405276479Sdim void anchor() override; 406276479Sdim 407234285Sdimpublic: 408234285Sdim enum MappingType { 409234285Sdim MT_Block, 410234285Sdim MT_Flow, 411239462Sdim MT_Inline ///< An inline mapping node is used for "[key: value]". 412234285Sdim }; 413234285Sdim 414276479Sdim MappingNode(std::unique_ptr<Document> &D, StringRef Anchor, StringRef Tag, 415261991Sdim MappingType MT) 416321369Sdim : Node(NK_Mapping, D, Anchor, Tag), Type(MT) {} 417234285Sdim 418234285Sdim friend class basic_collection_iterator<MappingNode, KeyValueNode>; 419321369Sdim 420321369Sdim using iterator = basic_collection_iterator<MappingNode, KeyValueNode>; 421321369Sdim 422234285Sdim template <class T> friend typename T::iterator yaml::begin(T &); 423234285Sdim template <class T> friend void yaml::skip(T &); 424234285Sdim 425276479Sdim iterator begin() { return yaml::begin(*this); } 426234285Sdim 427234285Sdim iterator end() { return iterator(); } 428234285Sdim 429276479Sdim void skip() override { yaml::skip(*this); } 430234285Sdim 431321369Sdim static bool classof(const Node *N) { 432234285Sdim return N->getType() == NK_Mapping; 433234285Sdim } 434234285Sdim 435234285Sdimprivate: 436234285Sdim MappingType Type; 437321369Sdim bool IsAtBeginning = true; 438321369Sdim bool IsAtEnd = false; 439321369Sdim KeyValueNode *CurrentEntry = nullptr; 440234285Sdim 441234285Sdim void increment(); 442234285Sdim}; 443234285Sdim 444341825Sdim/// Represents a YAML sequence created from either a block sequence for a 445234285Sdim/// flow sequence. 446234285Sdim/// 447234285Sdim/// This parses the YAML stream as increment() is called. 448234285Sdim/// 449234285Sdim/// Example: 450234285Sdim/// - Hello 451234285Sdim/// - World 452288943Sdimclass SequenceNode final : public Node { 453276479Sdim void anchor() override; 454276479Sdim 455234285Sdimpublic: 456234285Sdim enum SequenceType { 457234285Sdim ST_Block, 458234285Sdim ST_Flow, 459234285Sdim // Use for: 460234285Sdim // 461234285Sdim // key: 462234285Sdim // - val1 463234285Sdim // - val2 464234285Sdim // 465234285Sdim // As a BlockMappingEntry and BlockEnd are not created in this case. 466234285Sdim ST_Indentless 467234285Sdim }; 468234285Sdim 469276479Sdim SequenceNode(std::unique_ptr<Document> &D, StringRef Anchor, StringRef Tag, 470261991Sdim SequenceType ST) 471321369Sdim : Node(NK_Sequence, D, Anchor, Tag), SeqType(ST) {} 472234285Sdim 473234285Sdim friend class basic_collection_iterator<SequenceNode, Node>; 474321369Sdim 475321369Sdim using iterator = basic_collection_iterator<SequenceNode, Node>; 476321369Sdim 477234285Sdim template <class T> friend typename T::iterator yaml::begin(T &); 478234285Sdim template <class T> friend void yaml::skip(T &); 479234285Sdim 480234285Sdim void increment(); 481234285Sdim 482276479Sdim iterator begin() { return yaml::begin(*this); } 483234285Sdim 484234285Sdim iterator end() { return iterator(); } 485234285Sdim 486276479Sdim void skip() override { yaml::skip(*this); } 487234285Sdim 488321369Sdim static bool classof(const Node *N) { 489234285Sdim return N->getType() == NK_Sequence; 490234285Sdim } 491234285Sdim 492234285Sdimprivate: 493234285Sdim SequenceType SeqType; 494321369Sdim bool IsAtBeginning = true; 495321369Sdim bool IsAtEnd = false; 496321369Sdim bool WasPreviousTokenFlowEntry = true; // Start with an imaginary ','. 497321369Sdim Node *CurrentEntry = nullptr; 498234285Sdim}; 499234285Sdim 500341825Sdim/// Represents an alias to a Node with an anchor. 501234285Sdim/// 502234285Sdim/// Example: 503234285Sdim/// *AnchorName 504288943Sdimclass AliasNode final : public Node { 505276479Sdim void anchor() override; 506276479Sdim 507234285Sdimpublic: 508276479Sdim AliasNode(std::unique_ptr<Document> &D, StringRef Val) 509276479Sdim : Node(NK_Alias, D, StringRef(), StringRef()), Name(Val) {} 510234285Sdim 511234285Sdim StringRef getName() const { return Name; } 512234285Sdim Node *getTarget(); 513234285Sdim 514321369Sdim static bool classof(const Node *N) { return N->getType() == NK_Alias; } 515234285Sdim 516234285Sdimprivate: 517234285Sdim StringRef Name; 518234285Sdim}; 519234285Sdim 520341825Sdim/// A YAML Stream is a sequence of Documents. A document contains a root 521234285Sdim/// node. 522234285Sdimclass Document { 523234285Sdimpublic: 524321369Sdim Document(Stream &ParentStream); 525321369Sdim 526341825Sdim /// Root for parsing a node. Returns a single node. 527234285Sdim Node *parseBlockNode(); 528234285Sdim 529341825Sdim /// Finish parsing the current document and return true if there are 530234285Sdim /// more. Return false otherwise. 531234285Sdim bool skip(); 532234285Sdim 533341825Sdim /// Parse and return the root level node. 534234285Sdim Node *getRoot() { 535234285Sdim if (Root) 536234285Sdim return Root; 537234285Sdim return Root = parseBlockNode(); 538234285Sdim } 539234285Sdim 540276479Sdim const std::map<StringRef, StringRef> &getTagMap() const { return TagMap; } 541261991Sdim 542234285Sdimprivate: 543234285Sdim friend class Node; 544234285Sdim friend class document_iterator; 545234285Sdim 546341825Sdim /// Stream to read tokens from. 547234285Sdim Stream &stream; 548234285Sdim 549341825Sdim /// Used to allocate nodes to. All are destroyed without calling their 550234285Sdim /// destructor when the document is destroyed. 551234285Sdim BumpPtrAllocator NodeAllocator; 552234285Sdim 553341825Sdim /// The root node. Used to support skipping a partially parsed 554234285Sdim /// document. 555234285Sdim Node *Root; 556234285Sdim 557341825Sdim /// Maps tag prefixes to their expansion. 558261991Sdim std::map<StringRef, StringRef> TagMap; 559261991Sdim 560234285Sdim Token &peekNext(); 561234285Sdim Token getNext(); 562234285Sdim void setError(const Twine &Message, Token &Location) const; 563234285Sdim bool failed() const; 564234285Sdim 565341825Sdim /// Parse %BLAH directives and return true if any were encountered. 566234285Sdim bool parseDirectives(); 567234285Sdim 568341825Sdim /// Parse %YAML 569261991Sdim void parseYAMLDirective(); 570261991Sdim 571341825Sdim /// Parse %TAG 572261991Sdim void parseTAGDirective(); 573261991Sdim 574341825Sdim /// Consume the next token and error if it is not \a TK. 575234285Sdim bool expectToken(int TK); 576234285Sdim}; 577234285Sdim 578341825Sdim/// Iterator abstraction for Documents over a Stream. 579234285Sdimclass document_iterator { 580234285Sdimpublic: 581321369Sdim document_iterator() = default; 582276479Sdim document_iterator(std::unique_ptr<Document> &D) : Doc(&D) {} 583234285Sdim 584327952Sdim bool operator==(const document_iterator &Other) const { 585239462Sdim if (isAtEnd() || Other.isAtEnd()) 586239462Sdim return isAtEnd() && Other.isAtEnd(); 587239462Sdim 588261991Sdim return Doc == Other.Doc; 589234982Sdim } 590327952Sdim bool operator!=(const document_iterator &Other) const { 591327952Sdim return !(*this == Other); 592327952Sdim } 593234285Sdim 594276479Sdim document_iterator operator++() { 595276479Sdim assert(Doc && "incrementing iterator past the end."); 596239462Sdim if (!(*Doc)->skip()) { 597276479Sdim Doc->reset(nullptr); 598234285Sdim } else { 599239462Sdim Stream &S = (*Doc)->stream; 600239462Sdim Doc->reset(new Document(S)); 601234285Sdim } 602234285Sdim return *this; 603234285Sdim } 604234285Sdim 605276479Sdim Document &operator*() { return *Doc->get(); } 606234285Sdim 607276479Sdim std::unique_ptr<Document> &operator->() { return *Doc; } 608234285Sdim 609234285Sdimprivate: 610276479Sdim bool isAtEnd() const { return !Doc || !*Doc; } 611239462Sdim 612321369Sdim std::unique_ptr<Document> *Doc = nullptr; 613234285Sdim}; 614234285Sdim 615321369Sdim} // end namespace yaml 616234285Sdim 617321369Sdim} // end namespace llvm 618276479Sdim 619321369Sdim#endif // LLVM_SUPPORT_YAMLPARSER_H 620