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