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