xref: /aosp_15_r20/external/llvm/lib/Support/YAMLParser.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===--- YAMLParser.cpp - Simple YAML parser ------------------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker //  This file implements a YAML parser.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker 
14*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/YAMLParser.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallString.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallVector.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringExtras.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Twine.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/ilist.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/ilist_node.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MemoryBuffer.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/SourceMgr.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
25*9880d681SAndroid Build Coastguard Worker 
26*9880d681SAndroid Build Coastguard Worker using namespace llvm;
27*9880d681SAndroid Build Coastguard Worker using namespace yaml;
28*9880d681SAndroid Build Coastguard Worker 
29*9880d681SAndroid Build Coastguard Worker enum UnicodeEncodingForm {
30*9880d681SAndroid Build Coastguard Worker   UEF_UTF32_LE, ///< UTF-32 Little Endian
31*9880d681SAndroid Build Coastguard Worker   UEF_UTF32_BE, ///< UTF-32 Big Endian
32*9880d681SAndroid Build Coastguard Worker   UEF_UTF16_LE, ///< UTF-16 Little Endian
33*9880d681SAndroid Build Coastguard Worker   UEF_UTF16_BE, ///< UTF-16 Big Endian
34*9880d681SAndroid Build Coastguard Worker   UEF_UTF8,     ///< UTF-8 or ascii.
35*9880d681SAndroid Build Coastguard Worker   UEF_Unknown   ///< Not a valid Unicode encoding.
36*9880d681SAndroid Build Coastguard Worker };
37*9880d681SAndroid Build Coastguard Worker 
38*9880d681SAndroid Build Coastguard Worker /// EncodingInfo - Holds the encoding type and length of the byte order mark if
39*9880d681SAndroid Build Coastguard Worker ///                it exists. Length is in {0, 2, 3, 4}.
40*9880d681SAndroid Build Coastguard Worker typedef std::pair<UnicodeEncodingForm, unsigned> EncodingInfo;
41*9880d681SAndroid Build Coastguard Worker 
42*9880d681SAndroid Build Coastguard Worker /// getUnicodeEncoding - Reads up to the first 4 bytes to determine the Unicode
43*9880d681SAndroid Build Coastguard Worker ///                      encoding form of \a Input.
44*9880d681SAndroid Build Coastguard Worker ///
45*9880d681SAndroid Build Coastguard Worker /// @param Input A string of length 0 or more.
46*9880d681SAndroid Build Coastguard Worker /// @returns An EncodingInfo indicating the Unicode encoding form of the input
47*9880d681SAndroid Build Coastguard Worker ///          and how long the byte order mark is if one exists.
getUnicodeEncoding(StringRef Input)48*9880d681SAndroid Build Coastguard Worker static EncodingInfo getUnicodeEncoding(StringRef Input) {
49*9880d681SAndroid Build Coastguard Worker   if (Input.size() == 0)
50*9880d681SAndroid Build Coastguard Worker     return std::make_pair(UEF_Unknown, 0);
51*9880d681SAndroid Build Coastguard Worker 
52*9880d681SAndroid Build Coastguard Worker   switch (uint8_t(Input[0])) {
53*9880d681SAndroid Build Coastguard Worker   case 0x00:
54*9880d681SAndroid Build Coastguard Worker     if (Input.size() >= 4) {
55*9880d681SAndroid Build Coastguard Worker       if (  Input[1] == 0
56*9880d681SAndroid Build Coastguard Worker          && uint8_t(Input[2]) == 0xFE
57*9880d681SAndroid Build Coastguard Worker          && uint8_t(Input[3]) == 0xFF)
58*9880d681SAndroid Build Coastguard Worker         return std::make_pair(UEF_UTF32_BE, 4);
59*9880d681SAndroid Build Coastguard Worker       if (Input[1] == 0 && Input[2] == 0 && Input[3] != 0)
60*9880d681SAndroid Build Coastguard Worker         return std::make_pair(UEF_UTF32_BE, 0);
61*9880d681SAndroid Build Coastguard Worker     }
62*9880d681SAndroid Build Coastguard Worker 
63*9880d681SAndroid Build Coastguard Worker     if (Input.size() >= 2 && Input[1] != 0)
64*9880d681SAndroid Build Coastguard Worker       return std::make_pair(UEF_UTF16_BE, 0);
65*9880d681SAndroid Build Coastguard Worker     return std::make_pair(UEF_Unknown, 0);
66*9880d681SAndroid Build Coastguard Worker   case 0xFF:
67*9880d681SAndroid Build Coastguard Worker     if (  Input.size() >= 4
68*9880d681SAndroid Build Coastguard Worker        && uint8_t(Input[1]) == 0xFE
69*9880d681SAndroid Build Coastguard Worker        && Input[2] == 0
70*9880d681SAndroid Build Coastguard Worker        && Input[3] == 0)
71*9880d681SAndroid Build Coastguard Worker       return std::make_pair(UEF_UTF32_LE, 4);
72*9880d681SAndroid Build Coastguard Worker 
73*9880d681SAndroid Build Coastguard Worker     if (Input.size() >= 2 && uint8_t(Input[1]) == 0xFE)
74*9880d681SAndroid Build Coastguard Worker       return std::make_pair(UEF_UTF16_LE, 2);
75*9880d681SAndroid Build Coastguard Worker     return std::make_pair(UEF_Unknown, 0);
76*9880d681SAndroid Build Coastguard Worker   case 0xFE:
77*9880d681SAndroid Build Coastguard Worker     if (Input.size() >= 2 && uint8_t(Input[1]) == 0xFF)
78*9880d681SAndroid Build Coastguard Worker       return std::make_pair(UEF_UTF16_BE, 2);
79*9880d681SAndroid Build Coastguard Worker     return std::make_pair(UEF_Unknown, 0);
80*9880d681SAndroid Build Coastguard Worker   case 0xEF:
81*9880d681SAndroid Build Coastguard Worker     if (  Input.size() >= 3
82*9880d681SAndroid Build Coastguard Worker        && uint8_t(Input[1]) == 0xBB
83*9880d681SAndroid Build Coastguard Worker        && uint8_t(Input[2]) == 0xBF)
84*9880d681SAndroid Build Coastguard Worker       return std::make_pair(UEF_UTF8, 3);
85*9880d681SAndroid Build Coastguard Worker     return std::make_pair(UEF_Unknown, 0);
86*9880d681SAndroid Build Coastguard Worker   }
87*9880d681SAndroid Build Coastguard Worker 
88*9880d681SAndroid Build Coastguard Worker   // It could still be utf-32 or utf-16.
89*9880d681SAndroid Build Coastguard Worker   if (Input.size() >= 4 && Input[1] == 0 && Input[2] == 0 && Input[3] == 0)
90*9880d681SAndroid Build Coastguard Worker     return std::make_pair(UEF_UTF32_LE, 0);
91*9880d681SAndroid Build Coastguard Worker 
92*9880d681SAndroid Build Coastguard Worker   if (Input.size() >= 2 && Input[1] == 0)
93*9880d681SAndroid Build Coastguard Worker     return std::make_pair(UEF_UTF16_LE, 0);
94*9880d681SAndroid Build Coastguard Worker 
95*9880d681SAndroid Build Coastguard Worker   return std::make_pair(UEF_UTF8, 0);
96*9880d681SAndroid Build Coastguard Worker }
97*9880d681SAndroid Build Coastguard Worker 
98*9880d681SAndroid Build Coastguard Worker namespace llvm {
99*9880d681SAndroid Build Coastguard Worker namespace yaml {
100*9880d681SAndroid Build Coastguard Worker /// Pin the vtables to this file.
anchor()101*9880d681SAndroid Build Coastguard Worker void Node::anchor() {}
anchor()102*9880d681SAndroid Build Coastguard Worker void NullNode::anchor() {}
anchor()103*9880d681SAndroid Build Coastguard Worker void ScalarNode::anchor() {}
anchor()104*9880d681SAndroid Build Coastguard Worker void BlockScalarNode::anchor() {}
anchor()105*9880d681SAndroid Build Coastguard Worker void KeyValueNode::anchor() {}
anchor()106*9880d681SAndroid Build Coastguard Worker void MappingNode::anchor() {}
anchor()107*9880d681SAndroid Build Coastguard Worker void SequenceNode::anchor() {}
anchor()108*9880d681SAndroid Build Coastguard Worker void AliasNode::anchor() {}
109*9880d681SAndroid Build Coastguard Worker 
110*9880d681SAndroid Build Coastguard Worker /// Token - A single YAML token.
111*9880d681SAndroid Build Coastguard Worker struct Token : ilist_node<Token> {
112*9880d681SAndroid Build Coastguard Worker   enum TokenKind {
113*9880d681SAndroid Build Coastguard Worker     TK_Error, // Uninitialized token.
114*9880d681SAndroid Build Coastguard Worker     TK_StreamStart,
115*9880d681SAndroid Build Coastguard Worker     TK_StreamEnd,
116*9880d681SAndroid Build Coastguard Worker     TK_VersionDirective,
117*9880d681SAndroid Build Coastguard Worker     TK_TagDirective,
118*9880d681SAndroid Build Coastguard Worker     TK_DocumentStart,
119*9880d681SAndroid Build Coastguard Worker     TK_DocumentEnd,
120*9880d681SAndroid Build Coastguard Worker     TK_BlockEntry,
121*9880d681SAndroid Build Coastguard Worker     TK_BlockEnd,
122*9880d681SAndroid Build Coastguard Worker     TK_BlockSequenceStart,
123*9880d681SAndroid Build Coastguard Worker     TK_BlockMappingStart,
124*9880d681SAndroid Build Coastguard Worker     TK_FlowEntry,
125*9880d681SAndroid Build Coastguard Worker     TK_FlowSequenceStart,
126*9880d681SAndroid Build Coastguard Worker     TK_FlowSequenceEnd,
127*9880d681SAndroid Build Coastguard Worker     TK_FlowMappingStart,
128*9880d681SAndroid Build Coastguard Worker     TK_FlowMappingEnd,
129*9880d681SAndroid Build Coastguard Worker     TK_Key,
130*9880d681SAndroid Build Coastguard Worker     TK_Value,
131*9880d681SAndroid Build Coastguard Worker     TK_Scalar,
132*9880d681SAndroid Build Coastguard Worker     TK_BlockScalar,
133*9880d681SAndroid Build Coastguard Worker     TK_Alias,
134*9880d681SAndroid Build Coastguard Worker     TK_Anchor,
135*9880d681SAndroid Build Coastguard Worker     TK_Tag
136*9880d681SAndroid Build Coastguard Worker   } Kind;
137*9880d681SAndroid Build Coastguard Worker 
138*9880d681SAndroid Build Coastguard Worker   /// A string of length 0 or more whose begin() points to the logical location
139*9880d681SAndroid Build Coastguard Worker   /// of the token in the input.
140*9880d681SAndroid Build Coastguard Worker   StringRef Range;
141*9880d681SAndroid Build Coastguard Worker 
142*9880d681SAndroid Build Coastguard Worker   /// The value of a block scalar node.
143*9880d681SAndroid Build Coastguard Worker   std::string Value;
144*9880d681SAndroid Build Coastguard Worker 
Tokenllvm::yaml::Token145*9880d681SAndroid Build Coastguard Worker   Token() : Kind(TK_Error) {}
146*9880d681SAndroid Build Coastguard Worker };
147*9880d681SAndroid Build Coastguard Worker }
148*9880d681SAndroid Build Coastguard Worker }
149*9880d681SAndroid Build Coastguard Worker 
150*9880d681SAndroid Build Coastguard Worker namespace llvm {
151*9880d681SAndroid Build Coastguard Worker template<>
152*9880d681SAndroid Build Coastguard Worker struct ilist_sentinel_traits<Token> {
createSentinelllvm::ilist_sentinel_traits153*9880d681SAndroid Build Coastguard Worker   Token *createSentinel() const {
154*9880d681SAndroid Build Coastguard Worker     return &Sentinel;
155*9880d681SAndroid Build Coastguard Worker   }
destroySentinelllvm::ilist_sentinel_traits156*9880d681SAndroid Build Coastguard Worker   static void destroySentinel(Token*) {}
157*9880d681SAndroid Build Coastguard Worker 
provideInitialHeadllvm::ilist_sentinel_traits158*9880d681SAndroid Build Coastguard Worker   Token *provideInitialHead() const { return createSentinel(); }
ensureHeadllvm::ilist_sentinel_traits159*9880d681SAndroid Build Coastguard Worker   Token *ensureHead(Token*) const { return createSentinel(); }
noteHeadllvm::ilist_sentinel_traits160*9880d681SAndroid Build Coastguard Worker   static void noteHead(Token*, Token*) {}
161*9880d681SAndroid Build Coastguard Worker 
162*9880d681SAndroid Build Coastguard Worker private:
163*9880d681SAndroid Build Coastguard Worker   mutable Token Sentinel;
164*9880d681SAndroid Build Coastguard Worker };
165*9880d681SAndroid Build Coastguard Worker 
166*9880d681SAndroid Build Coastguard Worker template<>
167*9880d681SAndroid Build Coastguard Worker struct ilist_node_traits<Token> {
createNodellvm::ilist_node_traits168*9880d681SAndroid Build Coastguard Worker   Token *createNode(const Token &V) {
169*9880d681SAndroid Build Coastguard Worker     return new (Alloc.Allocate<Token>()) Token(V);
170*9880d681SAndroid Build Coastguard Worker   }
deleteNodellvm::ilist_node_traits171*9880d681SAndroid Build Coastguard Worker   static void deleteNode(Token *V) { V->~Token(); }
172*9880d681SAndroid Build Coastguard Worker 
addNodeToListllvm::ilist_node_traits173*9880d681SAndroid Build Coastguard Worker   void addNodeToList(Token *) {}
removeNodeFromListllvm::ilist_node_traits174*9880d681SAndroid Build Coastguard Worker   void removeNodeFromList(Token *) {}
transferNodesFromListllvm::ilist_node_traits175*9880d681SAndroid Build Coastguard Worker   void transferNodesFromList(ilist_node_traits &    /*SrcTraits*/,
176*9880d681SAndroid Build Coastguard Worker                              ilist_iterator<Token> /*first*/,
177*9880d681SAndroid Build Coastguard Worker                              ilist_iterator<Token> /*last*/) {}
178*9880d681SAndroid Build Coastguard Worker 
179*9880d681SAndroid Build Coastguard Worker   BumpPtrAllocator Alloc;
180*9880d681SAndroid Build Coastguard Worker };
181*9880d681SAndroid Build Coastguard Worker }
182*9880d681SAndroid Build Coastguard Worker 
183*9880d681SAndroid Build Coastguard Worker typedef ilist<Token> TokenQueueT;
184*9880d681SAndroid Build Coastguard Worker 
185*9880d681SAndroid Build Coastguard Worker namespace {
186*9880d681SAndroid Build Coastguard Worker /// @brief This struct is used to track simple keys.
187*9880d681SAndroid Build Coastguard Worker ///
188*9880d681SAndroid Build Coastguard Worker /// Simple keys are handled by creating an entry in SimpleKeys for each Token
189*9880d681SAndroid Build Coastguard Worker /// which could legally be the start of a simple key. When peekNext is called,
190*9880d681SAndroid Build Coastguard Worker /// if the Token To be returned is referenced by a SimpleKey, we continue
191*9880d681SAndroid Build Coastguard Worker /// tokenizing until that potential simple key has either been found to not be
192*9880d681SAndroid Build Coastguard Worker /// a simple key (we moved on to the next line or went further than 1024 chars).
193*9880d681SAndroid Build Coastguard Worker /// Or when we run into a Value, and then insert a Key token (and possibly
194*9880d681SAndroid Build Coastguard Worker /// others) before the SimpleKey's Tok.
195*9880d681SAndroid Build Coastguard Worker struct SimpleKey {
196*9880d681SAndroid Build Coastguard Worker   TokenQueueT::iterator Tok;
197*9880d681SAndroid Build Coastguard Worker   unsigned Column;
198*9880d681SAndroid Build Coastguard Worker   unsigned Line;
199*9880d681SAndroid Build Coastguard Worker   unsigned FlowLevel;
200*9880d681SAndroid Build Coastguard Worker   bool IsRequired;
201*9880d681SAndroid Build Coastguard Worker 
operator ==__anon8f0111340111::SimpleKey202*9880d681SAndroid Build Coastguard Worker   bool operator ==(const SimpleKey &Other) {
203*9880d681SAndroid Build Coastguard Worker     return Tok == Other.Tok;
204*9880d681SAndroid Build Coastguard Worker   }
205*9880d681SAndroid Build Coastguard Worker };
206*9880d681SAndroid Build Coastguard Worker }
207*9880d681SAndroid Build Coastguard Worker 
208*9880d681SAndroid Build Coastguard Worker /// @brief The Unicode scalar value of a UTF-8 minimal well-formed code unit
209*9880d681SAndroid Build Coastguard Worker ///        subsequence and the subsequence's length in code units (uint8_t).
210*9880d681SAndroid Build Coastguard Worker ///        A length of 0 represents an error.
211*9880d681SAndroid Build Coastguard Worker typedef std::pair<uint32_t, unsigned> UTF8Decoded;
212*9880d681SAndroid Build Coastguard Worker 
decodeUTF8(StringRef Range)213*9880d681SAndroid Build Coastguard Worker static UTF8Decoded decodeUTF8(StringRef Range) {
214*9880d681SAndroid Build Coastguard Worker   StringRef::iterator Position= Range.begin();
215*9880d681SAndroid Build Coastguard Worker   StringRef::iterator End = Range.end();
216*9880d681SAndroid Build Coastguard Worker   // 1 byte: [0x00, 0x7f]
217*9880d681SAndroid Build Coastguard Worker   // Bit pattern: 0xxxxxxx
218*9880d681SAndroid Build Coastguard Worker   if ((*Position & 0x80) == 0) {
219*9880d681SAndroid Build Coastguard Worker      return std::make_pair(*Position, 1);
220*9880d681SAndroid Build Coastguard Worker   }
221*9880d681SAndroid Build Coastguard Worker   // 2 bytes: [0x80, 0x7ff]
222*9880d681SAndroid Build Coastguard Worker   // Bit pattern: 110xxxxx 10xxxxxx
223*9880d681SAndroid Build Coastguard Worker   if (Position + 1 != End &&
224*9880d681SAndroid Build Coastguard Worker       ((*Position & 0xE0) == 0xC0) &&
225*9880d681SAndroid Build Coastguard Worker       ((*(Position + 1) & 0xC0) == 0x80)) {
226*9880d681SAndroid Build Coastguard Worker     uint32_t codepoint = ((*Position & 0x1F) << 6) |
227*9880d681SAndroid Build Coastguard Worker                           (*(Position + 1) & 0x3F);
228*9880d681SAndroid Build Coastguard Worker     if (codepoint >= 0x80)
229*9880d681SAndroid Build Coastguard Worker       return std::make_pair(codepoint, 2);
230*9880d681SAndroid Build Coastguard Worker   }
231*9880d681SAndroid Build Coastguard Worker   // 3 bytes: [0x8000, 0xffff]
232*9880d681SAndroid Build Coastguard Worker   // Bit pattern: 1110xxxx 10xxxxxx 10xxxxxx
233*9880d681SAndroid Build Coastguard Worker   if (Position + 2 != End &&
234*9880d681SAndroid Build Coastguard Worker       ((*Position & 0xF0) == 0xE0) &&
235*9880d681SAndroid Build Coastguard Worker       ((*(Position + 1) & 0xC0) == 0x80) &&
236*9880d681SAndroid Build Coastguard Worker       ((*(Position + 2) & 0xC0) == 0x80)) {
237*9880d681SAndroid Build Coastguard Worker     uint32_t codepoint = ((*Position & 0x0F) << 12) |
238*9880d681SAndroid Build Coastguard Worker                          ((*(Position + 1) & 0x3F) << 6) |
239*9880d681SAndroid Build Coastguard Worker                           (*(Position + 2) & 0x3F);
240*9880d681SAndroid Build Coastguard Worker     // Codepoints between 0xD800 and 0xDFFF are invalid, as
241*9880d681SAndroid Build Coastguard Worker     // they are high / low surrogate halves used by UTF-16.
242*9880d681SAndroid Build Coastguard Worker     if (codepoint >= 0x800 &&
243*9880d681SAndroid Build Coastguard Worker         (codepoint < 0xD800 || codepoint > 0xDFFF))
244*9880d681SAndroid Build Coastguard Worker       return std::make_pair(codepoint, 3);
245*9880d681SAndroid Build Coastguard Worker   }
246*9880d681SAndroid Build Coastguard Worker   // 4 bytes: [0x10000, 0x10FFFF]
247*9880d681SAndroid Build Coastguard Worker   // Bit pattern: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
248*9880d681SAndroid Build Coastguard Worker   if (Position + 3 != End &&
249*9880d681SAndroid Build Coastguard Worker       ((*Position & 0xF8) == 0xF0) &&
250*9880d681SAndroid Build Coastguard Worker       ((*(Position + 1) & 0xC0) == 0x80) &&
251*9880d681SAndroid Build Coastguard Worker       ((*(Position + 2) & 0xC0) == 0x80) &&
252*9880d681SAndroid Build Coastguard Worker       ((*(Position + 3) & 0xC0) == 0x80)) {
253*9880d681SAndroid Build Coastguard Worker     uint32_t codepoint = ((*Position & 0x07) << 18) |
254*9880d681SAndroid Build Coastguard Worker                          ((*(Position + 1) & 0x3F) << 12) |
255*9880d681SAndroid Build Coastguard Worker                          ((*(Position + 2) & 0x3F) << 6) |
256*9880d681SAndroid Build Coastguard Worker                           (*(Position + 3) & 0x3F);
257*9880d681SAndroid Build Coastguard Worker     if (codepoint >= 0x10000 && codepoint <= 0x10FFFF)
258*9880d681SAndroid Build Coastguard Worker       return std::make_pair(codepoint, 4);
259*9880d681SAndroid Build Coastguard Worker   }
260*9880d681SAndroid Build Coastguard Worker   return std::make_pair(0, 0);
261*9880d681SAndroid Build Coastguard Worker }
262*9880d681SAndroid Build Coastguard Worker 
263*9880d681SAndroid Build Coastguard Worker namespace llvm {
264*9880d681SAndroid Build Coastguard Worker namespace yaml {
265*9880d681SAndroid Build Coastguard Worker /// @brief Scans YAML tokens from a MemoryBuffer.
266*9880d681SAndroid Build Coastguard Worker class Scanner {
267*9880d681SAndroid Build Coastguard Worker public:
268*9880d681SAndroid Build Coastguard Worker   Scanner(StringRef Input, SourceMgr &SM, bool ShowColors = true);
269*9880d681SAndroid Build Coastguard Worker   Scanner(MemoryBufferRef Buffer, SourceMgr &SM_, bool ShowColors = true);
270*9880d681SAndroid Build Coastguard Worker 
271*9880d681SAndroid Build Coastguard Worker   /// @brief Parse the next token and return it without popping it.
272*9880d681SAndroid Build Coastguard Worker   Token &peekNext();
273*9880d681SAndroid Build Coastguard Worker 
274*9880d681SAndroid Build Coastguard Worker   /// @brief Parse the next token and pop it from the queue.
275*9880d681SAndroid Build Coastguard Worker   Token getNext();
276*9880d681SAndroid Build Coastguard Worker 
printError(SMLoc Loc,SourceMgr::DiagKind Kind,const Twine & Message,ArrayRef<SMRange> Ranges=None)277*9880d681SAndroid Build Coastguard Worker   void printError(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Message,
278*9880d681SAndroid Build Coastguard Worker                   ArrayRef<SMRange> Ranges = None) {
279*9880d681SAndroid Build Coastguard Worker     SM.PrintMessage(Loc, Kind, Message, Ranges, /* FixIts= */ None, ShowColors);
280*9880d681SAndroid Build Coastguard Worker   }
281*9880d681SAndroid Build Coastguard Worker 
setError(const Twine & Message,StringRef::iterator Position)282*9880d681SAndroid Build Coastguard Worker   void setError(const Twine &Message, StringRef::iterator Position) {
283*9880d681SAndroid Build Coastguard Worker     if (Current >= End)
284*9880d681SAndroid Build Coastguard Worker       Current = End - 1;
285*9880d681SAndroid Build Coastguard Worker 
286*9880d681SAndroid Build Coastguard Worker     // Don't print out more errors after the first one we encounter. The rest
287*9880d681SAndroid Build Coastguard Worker     // are just the result of the first, and have no meaning.
288*9880d681SAndroid Build Coastguard Worker     if (!Failed)
289*9880d681SAndroid Build Coastguard Worker       printError(SMLoc::getFromPointer(Current), SourceMgr::DK_Error, Message);
290*9880d681SAndroid Build Coastguard Worker     Failed = true;
291*9880d681SAndroid Build Coastguard Worker   }
292*9880d681SAndroid Build Coastguard Worker 
setError(const Twine & Message)293*9880d681SAndroid Build Coastguard Worker   void setError(const Twine &Message) {
294*9880d681SAndroid Build Coastguard Worker     setError(Message, Current);
295*9880d681SAndroid Build Coastguard Worker   }
296*9880d681SAndroid Build Coastguard Worker 
297*9880d681SAndroid Build Coastguard Worker   /// @brief Returns true if an error occurred while parsing.
failed()298*9880d681SAndroid Build Coastguard Worker   bool failed() {
299*9880d681SAndroid Build Coastguard Worker     return Failed;
300*9880d681SAndroid Build Coastguard Worker   }
301*9880d681SAndroid Build Coastguard Worker 
302*9880d681SAndroid Build Coastguard Worker private:
303*9880d681SAndroid Build Coastguard Worker   void init(MemoryBufferRef Buffer);
304*9880d681SAndroid Build Coastguard Worker 
currentInput()305*9880d681SAndroid Build Coastguard Worker   StringRef currentInput() {
306*9880d681SAndroid Build Coastguard Worker     return StringRef(Current, End - Current);
307*9880d681SAndroid Build Coastguard Worker   }
308*9880d681SAndroid Build Coastguard Worker 
309*9880d681SAndroid Build Coastguard Worker   /// @brief Decode a UTF-8 minimal well-formed code unit subsequence starting
310*9880d681SAndroid Build Coastguard Worker   ///        at \a Position.
311*9880d681SAndroid Build Coastguard Worker   ///
312*9880d681SAndroid Build Coastguard Worker   /// If the UTF-8 code units starting at Position do not form a well-formed
313*9880d681SAndroid Build Coastguard Worker   /// code unit subsequence, then the Unicode scalar value is 0, and the length
314*9880d681SAndroid Build Coastguard Worker   /// is 0.
decodeUTF8(StringRef::iterator Position)315*9880d681SAndroid Build Coastguard Worker   UTF8Decoded decodeUTF8(StringRef::iterator Position) {
316*9880d681SAndroid Build Coastguard Worker     return ::decodeUTF8(StringRef(Position, End - Position));
317*9880d681SAndroid Build Coastguard Worker   }
318*9880d681SAndroid Build Coastguard Worker 
319*9880d681SAndroid Build Coastguard Worker   // The following functions are based on the gramar rules in the YAML spec. The
320*9880d681SAndroid Build Coastguard Worker   // style of the function names it meant to closely match how they are written
321*9880d681SAndroid Build Coastguard Worker   // in the spec. The number within the [] is the number of the grammar rule in
322*9880d681SAndroid Build Coastguard Worker   // the spec.
323*9880d681SAndroid Build Coastguard Worker   //
324*9880d681SAndroid Build Coastguard Worker   // See 4.2 [Production Naming Conventions] for the meaning of the prefixes.
325*9880d681SAndroid Build Coastguard Worker   //
326*9880d681SAndroid Build Coastguard Worker   // c-
327*9880d681SAndroid Build Coastguard Worker   //   A production starting and ending with a special character.
328*9880d681SAndroid Build Coastguard Worker   // b-
329*9880d681SAndroid Build Coastguard Worker   //   A production matching a single line break.
330*9880d681SAndroid Build Coastguard Worker   // nb-
331*9880d681SAndroid Build Coastguard Worker   //   A production starting and ending with a non-break character.
332*9880d681SAndroid Build Coastguard Worker   // s-
333*9880d681SAndroid Build Coastguard Worker   //   A production starting and ending with a white space character.
334*9880d681SAndroid Build Coastguard Worker   // ns-
335*9880d681SAndroid Build Coastguard Worker   //   A production starting and ending with a non-space character.
336*9880d681SAndroid Build Coastguard Worker   // l-
337*9880d681SAndroid Build Coastguard Worker   //   A production matching complete line(s).
338*9880d681SAndroid Build Coastguard Worker 
339*9880d681SAndroid Build Coastguard Worker   /// @brief Skip a single nb-char[27] starting at Position.
340*9880d681SAndroid Build Coastguard Worker   ///
341*9880d681SAndroid Build Coastguard Worker   /// A nb-char is 0x9 | [0x20-0x7E] | 0x85 | [0xA0-0xD7FF] | [0xE000-0xFEFE]
342*9880d681SAndroid Build Coastguard Worker   ///                  | [0xFF00-0xFFFD] | [0x10000-0x10FFFF]
343*9880d681SAndroid Build Coastguard Worker   ///
344*9880d681SAndroid Build Coastguard Worker   /// @returns The code unit after the nb-char, or Position if it's not an
345*9880d681SAndroid Build Coastguard Worker   ///          nb-char.
346*9880d681SAndroid Build Coastguard Worker   StringRef::iterator skip_nb_char(StringRef::iterator Position);
347*9880d681SAndroid Build Coastguard Worker 
348*9880d681SAndroid Build Coastguard Worker   /// @brief Skip a single b-break[28] starting at Position.
349*9880d681SAndroid Build Coastguard Worker   ///
350*9880d681SAndroid Build Coastguard Worker   /// A b-break is 0xD 0xA | 0xD | 0xA
351*9880d681SAndroid Build Coastguard Worker   ///
352*9880d681SAndroid Build Coastguard Worker   /// @returns The code unit after the b-break, or Position if it's not a
353*9880d681SAndroid Build Coastguard Worker   ///          b-break.
354*9880d681SAndroid Build Coastguard Worker   StringRef::iterator skip_b_break(StringRef::iterator Position);
355*9880d681SAndroid Build Coastguard Worker 
356*9880d681SAndroid Build Coastguard Worker   /// Skip a single s-space[31] starting at Position.
357*9880d681SAndroid Build Coastguard Worker   ///
358*9880d681SAndroid Build Coastguard Worker   /// An s-space is 0x20
359*9880d681SAndroid Build Coastguard Worker   ///
360*9880d681SAndroid Build Coastguard Worker   /// @returns The code unit after the s-space, or Position if it's not a
361*9880d681SAndroid Build Coastguard Worker   ///          s-space.
362*9880d681SAndroid Build Coastguard Worker   StringRef::iterator skip_s_space(StringRef::iterator Position);
363*9880d681SAndroid Build Coastguard Worker 
364*9880d681SAndroid Build Coastguard Worker   /// @brief Skip a single s-white[33] starting at Position.
365*9880d681SAndroid Build Coastguard Worker   ///
366*9880d681SAndroid Build Coastguard Worker   /// A s-white is 0x20 | 0x9
367*9880d681SAndroid Build Coastguard Worker   ///
368*9880d681SAndroid Build Coastguard Worker   /// @returns The code unit after the s-white, or Position if it's not a
369*9880d681SAndroid Build Coastguard Worker   ///          s-white.
370*9880d681SAndroid Build Coastguard Worker   StringRef::iterator skip_s_white(StringRef::iterator Position);
371*9880d681SAndroid Build Coastguard Worker 
372*9880d681SAndroid Build Coastguard Worker   /// @brief Skip a single ns-char[34] starting at Position.
373*9880d681SAndroid Build Coastguard Worker   ///
374*9880d681SAndroid Build Coastguard Worker   /// A ns-char is nb-char - s-white
375*9880d681SAndroid Build Coastguard Worker   ///
376*9880d681SAndroid Build Coastguard Worker   /// @returns The code unit after the ns-char, or Position if it's not a
377*9880d681SAndroid Build Coastguard Worker   ///          ns-char.
378*9880d681SAndroid Build Coastguard Worker   StringRef::iterator skip_ns_char(StringRef::iterator Position);
379*9880d681SAndroid Build Coastguard Worker 
380*9880d681SAndroid Build Coastguard Worker   typedef StringRef::iterator (Scanner::*SkipWhileFunc)(StringRef::iterator);
381*9880d681SAndroid Build Coastguard Worker   /// @brief Skip minimal well-formed code unit subsequences until Func
382*9880d681SAndroid Build Coastguard Worker   ///        returns its input.
383*9880d681SAndroid Build Coastguard Worker   ///
384*9880d681SAndroid Build Coastguard Worker   /// @returns The code unit after the last minimal well-formed code unit
385*9880d681SAndroid Build Coastguard Worker   ///          subsequence that Func accepted.
386*9880d681SAndroid Build Coastguard Worker   StringRef::iterator skip_while( SkipWhileFunc Func
387*9880d681SAndroid Build Coastguard Worker                                 , StringRef::iterator Position);
388*9880d681SAndroid Build Coastguard Worker 
389*9880d681SAndroid Build Coastguard Worker   /// Skip minimal well-formed code unit subsequences until Func returns its
390*9880d681SAndroid Build Coastguard Worker   /// input.
391*9880d681SAndroid Build Coastguard Worker   void advanceWhile(SkipWhileFunc Func);
392*9880d681SAndroid Build Coastguard Worker 
393*9880d681SAndroid Build Coastguard Worker   /// @brief Scan ns-uri-char[39]s starting at Cur.
394*9880d681SAndroid Build Coastguard Worker   ///
395*9880d681SAndroid Build Coastguard Worker   /// This updates Cur and Column while scanning.
396*9880d681SAndroid Build Coastguard Worker   ///
397*9880d681SAndroid Build Coastguard Worker   /// @returns A StringRef starting at Cur which covers the longest contiguous
398*9880d681SAndroid Build Coastguard Worker   ///          sequence of ns-uri-char.
399*9880d681SAndroid Build Coastguard Worker   StringRef scan_ns_uri_char();
400*9880d681SAndroid Build Coastguard Worker 
401*9880d681SAndroid Build Coastguard Worker   /// @brief Consume a minimal well-formed code unit subsequence starting at
402*9880d681SAndroid Build Coastguard Worker   ///        \a Cur. Return false if it is not the same Unicode scalar value as
403*9880d681SAndroid Build Coastguard Worker   ///        \a Expected. This updates \a Column.
404*9880d681SAndroid Build Coastguard Worker   bool consume(uint32_t Expected);
405*9880d681SAndroid Build Coastguard Worker 
406*9880d681SAndroid Build Coastguard Worker   /// @brief Skip \a Distance UTF-8 code units. Updates \a Cur and \a Column.
407*9880d681SAndroid Build Coastguard Worker   void skip(uint32_t Distance);
408*9880d681SAndroid Build Coastguard Worker 
409*9880d681SAndroid Build Coastguard Worker   /// @brief Return true if the minimal well-formed code unit subsequence at
410*9880d681SAndroid Build Coastguard Worker   ///        Pos is whitespace or a new line
411*9880d681SAndroid Build Coastguard Worker   bool isBlankOrBreak(StringRef::iterator Position);
412*9880d681SAndroid Build Coastguard Worker 
413*9880d681SAndroid Build Coastguard Worker   /// Consume a single b-break[28] if it's present at the current position.
414*9880d681SAndroid Build Coastguard Worker   ///
415*9880d681SAndroid Build Coastguard Worker   /// Return false if the code unit at the current position isn't a line break.
416*9880d681SAndroid Build Coastguard Worker   bool consumeLineBreakIfPresent();
417*9880d681SAndroid Build Coastguard Worker 
418*9880d681SAndroid Build Coastguard Worker   /// @brief If IsSimpleKeyAllowed, create and push_back a new SimpleKey.
419*9880d681SAndroid Build Coastguard Worker   void saveSimpleKeyCandidate( TokenQueueT::iterator Tok
420*9880d681SAndroid Build Coastguard Worker                              , unsigned AtColumn
421*9880d681SAndroid Build Coastguard Worker                              , bool IsRequired);
422*9880d681SAndroid Build Coastguard Worker 
423*9880d681SAndroid Build Coastguard Worker   /// @brief Remove simple keys that can no longer be valid simple keys.
424*9880d681SAndroid Build Coastguard Worker   ///
425*9880d681SAndroid Build Coastguard Worker   /// Invalid simple keys are not on the current line or are further than 1024
426*9880d681SAndroid Build Coastguard Worker   /// columns back.
427*9880d681SAndroid Build Coastguard Worker   void removeStaleSimpleKeyCandidates();
428*9880d681SAndroid Build Coastguard Worker 
429*9880d681SAndroid Build Coastguard Worker   /// @brief Remove all simple keys on FlowLevel \a Level.
430*9880d681SAndroid Build Coastguard Worker   void removeSimpleKeyCandidatesOnFlowLevel(unsigned Level);
431*9880d681SAndroid Build Coastguard Worker 
432*9880d681SAndroid Build Coastguard Worker   /// @brief Unroll indentation in \a Indents back to \a Col. Creates BlockEnd
433*9880d681SAndroid Build Coastguard Worker   ///        tokens if needed.
434*9880d681SAndroid Build Coastguard Worker   bool unrollIndent(int ToColumn);
435*9880d681SAndroid Build Coastguard Worker 
436*9880d681SAndroid Build Coastguard Worker   /// @brief Increase indent to \a Col. Creates \a Kind token at \a InsertPoint
437*9880d681SAndroid Build Coastguard Worker   ///        if needed.
438*9880d681SAndroid Build Coastguard Worker   bool rollIndent( int ToColumn
439*9880d681SAndroid Build Coastguard Worker                  , Token::TokenKind Kind
440*9880d681SAndroid Build Coastguard Worker                  , TokenQueueT::iterator InsertPoint);
441*9880d681SAndroid Build Coastguard Worker 
442*9880d681SAndroid Build Coastguard Worker   /// @brief Skip a single-line comment when the comment starts at the current
443*9880d681SAndroid Build Coastguard Worker   /// position of the scanner.
444*9880d681SAndroid Build Coastguard Worker   void skipComment();
445*9880d681SAndroid Build Coastguard Worker 
446*9880d681SAndroid Build Coastguard Worker   /// @brief Skip whitespace and comments until the start of the next token.
447*9880d681SAndroid Build Coastguard Worker   void scanToNextToken();
448*9880d681SAndroid Build Coastguard Worker 
449*9880d681SAndroid Build Coastguard Worker   /// @brief Must be the first token generated.
450*9880d681SAndroid Build Coastguard Worker   bool scanStreamStart();
451*9880d681SAndroid Build Coastguard Worker 
452*9880d681SAndroid Build Coastguard Worker   /// @brief Generate tokens needed to close out the stream.
453*9880d681SAndroid Build Coastguard Worker   bool scanStreamEnd();
454*9880d681SAndroid Build Coastguard Worker 
455*9880d681SAndroid Build Coastguard Worker   /// @brief Scan a %BLAH directive.
456*9880d681SAndroid Build Coastguard Worker   bool scanDirective();
457*9880d681SAndroid Build Coastguard Worker 
458*9880d681SAndroid Build Coastguard Worker   /// @brief Scan a ... or ---.
459*9880d681SAndroid Build Coastguard Worker   bool scanDocumentIndicator(bool IsStart);
460*9880d681SAndroid Build Coastguard Worker 
461*9880d681SAndroid Build Coastguard Worker   /// @brief Scan a [ or { and generate the proper flow collection start token.
462*9880d681SAndroid Build Coastguard Worker   bool scanFlowCollectionStart(bool IsSequence);
463*9880d681SAndroid Build Coastguard Worker 
464*9880d681SAndroid Build Coastguard Worker   /// @brief Scan a ] or } and generate the proper flow collection end token.
465*9880d681SAndroid Build Coastguard Worker   bool scanFlowCollectionEnd(bool IsSequence);
466*9880d681SAndroid Build Coastguard Worker 
467*9880d681SAndroid Build Coastguard Worker   /// @brief Scan the , that separates entries in a flow collection.
468*9880d681SAndroid Build Coastguard Worker   bool scanFlowEntry();
469*9880d681SAndroid Build Coastguard Worker 
470*9880d681SAndroid Build Coastguard Worker   /// @brief Scan the - that starts block sequence entries.
471*9880d681SAndroid Build Coastguard Worker   bool scanBlockEntry();
472*9880d681SAndroid Build Coastguard Worker 
473*9880d681SAndroid Build Coastguard Worker   /// @brief Scan an explicit ? indicating a key.
474*9880d681SAndroid Build Coastguard Worker   bool scanKey();
475*9880d681SAndroid Build Coastguard Worker 
476*9880d681SAndroid Build Coastguard Worker   /// @brief Scan an explicit : indicating a value.
477*9880d681SAndroid Build Coastguard Worker   bool scanValue();
478*9880d681SAndroid Build Coastguard Worker 
479*9880d681SAndroid Build Coastguard Worker   /// @brief Scan a quoted scalar.
480*9880d681SAndroid Build Coastguard Worker   bool scanFlowScalar(bool IsDoubleQuoted);
481*9880d681SAndroid Build Coastguard Worker 
482*9880d681SAndroid Build Coastguard Worker   /// @brief Scan an unquoted scalar.
483*9880d681SAndroid Build Coastguard Worker   bool scanPlainScalar();
484*9880d681SAndroid Build Coastguard Worker 
485*9880d681SAndroid Build Coastguard Worker   /// @brief Scan an Alias or Anchor starting with * or &.
486*9880d681SAndroid Build Coastguard Worker   bool scanAliasOrAnchor(bool IsAlias);
487*9880d681SAndroid Build Coastguard Worker 
488*9880d681SAndroid Build Coastguard Worker   /// @brief Scan a block scalar starting with | or >.
489*9880d681SAndroid Build Coastguard Worker   bool scanBlockScalar(bool IsLiteral);
490*9880d681SAndroid Build Coastguard Worker 
491*9880d681SAndroid Build Coastguard Worker   /// Scan a chomping indicator in a block scalar header.
492*9880d681SAndroid Build Coastguard Worker   char scanBlockChompingIndicator();
493*9880d681SAndroid Build Coastguard Worker 
494*9880d681SAndroid Build Coastguard Worker   /// Scan an indentation indicator in a block scalar header.
495*9880d681SAndroid Build Coastguard Worker   unsigned scanBlockIndentationIndicator();
496*9880d681SAndroid Build Coastguard Worker 
497*9880d681SAndroid Build Coastguard Worker   /// Scan a block scalar header.
498*9880d681SAndroid Build Coastguard Worker   ///
499*9880d681SAndroid Build Coastguard Worker   /// Return false if an error occurred.
500*9880d681SAndroid Build Coastguard Worker   bool scanBlockScalarHeader(char &ChompingIndicator, unsigned &IndentIndicator,
501*9880d681SAndroid Build Coastguard Worker                              bool &IsDone);
502*9880d681SAndroid Build Coastguard Worker 
503*9880d681SAndroid Build Coastguard Worker   /// Look for the indentation level of a block scalar.
504*9880d681SAndroid Build Coastguard Worker   ///
505*9880d681SAndroid Build Coastguard Worker   /// Return false if an error occurred.
506*9880d681SAndroid Build Coastguard Worker   bool findBlockScalarIndent(unsigned &BlockIndent, unsigned BlockExitIndent,
507*9880d681SAndroid Build Coastguard Worker                              unsigned &LineBreaks, bool &IsDone);
508*9880d681SAndroid Build Coastguard Worker 
509*9880d681SAndroid Build Coastguard Worker   /// Scan the indentation of a text line in a block scalar.
510*9880d681SAndroid Build Coastguard Worker   ///
511*9880d681SAndroid Build Coastguard Worker   /// Return false if an error occurred.
512*9880d681SAndroid Build Coastguard Worker   bool scanBlockScalarIndent(unsigned BlockIndent, unsigned BlockExitIndent,
513*9880d681SAndroid Build Coastguard Worker                              bool &IsDone);
514*9880d681SAndroid Build Coastguard Worker 
515*9880d681SAndroid Build Coastguard Worker   /// @brief Scan a tag of the form !stuff.
516*9880d681SAndroid Build Coastguard Worker   bool scanTag();
517*9880d681SAndroid Build Coastguard Worker 
518*9880d681SAndroid Build Coastguard Worker   /// @brief Dispatch to the next scanning function based on \a *Cur.
519*9880d681SAndroid Build Coastguard Worker   bool fetchMoreTokens();
520*9880d681SAndroid Build Coastguard Worker 
521*9880d681SAndroid Build Coastguard Worker   /// @brief The SourceMgr used for diagnostics and buffer management.
522*9880d681SAndroid Build Coastguard Worker   SourceMgr &SM;
523*9880d681SAndroid Build Coastguard Worker 
524*9880d681SAndroid Build Coastguard Worker   /// @brief The original input.
525*9880d681SAndroid Build Coastguard Worker   MemoryBufferRef InputBuffer;
526*9880d681SAndroid Build Coastguard Worker 
527*9880d681SAndroid Build Coastguard Worker   /// @brief The current position of the scanner.
528*9880d681SAndroid Build Coastguard Worker   StringRef::iterator Current;
529*9880d681SAndroid Build Coastguard Worker 
530*9880d681SAndroid Build Coastguard Worker   /// @brief The end of the input (one past the last character).
531*9880d681SAndroid Build Coastguard Worker   StringRef::iterator End;
532*9880d681SAndroid Build Coastguard Worker 
533*9880d681SAndroid Build Coastguard Worker   /// @brief Current YAML indentation level in spaces.
534*9880d681SAndroid Build Coastguard Worker   int Indent;
535*9880d681SAndroid Build Coastguard Worker 
536*9880d681SAndroid Build Coastguard Worker   /// @brief Current column number in Unicode code points.
537*9880d681SAndroid Build Coastguard Worker   unsigned Column;
538*9880d681SAndroid Build Coastguard Worker 
539*9880d681SAndroid Build Coastguard Worker   /// @brief Current line number.
540*9880d681SAndroid Build Coastguard Worker   unsigned Line;
541*9880d681SAndroid Build Coastguard Worker 
542*9880d681SAndroid Build Coastguard Worker   /// @brief How deep we are in flow style containers. 0 Means at block level.
543*9880d681SAndroid Build Coastguard Worker   unsigned FlowLevel;
544*9880d681SAndroid Build Coastguard Worker 
545*9880d681SAndroid Build Coastguard Worker   /// @brief Are we at the start of the stream?
546*9880d681SAndroid Build Coastguard Worker   bool IsStartOfStream;
547*9880d681SAndroid Build Coastguard Worker 
548*9880d681SAndroid Build Coastguard Worker   /// @brief Can the next token be the start of a simple key?
549*9880d681SAndroid Build Coastguard Worker   bool IsSimpleKeyAllowed;
550*9880d681SAndroid Build Coastguard Worker 
551*9880d681SAndroid Build Coastguard Worker   /// @brief True if an error has occurred.
552*9880d681SAndroid Build Coastguard Worker   bool Failed;
553*9880d681SAndroid Build Coastguard Worker 
554*9880d681SAndroid Build Coastguard Worker   /// @brief Should colors be used when printing out the diagnostic messages?
555*9880d681SAndroid Build Coastguard Worker   bool ShowColors;
556*9880d681SAndroid Build Coastguard Worker 
557*9880d681SAndroid Build Coastguard Worker   /// @brief Queue of tokens. This is required to queue up tokens while looking
558*9880d681SAndroid Build Coastguard Worker   ///        for the end of a simple key. And for cases where a single character
559*9880d681SAndroid Build Coastguard Worker   ///        can produce multiple tokens (e.g. BlockEnd).
560*9880d681SAndroid Build Coastguard Worker   TokenQueueT TokenQueue;
561*9880d681SAndroid Build Coastguard Worker 
562*9880d681SAndroid Build Coastguard Worker   /// @brief Indentation levels.
563*9880d681SAndroid Build Coastguard Worker   SmallVector<int, 4> Indents;
564*9880d681SAndroid Build Coastguard Worker 
565*9880d681SAndroid Build Coastguard Worker   /// @brief Potential simple keys.
566*9880d681SAndroid Build Coastguard Worker   SmallVector<SimpleKey, 4> SimpleKeys;
567*9880d681SAndroid Build Coastguard Worker };
568*9880d681SAndroid Build Coastguard Worker 
569*9880d681SAndroid Build Coastguard Worker } // end namespace yaml
570*9880d681SAndroid Build Coastguard Worker } // end namespace llvm
571*9880d681SAndroid Build Coastguard Worker 
572*9880d681SAndroid Build Coastguard Worker /// encodeUTF8 - Encode \a UnicodeScalarValue in UTF-8 and append it to result.
encodeUTF8(uint32_t UnicodeScalarValue,SmallVectorImpl<char> & Result)573*9880d681SAndroid Build Coastguard Worker static void encodeUTF8( uint32_t UnicodeScalarValue
574*9880d681SAndroid Build Coastguard Worker                       , SmallVectorImpl<char> &Result) {
575*9880d681SAndroid Build Coastguard Worker   if (UnicodeScalarValue <= 0x7F) {
576*9880d681SAndroid Build Coastguard Worker     Result.push_back(UnicodeScalarValue & 0x7F);
577*9880d681SAndroid Build Coastguard Worker   } else if (UnicodeScalarValue <= 0x7FF) {
578*9880d681SAndroid Build Coastguard Worker     uint8_t FirstByte = 0xC0 | ((UnicodeScalarValue & 0x7C0) >> 6);
579*9880d681SAndroid Build Coastguard Worker     uint8_t SecondByte = 0x80 | (UnicodeScalarValue & 0x3F);
580*9880d681SAndroid Build Coastguard Worker     Result.push_back(FirstByte);
581*9880d681SAndroid Build Coastguard Worker     Result.push_back(SecondByte);
582*9880d681SAndroid Build Coastguard Worker   } else if (UnicodeScalarValue <= 0xFFFF) {
583*9880d681SAndroid Build Coastguard Worker     uint8_t FirstByte = 0xE0 | ((UnicodeScalarValue & 0xF000) >> 12);
584*9880d681SAndroid Build Coastguard Worker     uint8_t SecondByte = 0x80 | ((UnicodeScalarValue & 0xFC0) >> 6);
585*9880d681SAndroid Build Coastguard Worker     uint8_t ThirdByte = 0x80 | (UnicodeScalarValue & 0x3F);
586*9880d681SAndroid Build Coastguard Worker     Result.push_back(FirstByte);
587*9880d681SAndroid Build Coastguard Worker     Result.push_back(SecondByte);
588*9880d681SAndroid Build Coastguard Worker     Result.push_back(ThirdByte);
589*9880d681SAndroid Build Coastguard Worker   } else if (UnicodeScalarValue <= 0x10FFFF) {
590*9880d681SAndroid Build Coastguard Worker     uint8_t FirstByte = 0xF0 | ((UnicodeScalarValue & 0x1F0000) >> 18);
591*9880d681SAndroid Build Coastguard Worker     uint8_t SecondByte = 0x80 | ((UnicodeScalarValue & 0x3F000) >> 12);
592*9880d681SAndroid Build Coastguard Worker     uint8_t ThirdByte = 0x80 | ((UnicodeScalarValue & 0xFC0) >> 6);
593*9880d681SAndroid Build Coastguard Worker     uint8_t FourthByte = 0x80 | (UnicodeScalarValue & 0x3F);
594*9880d681SAndroid Build Coastguard Worker     Result.push_back(FirstByte);
595*9880d681SAndroid Build Coastguard Worker     Result.push_back(SecondByte);
596*9880d681SAndroid Build Coastguard Worker     Result.push_back(ThirdByte);
597*9880d681SAndroid Build Coastguard Worker     Result.push_back(FourthByte);
598*9880d681SAndroid Build Coastguard Worker   }
599*9880d681SAndroid Build Coastguard Worker }
600*9880d681SAndroid Build Coastguard Worker 
dumpTokens(StringRef Input,raw_ostream & OS)601*9880d681SAndroid Build Coastguard Worker bool yaml::dumpTokens(StringRef Input, raw_ostream &OS) {
602*9880d681SAndroid Build Coastguard Worker   SourceMgr SM;
603*9880d681SAndroid Build Coastguard Worker   Scanner scanner(Input, SM);
604*9880d681SAndroid Build Coastguard Worker   while (true) {
605*9880d681SAndroid Build Coastguard Worker     Token T = scanner.getNext();
606*9880d681SAndroid Build Coastguard Worker     switch (T.Kind) {
607*9880d681SAndroid Build Coastguard Worker     case Token::TK_StreamStart:
608*9880d681SAndroid Build Coastguard Worker       OS << "Stream-Start: ";
609*9880d681SAndroid Build Coastguard Worker       break;
610*9880d681SAndroid Build Coastguard Worker     case Token::TK_StreamEnd:
611*9880d681SAndroid Build Coastguard Worker       OS << "Stream-End: ";
612*9880d681SAndroid Build Coastguard Worker       break;
613*9880d681SAndroid Build Coastguard Worker     case Token::TK_VersionDirective:
614*9880d681SAndroid Build Coastguard Worker       OS << "Version-Directive: ";
615*9880d681SAndroid Build Coastguard Worker       break;
616*9880d681SAndroid Build Coastguard Worker     case Token::TK_TagDirective:
617*9880d681SAndroid Build Coastguard Worker       OS << "Tag-Directive: ";
618*9880d681SAndroid Build Coastguard Worker       break;
619*9880d681SAndroid Build Coastguard Worker     case Token::TK_DocumentStart:
620*9880d681SAndroid Build Coastguard Worker       OS << "Document-Start: ";
621*9880d681SAndroid Build Coastguard Worker       break;
622*9880d681SAndroid Build Coastguard Worker     case Token::TK_DocumentEnd:
623*9880d681SAndroid Build Coastguard Worker       OS << "Document-End: ";
624*9880d681SAndroid Build Coastguard Worker       break;
625*9880d681SAndroid Build Coastguard Worker     case Token::TK_BlockEntry:
626*9880d681SAndroid Build Coastguard Worker       OS << "Block-Entry: ";
627*9880d681SAndroid Build Coastguard Worker       break;
628*9880d681SAndroid Build Coastguard Worker     case Token::TK_BlockEnd:
629*9880d681SAndroid Build Coastguard Worker       OS << "Block-End: ";
630*9880d681SAndroid Build Coastguard Worker       break;
631*9880d681SAndroid Build Coastguard Worker     case Token::TK_BlockSequenceStart:
632*9880d681SAndroid Build Coastguard Worker       OS << "Block-Sequence-Start: ";
633*9880d681SAndroid Build Coastguard Worker       break;
634*9880d681SAndroid Build Coastguard Worker     case Token::TK_BlockMappingStart:
635*9880d681SAndroid Build Coastguard Worker       OS << "Block-Mapping-Start: ";
636*9880d681SAndroid Build Coastguard Worker       break;
637*9880d681SAndroid Build Coastguard Worker     case Token::TK_FlowEntry:
638*9880d681SAndroid Build Coastguard Worker       OS << "Flow-Entry: ";
639*9880d681SAndroid Build Coastguard Worker       break;
640*9880d681SAndroid Build Coastguard Worker     case Token::TK_FlowSequenceStart:
641*9880d681SAndroid Build Coastguard Worker       OS << "Flow-Sequence-Start: ";
642*9880d681SAndroid Build Coastguard Worker       break;
643*9880d681SAndroid Build Coastguard Worker     case Token::TK_FlowSequenceEnd:
644*9880d681SAndroid Build Coastguard Worker       OS << "Flow-Sequence-End: ";
645*9880d681SAndroid Build Coastguard Worker       break;
646*9880d681SAndroid Build Coastguard Worker     case Token::TK_FlowMappingStart:
647*9880d681SAndroid Build Coastguard Worker       OS << "Flow-Mapping-Start: ";
648*9880d681SAndroid Build Coastguard Worker       break;
649*9880d681SAndroid Build Coastguard Worker     case Token::TK_FlowMappingEnd:
650*9880d681SAndroid Build Coastguard Worker       OS << "Flow-Mapping-End: ";
651*9880d681SAndroid Build Coastguard Worker       break;
652*9880d681SAndroid Build Coastguard Worker     case Token::TK_Key:
653*9880d681SAndroid Build Coastguard Worker       OS << "Key: ";
654*9880d681SAndroid Build Coastguard Worker       break;
655*9880d681SAndroid Build Coastguard Worker     case Token::TK_Value:
656*9880d681SAndroid Build Coastguard Worker       OS << "Value: ";
657*9880d681SAndroid Build Coastguard Worker       break;
658*9880d681SAndroid Build Coastguard Worker     case Token::TK_Scalar:
659*9880d681SAndroid Build Coastguard Worker       OS << "Scalar: ";
660*9880d681SAndroid Build Coastguard Worker       break;
661*9880d681SAndroid Build Coastguard Worker     case Token::TK_BlockScalar:
662*9880d681SAndroid Build Coastguard Worker       OS << "Block Scalar: ";
663*9880d681SAndroid Build Coastguard Worker       break;
664*9880d681SAndroid Build Coastguard Worker     case Token::TK_Alias:
665*9880d681SAndroid Build Coastguard Worker       OS << "Alias: ";
666*9880d681SAndroid Build Coastguard Worker       break;
667*9880d681SAndroid Build Coastguard Worker     case Token::TK_Anchor:
668*9880d681SAndroid Build Coastguard Worker       OS << "Anchor: ";
669*9880d681SAndroid Build Coastguard Worker       break;
670*9880d681SAndroid Build Coastguard Worker     case Token::TK_Tag:
671*9880d681SAndroid Build Coastguard Worker       OS << "Tag: ";
672*9880d681SAndroid Build Coastguard Worker       break;
673*9880d681SAndroid Build Coastguard Worker     case Token::TK_Error:
674*9880d681SAndroid Build Coastguard Worker       break;
675*9880d681SAndroid Build Coastguard Worker     }
676*9880d681SAndroid Build Coastguard Worker     OS << T.Range << "\n";
677*9880d681SAndroid Build Coastguard Worker     if (T.Kind == Token::TK_StreamEnd)
678*9880d681SAndroid Build Coastguard Worker       break;
679*9880d681SAndroid Build Coastguard Worker     else if (T.Kind == Token::TK_Error)
680*9880d681SAndroid Build Coastguard Worker       return false;
681*9880d681SAndroid Build Coastguard Worker   }
682*9880d681SAndroid Build Coastguard Worker   return true;
683*9880d681SAndroid Build Coastguard Worker }
684*9880d681SAndroid Build Coastguard Worker 
scanTokens(StringRef Input)685*9880d681SAndroid Build Coastguard Worker bool yaml::scanTokens(StringRef Input) {
686*9880d681SAndroid Build Coastguard Worker   llvm::SourceMgr SM;
687*9880d681SAndroid Build Coastguard Worker   llvm::yaml::Scanner scanner(Input, SM);
688*9880d681SAndroid Build Coastguard Worker   for (;;) {
689*9880d681SAndroid Build Coastguard Worker     llvm::yaml::Token T = scanner.getNext();
690*9880d681SAndroid Build Coastguard Worker     if (T.Kind == Token::TK_StreamEnd)
691*9880d681SAndroid Build Coastguard Worker       break;
692*9880d681SAndroid Build Coastguard Worker     else if (T.Kind == Token::TK_Error)
693*9880d681SAndroid Build Coastguard Worker       return false;
694*9880d681SAndroid Build Coastguard Worker   }
695*9880d681SAndroid Build Coastguard Worker   return true;
696*9880d681SAndroid Build Coastguard Worker }
697*9880d681SAndroid Build Coastguard Worker 
escape(StringRef Input)698*9880d681SAndroid Build Coastguard Worker std::string yaml::escape(StringRef Input) {
699*9880d681SAndroid Build Coastguard Worker   std::string EscapedInput;
700*9880d681SAndroid Build Coastguard Worker   for (StringRef::iterator i = Input.begin(), e = Input.end(); i != e; ++i) {
701*9880d681SAndroid Build Coastguard Worker     if (*i == '\\')
702*9880d681SAndroid Build Coastguard Worker       EscapedInput += "\\\\";
703*9880d681SAndroid Build Coastguard Worker     else if (*i == '"')
704*9880d681SAndroid Build Coastguard Worker       EscapedInput += "\\\"";
705*9880d681SAndroid Build Coastguard Worker     else if (*i == 0)
706*9880d681SAndroid Build Coastguard Worker       EscapedInput += "\\0";
707*9880d681SAndroid Build Coastguard Worker     else if (*i == 0x07)
708*9880d681SAndroid Build Coastguard Worker       EscapedInput += "\\a";
709*9880d681SAndroid Build Coastguard Worker     else if (*i == 0x08)
710*9880d681SAndroid Build Coastguard Worker       EscapedInput += "\\b";
711*9880d681SAndroid Build Coastguard Worker     else if (*i == 0x09)
712*9880d681SAndroid Build Coastguard Worker       EscapedInput += "\\t";
713*9880d681SAndroid Build Coastguard Worker     else if (*i == 0x0A)
714*9880d681SAndroid Build Coastguard Worker       EscapedInput += "\\n";
715*9880d681SAndroid Build Coastguard Worker     else if (*i == 0x0B)
716*9880d681SAndroid Build Coastguard Worker       EscapedInput += "\\v";
717*9880d681SAndroid Build Coastguard Worker     else if (*i == 0x0C)
718*9880d681SAndroid Build Coastguard Worker       EscapedInput += "\\f";
719*9880d681SAndroid Build Coastguard Worker     else if (*i == 0x0D)
720*9880d681SAndroid Build Coastguard Worker       EscapedInput += "\\r";
721*9880d681SAndroid Build Coastguard Worker     else if (*i == 0x1B)
722*9880d681SAndroid Build Coastguard Worker       EscapedInput += "\\e";
723*9880d681SAndroid Build Coastguard Worker     else if ((unsigned char)*i < 0x20) { // Control characters not handled above.
724*9880d681SAndroid Build Coastguard Worker       std::string HexStr = utohexstr(*i);
725*9880d681SAndroid Build Coastguard Worker       EscapedInput += "\\x" + std::string(2 - HexStr.size(), '0') + HexStr;
726*9880d681SAndroid Build Coastguard Worker     } else if (*i & 0x80) { // UTF-8 multiple code unit subsequence.
727*9880d681SAndroid Build Coastguard Worker       UTF8Decoded UnicodeScalarValue
728*9880d681SAndroid Build Coastguard Worker         = decodeUTF8(StringRef(i, Input.end() - i));
729*9880d681SAndroid Build Coastguard Worker       if (UnicodeScalarValue.second == 0) {
730*9880d681SAndroid Build Coastguard Worker         // Found invalid char.
731*9880d681SAndroid Build Coastguard Worker         SmallString<4> Val;
732*9880d681SAndroid Build Coastguard Worker         encodeUTF8(0xFFFD, Val);
733*9880d681SAndroid Build Coastguard Worker         EscapedInput.insert(EscapedInput.end(), Val.begin(), Val.end());
734*9880d681SAndroid Build Coastguard Worker         // FIXME: Error reporting.
735*9880d681SAndroid Build Coastguard Worker         return EscapedInput;
736*9880d681SAndroid Build Coastguard Worker       }
737*9880d681SAndroid Build Coastguard Worker       if (UnicodeScalarValue.first == 0x85)
738*9880d681SAndroid Build Coastguard Worker         EscapedInput += "\\N";
739*9880d681SAndroid Build Coastguard Worker       else if (UnicodeScalarValue.first == 0xA0)
740*9880d681SAndroid Build Coastguard Worker         EscapedInput += "\\_";
741*9880d681SAndroid Build Coastguard Worker       else if (UnicodeScalarValue.first == 0x2028)
742*9880d681SAndroid Build Coastguard Worker         EscapedInput += "\\L";
743*9880d681SAndroid Build Coastguard Worker       else if (UnicodeScalarValue.first == 0x2029)
744*9880d681SAndroid Build Coastguard Worker         EscapedInput += "\\P";
745*9880d681SAndroid Build Coastguard Worker       else {
746*9880d681SAndroid Build Coastguard Worker         std::string HexStr = utohexstr(UnicodeScalarValue.first);
747*9880d681SAndroid Build Coastguard Worker         if (HexStr.size() <= 2)
748*9880d681SAndroid Build Coastguard Worker           EscapedInput += "\\x" + std::string(2 - HexStr.size(), '0') + HexStr;
749*9880d681SAndroid Build Coastguard Worker         else if (HexStr.size() <= 4)
750*9880d681SAndroid Build Coastguard Worker           EscapedInput += "\\u" + std::string(4 - HexStr.size(), '0') + HexStr;
751*9880d681SAndroid Build Coastguard Worker         else if (HexStr.size() <= 8)
752*9880d681SAndroid Build Coastguard Worker           EscapedInput += "\\U" + std::string(8 - HexStr.size(), '0') + HexStr;
753*9880d681SAndroid Build Coastguard Worker       }
754*9880d681SAndroid Build Coastguard Worker       i += UnicodeScalarValue.second - 1;
755*9880d681SAndroid Build Coastguard Worker     } else
756*9880d681SAndroid Build Coastguard Worker       EscapedInput.push_back(*i);
757*9880d681SAndroid Build Coastguard Worker   }
758*9880d681SAndroid Build Coastguard Worker   return EscapedInput;
759*9880d681SAndroid Build Coastguard Worker }
760*9880d681SAndroid Build Coastguard Worker 
Scanner(StringRef Input,SourceMgr & sm,bool ShowColors)761*9880d681SAndroid Build Coastguard Worker Scanner::Scanner(StringRef Input, SourceMgr &sm, bool ShowColors)
762*9880d681SAndroid Build Coastguard Worker     : SM(sm), ShowColors(ShowColors) {
763*9880d681SAndroid Build Coastguard Worker   init(MemoryBufferRef(Input, "YAML"));
764*9880d681SAndroid Build Coastguard Worker }
765*9880d681SAndroid Build Coastguard Worker 
Scanner(MemoryBufferRef Buffer,SourceMgr & SM_,bool ShowColors)766*9880d681SAndroid Build Coastguard Worker Scanner::Scanner(MemoryBufferRef Buffer, SourceMgr &SM_, bool ShowColors)
767*9880d681SAndroid Build Coastguard Worker     : SM(SM_), ShowColors(ShowColors) {
768*9880d681SAndroid Build Coastguard Worker   init(Buffer);
769*9880d681SAndroid Build Coastguard Worker }
770*9880d681SAndroid Build Coastguard Worker 
init(MemoryBufferRef Buffer)771*9880d681SAndroid Build Coastguard Worker void Scanner::init(MemoryBufferRef Buffer) {
772*9880d681SAndroid Build Coastguard Worker   InputBuffer = Buffer;
773*9880d681SAndroid Build Coastguard Worker   Current = InputBuffer.getBufferStart();
774*9880d681SAndroid Build Coastguard Worker   End = InputBuffer.getBufferEnd();
775*9880d681SAndroid Build Coastguard Worker   Indent = -1;
776*9880d681SAndroid Build Coastguard Worker   Column = 0;
777*9880d681SAndroid Build Coastguard Worker   Line = 0;
778*9880d681SAndroid Build Coastguard Worker   FlowLevel = 0;
779*9880d681SAndroid Build Coastguard Worker   IsStartOfStream = true;
780*9880d681SAndroid Build Coastguard Worker   IsSimpleKeyAllowed = true;
781*9880d681SAndroid Build Coastguard Worker   Failed = false;
782*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<MemoryBuffer> InputBufferOwner =
783*9880d681SAndroid Build Coastguard Worker       MemoryBuffer::getMemBuffer(Buffer);
784*9880d681SAndroid Build Coastguard Worker   SM.AddNewSourceBuffer(std::move(InputBufferOwner), SMLoc());
785*9880d681SAndroid Build Coastguard Worker }
786*9880d681SAndroid Build Coastguard Worker 
peekNext()787*9880d681SAndroid Build Coastguard Worker Token &Scanner::peekNext() {
788*9880d681SAndroid Build Coastguard Worker   // If the current token is a possible simple key, keep parsing until we
789*9880d681SAndroid Build Coastguard Worker   // can confirm.
790*9880d681SAndroid Build Coastguard Worker   bool NeedMore = false;
791*9880d681SAndroid Build Coastguard Worker   while (true) {
792*9880d681SAndroid Build Coastguard Worker     if (TokenQueue.empty() || NeedMore) {
793*9880d681SAndroid Build Coastguard Worker       if (!fetchMoreTokens()) {
794*9880d681SAndroid Build Coastguard Worker         TokenQueue.clear();
795*9880d681SAndroid Build Coastguard Worker         TokenQueue.push_back(Token());
796*9880d681SAndroid Build Coastguard Worker         return TokenQueue.front();
797*9880d681SAndroid Build Coastguard Worker       }
798*9880d681SAndroid Build Coastguard Worker     }
799*9880d681SAndroid Build Coastguard Worker     assert(!TokenQueue.empty() &&
800*9880d681SAndroid Build Coastguard Worker             "fetchMoreTokens lied about getting tokens!");
801*9880d681SAndroid Build Coastguard Worker 
802*9880d681SAndroid Build Coastguard Worker     removeStaleSimpleKeyCandidates();
803*9880d681SAndroid Build Coastguard Worker     SimpleKey SK;
804*9880d681SAndroid Build Coastguard Worker     SK.Tok = TokenQueue.begin();
805*9880d681SAndroid Build Coastguard Worker     if (std::find(SimpleKeys.begin(), SimpleKeys.end(), SK)
806*9880d681SAndroid Build Coastguard Worker         == SimpleKeys.end())
807*9880d681SAndroid Build Coastguard Worker       break;
808*9880d681SAndroid Build Coastguard Worker     else
809*9880d681SAndroid Build Coastguard Worker       NeedMore = true;
810*9880d681SAndroid Build Coastguard Worker   }
811*9880d681SAndroid Build Coastguard Worker   return TokenQueue.front();
812*9880d681SAndroid Build Coastguard Worker }
813*9880d681SAndroid Build Coastguard Worker 
getNext()814*9880d681SAndroid Build Coastguard Worker Token Scanner::getNext() {
815*9880d681SAndroid Build Coastguard Worker   Token Ret = peekNext();
816*9880d681SAndroid Build Coastguard Worker   // TokenQueue can be empty if there was an error getting the next token.
817*9880d681SAndroid Build Coastguard Worker   if (!TokenQueue.empty())
818*9880d681SAndroid Build Coastguard Worker     TokenQueue.pop_front();
819*9880d681SAndroid Build Coastguard Worker 
820*9880d681SAndroid Build Coastguard Worker   // There cannot be any referenced Token's if the TokenQueue is empty. So do a
821*9880d681SAndroid Build Coastguard Worker   // quick deallocation of them all.
822*9880d681SAndroid Build Coastguard Worker   if (TokenQueue.empty()) {
823*9880d681SAndroid Build Coastguard Worker     TokenQueue.Alloc.Reset();
824*9880d681SAndroid Build Coastguard Worker   }
825*9880d681SAndroid Build Coastguard Worker 
826*9880d681SAndroid Build Coastguard Worker   return Ret;
827*9880d681SAndroid Build Coastguard Worker }
828*9880d681SAndroid Build Coastguard Worker 
skip_nb_char(StringRef::iterator Position)829*9880d681SAndroid Build Coastguard Worker StringRef::iterator Scanner::skip_nb_char(StringRef::iterator Position) {
830*9880d681SAndroid Build Coastguard Worker   if (Position == End)
831*9880d681SAndroid Build Coastguard Worker     return Position;
832*9880d681SAndroid Build Coastguard Worker   // Check 7 bit c-printable - b-char.
833*9880d681SAndroid Build Coastguard Worker   if (   *Position == 0x09
834*9880d681SAndroid Build Coastguard Worker       || (*Position >= 0x20 && *Position <= 0x7E))
835*9880d681SAndroid Build Coastguard Worker     return Position + 1;
836*9880d681SAndroid Build Coastguard Worker 
837*9880d681SAndroid Build Coastguard Worker   // Check for valid UTF-8.
838*9880d681SAndroid Build Coastguard Worker   if (uint8_t(*Position) & 0x80) {
839*9880d681SAndroid Build Coastguard Worker     UTF8Decoded u8d = decodeUTF8(Position);
840*9880d681SAndroid Build Coastguard Worker     if (   u8d.second != 0
841*9880d681SAndroid Build Coastguard Worker         && u8d.first != 0xFEFF
842*9880d681SAndroid Build Coastguard Worker         && ( u8d.first == 0x85
843*9880d681SAndroid Build Coastguard Worker           || ( u8d.first >= 0xA0
844*9880d681SAndroid Build Coastguard Worker             && u8d.first <= 0xD7FF)
845*9880d681SAndroid Build Coastguard Worker           || ( u8d.first >= 0xE000
846*9880d681SAndroid Build Coastguard Worker             && u8d.first <= 0xFFFD)
847*9880d681SAndroid Build Coastguard Worker           || ( u8d.first >= 0x10000
848*9880d681SAndroid Build Coastguard Worker             && u8d.first <= 0x10FFFF)))
849*9880d681SAndroid Build Coastguard Worker       return Position + u8d.second;
850*9880d681SAndroid Build Coastguard Worker   }
851*9880d681SAndroid Build Coastguard Worker   return Position;
852*9880d681SAndroid Build Coastguard Worker }
853*9880d681SAndroid Build Coastguard Worker 
skip_b_break(StringRef::iterator Position)854*9880d681SAndroid Build Coastguard Worker StringRef::iterator Scanner::skip_b_break(StringRef::iterator Position) {
855*9880d681SAndroid Build Coastguard Worker   if (Position == End)
856*9880d681SAndroid Build Coastguard Worker     return Position;
857*9880d681SAndroid Build Coastguard Worker   if (*Position == 0x0D) {
858*9880d681SAndroid Build Coastguard Worker     if (Position + 1 != End && *(Position + 1) == 0x0A)
859*9880d681SAndroid Build Coastguard Worker       return Position + 2;
860*9880d681SAndroid Build Coastguard Worker     return Position + 1;
861*9880d681SAndroid Build Coastguard Worker   }
862*9880d681SAndroid Build Coastguard Worker 
863*9880d681SAndroid Build Coastguard Worker   if (*Position == 0x0A)
864*9880d681SAndroid Build Coastguard Worker     return Position + 1;
865*9880d681SAndroid Build Coastguard Worker   return Position;
866*9880d681SAndroid Build Coastguard Worker }
867*9880d681SAndroid Build Coastguard Worker 
skip_s_space(StringRef::iterator Position)868*9880d681SAndroid Build Coastguard Worker StringRef::iterator Scanner::skip_s_space(StringRef::iterator Position) {
869*9880d681SAndroid Build Coastguard Worker   if (Position == End)
870*9880d681SAndroid Build Coastguard Worker     return Position;
871*9880d681SAndroid Build Coastguard Worker   if (*Position == ' ')
872*9880d681SAndroid Build Coastguard Worker     return Position + 1;
873*9880d681SAndroid Build Coastguard Worker   return Position;
874*9880d681SAndroid Build Coastguard Worker }
875*9880d681SAndroid Build Coastguard Worker 
skip_s_white(StringRef::iterator Position)876*9880d681SAndroid Build Coastguard Worker StringRef::iterator Scanner::skip_s_white(StringRef::iterator Position) {
877*9880d681SAndroid Build Coastguard Worker   if (Position == End)
878*9880d681SAndroid Build Coastguard Worker     return Position;
879*9880d681SAndroid Build Coastguard Worker   if (*Position == ' ' || *Position == '\t')
880*9880d681SAndroid Build Coastguard Worker     return Position + 1;
881*9880d681SAndroid Build Coastguard Worker   return Position;
882*9880d681SAndroid Build Coastguard Worker }
883*9880d681SAndroid Build Coastguard Worker 
skip_ns_char(StringRef::iterator Position)884*9880d681SAndroid Build Coastguard Worker StringRef::iterator Scanner::skip_ns_char(StringRef::iterator Position) {
885*9880d681SAndroid Build Coastguard Worker   if (Position == End)
886*9880d681SAndroid Build Coastguard Worker     return Position;
887*9880d681SAndroid Build Coastguard Worker   if (*Position == ' ' || *Position == '\t')
888*9880d681SAndroid Build Coastguard Worker     return Position;
889*9880d681SAndroid Build Coastguard Worker   return skip_nb_char(Position);
890*9880d681SAndroid Build Coastguard Worker }
891*9880d681SAndroid Build Coastguard Worker 
skip_while(SkipWhileFunc Func,StringRef::iterator Position)892*9880d681SAndroid Build Coastguard Worker StringRef::iterator Scanner::skip_while( SkipWhileFunc Func
893*9880d681SAndroid Build Coastguard Worker                                        , StringRef::iterator Position) {
894*9880d681SAndroid Build Coastguard Worker   while (true) {
895*9880d681SAndroid Build Coastguard Worker     StringRef::iterator i = (this->*Func)(Position);
896*9880d681SAndroid Build Coastguard Worker     if (i == Position)
897*9880d681SAndroid Build Coastguard Worker       break;
898*9880d681SAndroid Build Coastguard Worker     Position = i;
899*9880d681SAndroid Build Coastguard Worker   }
900*9880d681SAndroid Build Coastguard Worker   return Position;
901*9880d681SAndroid Build Coastguard Worker }
902*9880d681SAndroid Build Coastguard Worker 
advanceWhile(SkipWhileFunc Func)903*9880d681SAndroid Build Coastguard Worker void Scanner::advanceWhile(SkipWhileFunc Func) {
904*9880d681SAndroid Build Coastguard Worker   auto Final = skip_while(Func, Current);
905*9880d681SAndroid Build Coastguard Worker   Column += Final - Current;
906*9880d681SAndroid Build Coastguard Worker   Current = Final;
907*9880d681SAndroid Build Coastguard Worker }
908*9880d681SAndroid Build Coastguard Worker 
is_ns_hex_digit(const char C)909*9880d681SAndroid Build Coastguard Worker static bool is_ns_hex_digit(const char C) {
910*9880d681SAndroid Build Coastguard Worker   return    (C >= '0' && C <= '9')
911*9880d681SAndroid Build Coastguard Worker          || (C >= 'a' && C <= 'z')
912*9880d681SAndroid Build Coastguard Worker          || (C >= 'A' && C <= 'Z');
913*9880d681SAndroid Build Coastguard Worker }
914*9880d681SAndroid Build Coastguard Worker 
is_ns_word_char(const char C)915*9880d681SAndroid Build Coastguard Worker static bool is_ns_word_char(const char C) {
916*9880d681SAndroid Build Coastguard Worker   return    C == '-'
917*9880d681SAndroid Build Coastguard Worker          || (C >= 'a' && C <= 'z')
918*9880d681SAndroid Build Coastguard Worker          || (C >= 'A' && C <= 'Z');
919*9880d681SAndroid Build Coastguard Worker }
920*9880d681SAndroid Build Coastguard Worker 
scan_ns_uri_char()921*9880d681SAndroid Build Coastguard Worker StringRef Scanner::scan_ns_uri_char() {
922*9880d681SAndroid Build Coastguard Worker   StringRef::iterator Start = Current;
923*9880d681SAndroid Build Coastguard Worker   while (true) {
924*9880d681SAndroid Build Coastguard Worker     if (Current == End)
925*9880d681SAndroid Build Coastguard Worker       break;
926*9880d681SAndroid Build Coastguard Worker     if ((   *Current == '%'
927*9880d681SAndroid Build Coastguard Worker           && Current + 2 < End
928*9880d681SAndroid Build Coastguard Worker           && is_ns_hex_digit(*(Current + 1))
929*9880d681SAndroid Build Coastguard Worker           && is_ns_hex_digit(*(Current + 2)))
930*9880d681SAndroid Build Coastguard Worker         || is_ns_word_char(*Current)
931*9880d681SAndroid Build Coastguard Worker         || StringRef(Current, 1).find_first_of("#;/?:@&=+$,_.!~*'()[]")
932*9880d681SAndroid Build Coastguard Worker           != StringRef::npos) {
933*9880d681SAndroid Build Coastguard Worker       ++Current;
934*9880d681SAndroid Build Coastguard Worker       ++Column;
935*9880d681SAndroid Build Coastguard Worker     } else
936*9880d681SAndroid Build Coastguard Worker       break;
937*9880d681SAndroid Build Coastguard Worker   }
938*9880d681SAndroid Build Coastguard Worker   return StringRef(Start, Current - Start);
939*9880d681SAndroid Build Coastguard Worker }
940*9880d681SAndroid Build Coastguard Worker 
consume(uint32_t Expected)941*9880d681SAndroid Build Coastguard Worker bool Scanner::consume(uint32_t Expected) {
942*9880d681SAndroid Build Coastguard Worker   if (Expected >= 0x80)
943*9880d681SAndroid Build Coastguard Worker     report_fatal_error("Not dealing with this yet");
944*9880d681SAndroid Build Coastguard Worker   if (Current == End)
945*9880d681SAndroid Build Coastguard Worker     return false;
946*9880d681SAndroid Build Coastguard Worker   if (uint8_t(*Current) >= 0x80)
947*9880d681SAndroid Build Coastguard Worker     report_fatal_error("Not dealing with this yet");
948*9880d681SAndroid Build Coastguard Worker   if (uint8_t(*Current) == Expected) {
949*9880d681SAndroid Build Coastguard Worker     ++Current;
950*9880d681SAndroid Build Coastguard Worker     ++Column;
951*9880d681SAndroid Build Coastguard Worker     return true;
952*9880d681SAndroid Build Coastguard Worker   }
953*9880d681SAndroid Build Coastguard Worker   return false;
954*9880d681SAndroid Build Coastguard Worker }
955*9880d681SAndroid Build Coastguard Worker 
skip(uint32_t Distance)956*9880d681SAndroid Build Coastguard Worker void Scanner::skip(uint32_t Distance) {
957*9880d681SAndroid Build Coastguard Worker   Current += Distance;
958*9880d681SAndroid Build Coastguard Worker   Column += Distance;
959*9880d681SAndroid Build Coastguard Worker   assert(Current <= End && "Skipped past the end");
960*9880d681SAndroid Build Coastguard Worker }
961*9880d681SAndroid Build Coastguard Worker 
isBlankOrBreak(StringRef::iterator Position)962*9880d681SAndroid Build Coastguard Worker bool Scanner::isBlankOrBreak(StringRef::iterator Position) {
963*9880d681SAndroid Build Coastguard Worker   if (Position == End)
964*9880d681SAndroid Build Coastguard Worker     return false;
965*9880d681SAndroid Build Coastguard Worker   return *Position == ' ' || *Position == '\t' || *Position == '\r' ||
966*9880d681SAndroid Build Coastguard Worker          *Position == '\n';
967*9880d681SAndroid Build Coastguard Worker }
968*9880d681SAndroid Build Coastguard Worker 
consumeLineBreakIfPresent()969*9880d681SAndroid Build Coastguard Worker bool Scanner::consumeLineBreakIfPresent() {
970*9880d681SAndroid Build Coastguard Worker   auto Next = skip_b_break(Current);
971*9880d681SAndroid Build Coastguard Worker   if (Next == Current)
972*9880d681SAndroid Build Coastguard Worker     return false;
973*9880d681SAndroid Build Coastguard Worker   Column = 0;
974*9880d681SAndroid Build Coastguard Worker   ++Line;
975*9880d681SAndroid Build Coastguard Worker   Current = Next;
976*9880d681SAndroid Build Coastguard Worker   return true;
977*9880d681SAndroid Build Coastguard Worker }
978*9880d681SAndroid Build Coastguard Worker 
saveSimpleKeyCandidate(TokenQueueT::iterator Tok,unsigned AtColumn,bool IsRequired)979*9880d681SAndroid Build Coastguard Worker void Scanner::saveSimpleKeyCandidate( TokenQueueT::iterator Tok
980*9880d681SAndroid Build Coastguard Worker                                     , unsigned AtColumn
981*9880d681SAndroid Build Coastguard Worker                                     , bool IsRequired) {
982*9880d681SAndroid Build Coastguard Worker   if (IsSimpleKeyAllowed) {
983*9880d681SAndroid Build Coastguard Worker     SimpleKey SK;
984*9880d681SAndroid Build Coastguard Worker     SK.Tok = Tok;
985*9880d681SAndroid Build Coastguard Worker     SK.Line = Line;
986*9880d681SAndroid Build Coastguard Worker     SK.Column = AtColumn;
987*9880d681SAndroid Build Coastguard Worker     SK.IsRequired = IsRequired;
988*9880d681SAndroid Build Coastguard Worker     SK.FlowLevel = FlowLevel;
989*9880d681SAndroid Build Coastguard Worker     SimpleKeys.push_back(SK);
990*9880d681SAndroid Build Coastguard Worker   }
991*9880d681SAndroid Build Coastguard Worker }
992*9880d681SAndroid Build Coastguard Worker 
removeStaleSimpleKeyCandidates()993*9880d681SAndroid Build Coastguard Worker void Scanner::removeStaleSimpleKeyCandidates() {
994*9880d681SAndroid Build Coastguard Worker   for (SmallVectorImpl<SimpleKey>::iterator i = SimpleKeys.begin();
995*9880d681SAndroid Build Coastguard Worker                                             i != SimpleKeys.end();) {
996*9880d681SAndroid Build Coastguard Worker     if (i->Line != Line || i->Column + 1024 < Column) {
997*9880d681SAndroid Build Coastguard Worker       if (i->IsRequired)
998*9880d681SAndroid Build Coastguard Worker         setError( "Could not find expected : for simple key"
999*9880d681SAndroid Build Coastguard Worker                 , i->Tok->Range.begin());
1000*9880d681SAndroid Build Coastguard Worker       i = SimpleKeys.erase(i);
1001*9880d681SAndroid Build Coastguard Worker     } else
1002*9880d681SAndroid Build Coastguard Worker       ++i;
1003*9880d681SAndroid Build Coastguard Worker   }
1004*9880d681SAndroid Build Coastguard Worker }
1005*9880d681SAndroid Build Coastguard Worker 
removeSimpleKeyCandidatesOnFlowLevel(unsigned Level)1006*9880d681SAndroid Build Coastguard Worker void Scanner::removeSimpleKeyCandidatesOnFlowLevel(unsigned Level) {
1007*9880d681SAndroid Build Coastguard Worker   if (!SimpleKeys.empty() && (SimpleKeys.end() - 1)->FlowLevel == Level)
1008*9880d681SAndroid Build Coastguard Worker     SimpleKeys.pop_back();
1009*9880d681SAndroid Build Coastguard Worker }
1010*9880d681SAndroid Build Coastguard Worker 
unrollIndent(int ToColumn)1011*9880d681SAndroid Build Coastguard Worker bool Scanner::unrollIndent(int ToColumn) {
1012*9880d681SAndroid Build Coastguard Worker   Token T;
1013*9880d681SAndroid Build Coastguard Worker   // Indentation is ignored in flow.
1014*9880d681SAndroid Build Coastguard Worker   if (FlowLevel != 0)
1015*9880d681SAndroid Build Coastguard Worker     return true;
1016*9880d681SAndroid Build Coastguard Worker 
1017*9880d681SAndroid Build Coastguard Worker   while (Indent > ToColumn) {
1018*9880d681SAndroid Build Coastguard Worker     T.Kind = Token::TK_BlockEnd;
1019*9880d681SAndroid Build Coastguard Worker     T.Range = StringRef(Current, 1);
1020*9880d681SAndroid Build Coastguard Worker     TokenQueue.push_back(T);
1021*9880d681SAndroid Build Coastguard Worker     Indent = Indents.pop_back_val();
1022*9880d681SAndroid Build Coastguard Worker   }
1023*9880d681SAndroid Build Coastguard Worker 
1024*9880d681SAndroid Build Coastguard Worker   return true;
1025*9880d681SAndroid Build Coastguard Worker }
1026*9880d681SAndroid Build Coastguard Worker 
rollIndent(int ToColumn,Token::TokenKind Kind,TokenQueueT::iterator InsertPoint)1027*9880d681SAndroid Build Coastguard Worker bool Scanner::rollIndent( int ToColumn
1028*9880d681SAndroid Build Coastguard Worker                         , Token::TokenKind Kind
1029*9880d681SAndroid Build Coastguard Worker                         , TokenQueueT::iterator InsertPoint) {
1030*9880d681SAndroid Build Coastguard Worker   if (FlowLevel)
1031*9880d681SAndroid Build Coastguard Worker     return true;
1032*9880d681SAndroid Build Coastguard Worker   if (Indent < ToColumn) {
1033*9880d681SAndroid Build Coastguard Worker     Indents.push_back(Indent);
1034*9880d681SAndroid Build Coastguard Worker     Indent = ToColumn;
1035*9880d681SAndroid Build Coastguard Worker 
1036*9880d681SAndroid Build Coastguard Worker     Token T;
1037*9880d681SAndroid Build Coastguard Worker     T.Kind = Kind;
1038*9880d681SAndroid Build Coastguard Worker     T.Range = StringRef(Current, 0);
1039*9880d681SAndroid Build Coastguard Worker     TokenQueue.insert(InsertPoint, T);
1040*9880d681SAndroid Build Coastguard Worker   }
1041*9880d681SAndroid Build Coastguard Worker   return true;
1042*9880d681SAndroid Build Coastguard Worker }
1043*9880d681SAndroid Build Coastguard Worker 
skipComment()1044*9880d681SAndroid Build Coastguard Worker void Scanner::skipComment() {
1045*9880d681SAndroid Build Coastguard Worker   if (*Current != '#')
1046*9880d681SAndroid Build Coastguard Worker     return;
1047*9880d681SAndroid Build Coastguard Worker   while (true) {
1048*9880d681SAndroid Build Coastguard Worker     // This may skip more than one byte, thus Column is only incremented
1049*9880d681SAndroid Build Coastguard Worker     // for code points.
1050*9880d681SAndroid Build Coastguard Worker     StringRef::iterator I = skip_nb_char(Current);
1051*9880d681SAndroid Build Coastguard Worker     if (I == Current)
1052*9880d681SAndroid Build Coastguard Worker       break;
1053*9880d681SAndroid Build Coastguard Worker     Current = I;
1054*9880d681SAndroid Build Coastguard Worker     ++Column;
1055*9880d681SAndroid Build Coastguard Worker   }
1056*9880d681SAndroid Build Coastguard Worker }
1057*9880d681SAndroid Build Coastguard Worker 
scanToNextToken()1058*9880d681SAndroid Build Coastguard Worker void Scanner::scanToNextToken() {
1059*9880d681SAndroid Build Coastguard Worker   while (true) {
1060*9880d681SAndroid Build Coastguard Worker     while (*Current == ' ' || *Current == '\t') {
1061*9880d681SAndroid Build Coastguard Worker       skip(1);
1062*9880d681SAndroid Build Coastguard Worker     }
1063*9880d681SAndroid Build Coastguard Worker 
1064*9880d681SAndroid Build Coastguard Worker     skipComment();
1065*9880d681SAndroid Build Coastguard Worker 
1066*9880d681SAndroid Build Coastguard Worker     // Skip EOL.
1067*9880d681SAndroid Build Coastguard Worker     StringRef::iterator i = skip_b_break(Current);
1068*9880d681SAndroid Build Coastguard Worker     if (i == Current)
1069*9880d681SAndroid Build Coastguard Worker       break;
1070*9880d681SAndroid Build Coastguard Worker     Current = i;
1071*9880d681SAndroid Build Coastguard Worker     ++Line;
1072*9880d681SAndroid Build Coastguard Worker     Column = 0;
1073*9880d681SAndroid Build Coastguard Worker     // New lines may start a simple key.
1074*9880d681SAndroid Build Coastguard Worker     if (!FlowLevel)
1075*9880d681SAndroid Build Coastguard Worker       IsSimpleKeyAllowed = true;
1076*9880d681SAndroid Build Coastguard Worker   }
1077*9880d681SAndroid Build Coastguard Worker }
1078*9880d681SAndroid Build Coastguard Worker 
scanStreamStart()1079*9880d681SAndroid Build Coastguard Worker bool Scanner::scanStreamStart() {
1080*9880d681SAndroid Build Coastguard Worker   IsStartOfStream = false;
1081*9880d681SAndroid Build Coastguard Worker 
1082*9880d681SAndroid Build Coastguard Worker   EncodingInfo EI = getUnicodeEncoding(currentInput());
1083*9880d681SAndroid Build Coastguard Worker 
1084*9880d681SAndroid Build Coastguard Worker   Token T;
1085*9880d681SAndroid Build Coastguard Worker   T.Kind = Token::TK_StreamStart;
1086*9880d681SAndroid Build Coastguard Worker   T.Range = StringRef(Current, EI.second);
1087*9880d681SAndroid Build Coastguard Worker   TokenQueue.push_back(T);
1088*9880d681SAndroid Build Coastguard Worker   Current += EI.second;
1089*9880d681SAndroid Build Coastguard Worker   return true;
1090*9880d681SAndroid Build Coastguard Worker }
1091*9880d681SAndroid Build Coastguard Worker 
scanStreamEnd()1092*9880d681SAndroid Build Coastguard Worker bool Scanner::scanStreamEnd() {
1093*9880d681SAndroid Build Coastguard Worker   // Force an ending new line if one isn't present.
1094*9880d681SAndroid Build Coastguard Worker   if (Column != 0) {
1095*9880d681SAndroid Build Coastguard Worker     Column = 0;
1096*9880d681SAndroid Build Coastguard Worker     ++Line;
1097*9880d681SAndroid Build Coastguard Worker   }
1098*9880d681SAndroid Build Coastguard Worker 
1099*9880d681SAndroid Build Coastguard Worker   unrollIndent(-1);
1100*9880d681SAndroid Build Coastguard Worker   SimpleKeys.clear();
1101*9880d681SAndroid Build Coastguard Worker   IsSimpleKeyAllowed = false;
1102*9880d681SAndroid Build Coastguard Worker 
1103*9880d681SAndroid Build Coastguard Worker   Token T;
1104*9880d681SAndroid Build Coastguard Worker   T.Kind = Token::TK_StreamEnd;
1105*9880d681SAndroid Build Coastguard Worker   T.Range = StringRef(Current, 0);
1106*9880d681SAndroid Build Coastguard Worker   TokenQueue.push_back(T);
1107*9880d681SAndroid Build Coastguard Worker   return true;
1108*9880d681SAndroid Build Coastguard Worker }
1109*9880d681SAndroid Build Coastguard Worker 
scanDirective()1110*9880d681SAndroid Build Coastguard Worker bool Scanner::scanDirective() {
1111*9880d681SAndroid Build Coastguard Worker   // Reset the indentation level.
1112*9880d681SAndroid Build Coastguard Worker   unrollIndent(-1);
1113*9880d681SAndroid Build Coastguard Worker   SimpleKeys.clear();
1114*9880d681SAndroid Build Coastguard Worker   IsSimpleKeyAllowed = false;
1115*9880d681SAndroid Build Coastguard Worker 
1116*9880d681SAndroid Build Coastguard Worker   StringRef::iterator Start = Current;
1117*9880d681SAndroid Build Coastguard Worker   consume('%');
1118*9880d681SAndroid Build Coastguard Worker   StringRef::iterator NameStart = Current;
1119*9880d681SAndroid Build Coastguard Worker   Current = skip_while(&Scanner::skip_ns_char, Current);
1120*9880d681SAndroid Build Coastguard Worker   StringRef Name(NameStart, Current - NameStart);
1121*9880d681SAndroid Build Coastguard Worker   Current = skip_while(&Scanner::skip_s_white, Current);
1122*9880d681SAndroid Build Coastguard Worker 
1123*9880d681SAndroid Build Coastguard Worker   Token T;
1124*9880d681SAndroid Build Coastguard Worker   if (Name == "YAML") {
1125*9880d681SAndroid Build Coastguard Worker     Current = skip_while(&Scanner::skip_ns_char, Current);
1126*9880d681SAndroid Build Coastguard Worker     T.Kind = Token::TK_VersionDirective;
1127*9880d681SAndroid Build Coastguard Worker     T.Range = StringRef(Start, Current - Start);
1128*9880d681SAndroid Build Coastguard Worker     TokenQueue.push_back(T);
1129*9880d681SAndroid Build Coastguard Worker     return true;
1130*9880d681SAndroid Build Coastguard Worker   } else if(Name == "TAG") {
1131*9880d681SAndroid Build Coastguard Worker     Current = skip_while(&Scanner::skip_ns_char, Current);
1132*9880d681SAndroid Build Coastguard Worker     Current = skip_while(&Scanner::skip_s_white, Current);
1133*9880d681SAndroid Build Coastguard Worker     Current = skip_while(&Scanner::skip_ns_char, Current);
1134*9880d681SAndroid Build Coastguard Worker     T.Kind = Token::TK_TagDirective;
1135*9880d681SAndroid Build Coastguard Worker     T.Range = StringRef(Start, Current - Start);
1136*9880d681SAndroid Build Coastguard Worker     TokenQueue.push_back(T);
1137*9880d681SAndroid Build Coastguard Worker     return true;
1138*9880d681SAndroid Build Coastguard Worker   }
1139*9880d681SAndroid Build Coastguard Worker   return false;
1140*9880d681SAndroid Build Coastguard Worker }
1141*9880d681SAndroid Build Coastguard Worker 
scanDocumentIndicator(bool IsStart)1142*9880d681SAndroid Build Coastguard Worker bool Scanner::scanDocumentIndicator(bool IsStart) {
1143*9880d681SAndroid Build Coastguard Worker   unrollIndent(-1);
1144*9880d681SAndroid Build Coastguard Worker   SimpleKeys.clear();
1145*9880d681SAndroid Build Coastguard Worker   IsSimpleKeyAllowed = false;
1146*9880d681SAndroid Build Coastguard Worker 
1147*9880d681SAndroid Build Coastguard Worker   Token T;
1148*9880d681SAndroid Build Coastguard Worker   T.Kind = IsStart ? Token::TK_DocumentStart : Token::TK_DocumentEnd;
1149*9880d681SAndroid Build Coastguard Worker   T.Range = StringRef(Current, 3);
1150*9880d681SAndroid Build Coastguard Worker   skip(3);
1151*9880d681SAndroid Build Coastguard Worker   TokenQueue.push_back(T);
1152*9880d681SAndroid Build Coastguard Worker   return true;
1153*9880d681SAndroid Build Coastguard Worker }
1154*9880d681SAndroid Build Coastguard Worker 
scanFlowCollectionStart(bool IsSequence)1155*9880d681SAndroid Build Coastguard Worker bool Scanner::scanFlowCollectionStart(bool IsSequence) {
1156*9880d681SAndroid Build Coastguard Worker   Token T;
1157*9880d681SAndroid Build Coastguard Worker   T.Kind = IsSequence ? Token::TK_FlowSequenceStart
1158*9880d681SAndroid Build Coastguard Worker                       : Token::TK_FlowMappingStart;
1159*9880d681SAndroid Build Coastguard Worker   T.Range = StringRef(Current, 1);
1160*9880d681SAndroid Build Coastguard Worker   skip(1);
1161*9880d681SAndroid Build Coastguard Worker   TokenQueue.push_back(T);
1162*9880d681SAndroid Build Coastguard Worker 
1163*9880d681SAndroid Build Coastguard Worker   // [ and { may begin a simple key.
1164*9880d681SAndroid Build Coastguard Worker   saveSimpleKeyCandidate(--TokenQueue.end(), Column - 1, false);
1165*9880d681SAndroid Build Coastguard Worker 
1166*9880d681SAndroid Build Coastguard Worker   // And may also be followed by a simple key.
1167*9880d681SAndroid Build Coastguard Worker   IsSimpleKeyAllowed = true;
1168*9880d681SAndroid Build Coastguard Worker   ++FlowLevel;
1169*9880d681SAndroid Build Coastguard Worker   return true;
1170*9880d681SAndroid Build Coastguard Worker }
1171*9880d681SAndroid Build Coastguard Worker 
scanFlowCollectionEnd(bool IsSequence)1172*9880d681SAndroid Build Coastguard Worker bool Scanner::scanFlowCollectionEnd(bool IsSequence) {
1173*9880d681SAndroid Build Coastguard Worker   removeSimpleKeyCandidatesOnFlowLevel(FlowLevel);
1174*9880d681SAndroid Build Coastguard Worker   IsSimpleKeyAllowed = false;
1175*9880d681SAndroid Build Coastguard Worker   Token T;
1176*9880d681SAndroid Build Coastguard Worker   T.Kind = IsSequence ? Token::TK_FlowSequenceEnd
1177*9880d681SAndroid Build Coastguard Worker                       : Token::TK_FlowMappingEnd;
1178*9880d681SAndroid Build Coastguard Worker   T.Range = StringRef(Current, 1);
1179*9880d681SAndroid Build Coastguard Worker   skip(1);
1180*9880d681SAndroid Build Coastguard Worker   TokenQueue.push_back(T);
1181*9880d681SAndroid Build Coastguard Worker   if (FlowLevel)
1182*9880d681SAndroid Build Coastguard Worker     --FlowLevel;
1183*9880d681SAndroid Build Coastguard Worker   return true;
1184*9880d681SAndroid Build Coastguard Worker }
1185*9880d681SAndroid Build Coastguard Worker 
scanFlowEntry()1186*9880d681SAndroid Build Coastguard Worker bool Scanner::scanFlowEntry() {
1187*9880d681SAndroid Build Coastguard Worker   removeSimpleKeyCandidatesOnFlowLevel(FlowLevel);
1188*9880d681SAndroid Build Coastguard Worker   IsSimpleKeyAllowed = true;
1189*9880d681SAndroid Build Coastguard Worker   Token T;
1190*9880d681SAndroid Build Coastguard Worker   T.Kind = Token::TK_FlowEntry;
1191*9880d681SAndroid Build Coastguard Worker   T.Range = StringRef(Current, 1);
1192*9880d681SAndroid Build Coastguard Worker   skip(1);
1193*9880d681SAndroid Build Coastguard Worker   TokenQueue.push_back(T);
1194*9880d681SAndroid Build Coastguard Worker   return true;
1195*9880d681SAndroid Build Coastguard Worker }
1196*9880d681SAndroid Build Coastguard Worker 
scanBlockEntry()1197*9880d681SAndroid Build Coastguard Worker bool Scanner::scanBlockEntry() {
1198*9880d681SAndroid Build Coastguard Worker   rollIndent(Column, Token::TK_BlockSequenceStart, TokenQueue.end());
1199*9880d681SAndroid Build Coastguard Worker   removeSimpleKeyCandidatesOnFlowLevel(FlowLevel);
1200*9880d681SAndroid Build Coastguard Worker   IsSimpleKeyAllowed = true;
1201*9880d681SAndroid Build Coastguard Worker   Token T;
1202*9880d681SAndroid Build Coastguard Worker   T.Kind = Token::TK_BlockEntry;
1203*9880d681SAndroid Build Coastguard Worker   T.Range = StringRef(Current, 1);
1204*9880d681SAndroid Build Coastguard Worker   skip(1);
1205*9880d681SAndroid Build Coastguard Worker   TokenQueue.push_back(T);
1206*9880d681SAndroid Build Coastguard Worker   return true;
1207*9880d681SAndroid Build Coastguard Worker }
1208*9880d681SAndroid Build Coastguard Worker 
scanKey()1209*9880d681SAndroid Build Coastguard Worker bool Scanner::scanKey() {
1210*9880d681SAndroid Build Coastguard Worker   if (!FlowLevel)
1211*9880d681SAndroid Build Coastguard Worker     rollIndent(Column, Token::TK_BlockMappingStart, TokenQueue.end());
1212*9880d681SAndroid Build Coastguard Worker 
1213*9880d681SAndroid Build Coastguard Worker   removeSimpleKeyCandidatesOnFlowLevel(FlowLevel);
1214*9880d681SAndroid Build Coastguard Worker   IsSimpleKeyAllowed = !FlowLevel;
1215*9880d681SAndroid Build Coastguard Worker 
1216*9880d681SAndroid Build Coastguard Worker   Token T;
1217*9880d681SAndroid Build Coastguard Worker   T.Kind = Token::TK_Key;
1218*9880d681SAndroid Build Coastguard Worker   T.Range = StringRef(Current, 1);
1219*9880d681SAndroid Build Coastguard Worker   skip(1);
1220*9880d681SAndroid Build Coastguard Worker   TokenQueue.push_back(T);
1221*9880d681SAndroid Build Coastguard Worker   return true;
1222*9880d681SAndroid Build Coastguard Worker }
1223*9880d681SAndroid Build Coastguard Worker 
scanValue()1224*9880d681SAndroid Build Coastguard Worker bool Scanner::scanValue() {
1225*9880d681SAndroid Build Coastguard Worker   // If the previous token could have been a simple key, insert the key token
1226*9880d681SAndroid Build Coastguard Worker   // into the token queue.
1227*9880d681SAndroid Build Coastguard Worker   if (!SimpleKeys.empty()) {
1228*9880d681SAndroid Build Coastguard Worker     SimpleKey SK = SimpleKeys.pop_back_val();
1229*9880d681SAndroid Build Coastguard Worker     Token T;
1230*9880d681SAndroid Build Coastguard Worker     T.Kind = Token::TK_Key;
1231*9880d681SAndroid Build Coastguard Worker     T.Range = SK.Tok->Range;
1232*9880d681SAndroid Build Coastguard Worker     TokenQueueT::iterator i, e;
1233*9880d681SAndroid Build Coastguard Worker     for (i = TokenQueue.begin(), e = TokenQueue.end(); i != e; ++i) {
1234*9880d681SAndroid Build Coastguard Worker       if (i == SK.Tok)
1235*9880d681SAndroid Build Coastguard Worker         break;
1236*9880d681SAndroid Build Coastguard Worker     }
1237*9880d681SAndroid Build Coastguard Worker     assert(i != e && "SimpleKey not in token queue!");
1238*9880d681SAndroid Build Coastguard Worker     i = TokenQueue.insert(i, T);
1239*9880d681SAndroid Build Coastguard Worker 
1240*9880d681SAndroid Build Coastguard Worker     // We may also need to add a Block-Mapping-Start token.
1241*9880d681SAndroid Build Coastguard Worker     rollIndent(SK.Column, Token::TK_BlockMappingStart, i);
1242*9880d681SAndroid Build Coastguard Worker 
1243*9880d681SAndroid Build Coastguard Worker     IsSimpleKeyAllowed = false;
1244*9880d681SAndroid Build Coastguard Worker   } else {
1245*9880d681SAndroid Build Coastguard Worker     if (!FlowLevel)
1246*9880d681SAndroid Build Coastguard Worker       rollIndent(Column, Token::TK_BlockMappingStart, TokenQueue.end());
1247*9880d681SAndroid Build Coastguard Worker     IsSimpleKeyAllowed = !FlowLevel;
1248*9880d681SAndroid Build Coastguard Worker   }
1249*9880d681SAndroid Build Coastguard Worker 
1250*9880d681SAndroid Build Coastguard Worker   Token T;
1251*9880d681SAndroid Build Coastguard Worker   T.Kind = Token::TK_Value;
1252*9880d681SAndroid Build Coastguard Worker   T.Range = StringRef(Current, 1);
1253*9880d681SAndroid Build Coastguard Worker   skip(1);
1254*9880d681SAndroid Build Coastguard Worker   TokenQueue.push_back(T);
1255*9880d681SAndroid Build Coastguard Worker   return true;
1256*9880d681SAndroid Build Coastguard Worker }
1257*9880d681SAndroid Build Coastguard Worker 
1258*9880d681SAndroid Build Coastguard Worker // Forbidding inlining improves performance by roughly 20%.
1259*9880d681SAndroid Build Coastguard Worker // FIXME: Remove once llvm optimizes this to the faster version without hints.
1260*9880d681SAndroid Build Coastguard Worker LLVM_ATTRIBUTE_NOINLINE static bool
1261*9880d681SAndroid Build Coastguard Worker wasEscaped(StringRef::iterator First, StringRef::iterator Position);
1262*9880d681SAndroid Build Coastguard Worker 
1263*9880d681SAndroid Build Coastguard Worker // Returns whether a character at 'Position' was escaped with a leading '\'.
1264*9880d681SAndroid Build Coastguard Worker // 'First' specifies the position of the first character in the string.
wasEscaped(StringRef::iterator First,StringRef::iterator Position)1265*9880d681SAndroid Build Coastguard Worker static bool wasEscaped(StringRef::iterator First,
1266*9880d681SAndroid Build Coastguard Worker                        StringRef::iterator Position) {
1267*9880d681SAndroid Build Coastguard Worker   assert(Position - 1 >= First);
1268*9880d681SAndroid Build Coastguard Worker   StringRef::iterator I = Position - 1;
1269*9880d681SAndroid Build Coastguard Worker   // We calculate the number of consecutive '\'s before the current position
1270*9880d681SAndroid Build Coastguard Worker   // by iterating backwards through our string.
1271*9880d681SAndroid Build Coastguard Worker   while (I >= First && *I == '\\') --I;
1272*9880d681SAndroid Build Coastguard Worker   // (Position - 1 - I) now contains the number of '\'s before the current
1273*9880d681SAndroid Build Coastguard Worker   // position. If it is odd, the character at 'Position' was escaped.
1274*9880d681SAndroid Build Coastguard Worker   return (Position - 1 - I) % 2 == 1;
1275*9880d681SAndroid Build Coastguard Worker }
1276*9880d681SAndroid Build Coastguard Worker 
scanFlowScalar(bool IsDoubleQuoted)1277*9880d681SAndroid Build Coastguard Worker bool Scanner::scanFlowScalar(bool IsDoubleQuoted) {
1278*9880d681SAndroid Build Coastguard Worker   StringRef::iterator Start = Current;
1279*9880d681SAndroid Build Coastguard Worker   unsigned ColStart = Column;
1280*9880d681SAndroid Build Coastguard Worker   if (IsDoubleQuoted) {
1281*9880d681SAndroid Build Coastguard Worker     do {
1282*9880d681SAndroid Build Coastguard Worker       ++Current;
1283*9880d681SAndroid Build Coastguard Worker       while (Current != End && *Current != '"')
1284*9880d681SAndroid Build Coastguard Worker         ++Current;
1285*9880d681SAndroid Build Coastguard Worker       // Repeat until the previous character was not a '\' or was an escaped
1286*9880d681SAndroid Build Coastguard Worker       // backslash.
1287*9880d681SAndroid Build Coastguard Worker     } while (   Current != End
1288*9880d681SAndroid Build Coastguard Worker              && *(Current - 1) == '\\'
1289*9880d681SAndroid Build Coastguard Worker              && wasEscaped(Start + 1, Current));
1290*9880d681SAndroid Build Coastguard Worker   } else {
1291*9880d681SAndroid Build Coastguard Worker     skip(1);
1292*9880d681SAndroid Build Coastguard Worker     while (true) {
1293*9880d681SAndroid Build Coastguard Worker       // Skip a ' followed by another '.
1294*9880d681SAndroid Build Coastguard Worker       if (Current + 1 < End && *Current == '\'' && *(Current + 1) == '\'') {
1295*9880d681SAndroid Build Coastguard Worker         skip(2);
1296*9880d681SAndroid Build Coastguard Worker         continue;
1297*9880d681SAndroid Build Coastguard Worker       } else if (*Current == '\'')
1298*9880d681SAndroid Build Coastguard Worker         break;
1299*9880d681SAndroid Build Coastguard Worker       StringRef::iterator i = skip_nb_char(Current);
1300*9880d681SAndroid Build Coastguard Worker       if (i == Current) {
1301*9880d681SAndroid Build Coastguard Worker         i = skip_b_break(Current);
1302*9880d681SAndroid Build Coastguard Worker         if (i == Current)
1303*9880d681SAndroid Build Coastguard Worker           break;
1304*9880d681SAndroid Build Coastguard Worker         Current = i;
1305*9880d681SAndroid Build Coastguard Worker         Column = 0;
1306*9880d681SAndroid Build Coastguard Worker         ++Line;
1307*9880d681SAndroid Build Coastguard Worker       } else {
1308*9880d681SAndroid Build Coastguard Worker         if (i == End)
1309*9880d681SAndroid Build Coastguard Worker           break;
1310*9880d681SAndroid Build Coastguard Worker         Current = i;
1311*9880d681SAndroid Build Coastguard Worker         ++Column;
1312*9880d681SAndroid Build Coastguard Worker       }
1313*9880d681SAndroid Build Coastguard Worker     }
1314*9880d681SAndroid Build Coastguard Worker   }
1315*9880d681SAndroid Build Coastguard Worker 
1316*9880d681SAndroid Build Coastguard Worker   if (Current == End) {
1317*9880d681SAndroid Build Coastguard Worker     setError("Expected quote at end of scalar", Current);
1318*9880d681SAndroid Build Coastguard Worker     return false;
1319*9880d681SAndroid Build Coastguard Worker   }
1320*9880d681SAndroid Build Coastguard Worker 
1321*9880d681SAndroid Build Coastguard Worker   skip(1); // Skip ending quote.
1322*9880d681SAndroid Build Coastguard Worker   Token T;
1323*9880d681SAndroid Build Coastguard Worker   T.Kind = Token::TK_Scalar;
1324*9880d681SAndroid Build Coastguard Worker   T.Range = StringRef(Start, Current - Start);
1325*9880d681SAndroid Build Coastguard Worker   TokenQueue.push_back(T);
1326*9880d681SAndroid Build Coastguard Worker 
1327*9880d681SAndroid Build Coastguard Worker   saveSimpleKeyCandidate(--TokenQueue.end(), ColStart, false);
1328*9880d681SAndroid Build Coastguard Worker 
1329*9880d681SAndroid Build Coastguard Worker   IsSimpleKeyAllowed = false;
1330*9880d681SAndroid Build Coastguard Worker 
1331*9880d681SAndroid Build Coastguard Worker   return true;
1332*9880d681SAndroid Build Coastguard Worker }
1333*9880d681SAndroid Build Coastguard Worker 
scanPlainScalar()1334*9880d681SAndroid Build Coastguard Worker bool Scanner::scanPlainScalar() {
1335*9880d681SAndroid Build Coastguard Worker   StringRef::iterator Start = Current;
1336*9880d681SAndroid Build Coastguard Worker   unsigned ColStart = Column;
1337*9880d681SAndroid Build Coastguard Worker   unsigned LeadingBlanks = 0;
1338*9880d681SAndroid Build Coastguard Worker   assert(Indent >= -1 && "Indent must be >= -1 !");
1339*9880d681SAndroid Build Coastguard Worker   unsigned indent = static_cast<unsigned>(Indent + 1);
1340*9880d681SAndroid Build Coastguard Worker   while (true) {
1341*9880d681SAndroid Build Coastguard Worker     if (*Current == '#')
1342*9880d681SAndroid Build Coastguard Worker       break;
1343*9880d681SAndroid Build Coastguard Worker 
1344*9880d681SAndroid Build Coastguard Worker     while (!isBlankOrBreak(Current)) {
1345*9880d681SAndroid Build Coastguard Worker       if (  FlowLevel && *Current == ':'
1346*9880d681SAndroid Build Coastguard Worker           && !(isBlankOrBreak(Current + 1) || *(Current + 1) == ',')) {
1347*9880d681SAndroid Build Coastguard Worker         setError("Found unexpected ':' while scanning a plain scalar", Current);
1348*9880d681SAndroid Build Coastguard Worker         return false;
1349*9880d681SAndroid Build Coastguard Worker       }
1350*9880d681SAndroid Build Coastguard Worker 
1351*9880d681SAndroid Build Coastguard Worker       // Check for the end of the plain scalar.
1352*9880d681SAndroid Build Coastguard Worker       if (  (*Current == ':' && isBlankOrBreak(Current + 1))
1353*9880d681SAndroid Build Coastguard Worker           || (  FlowLevel
1354*9880d681SAndroid Build Coastguard Worker           && (StringRef(Current, 1).find_first_of(",:?[]{}")
1355*9880d681SAndroid Build Coastguard Worker               != StringRef::npos)))
1356*9880d681SAndroid Build Coastguard Worker         break;
1357*9880d681SAndroid Build Coastguard Worker 
1358*9880d681SAndroid Build Coastguard Worker       StringRef::iterator i = skip_nb_char(Current);
1359*9880d681SAndroid Build Coastguard Worker       if (i == Current)
1360*9880d681SAndroid Build Coastguard Worker         break;
1361*9880d681SAndroid Build Coastguard Worker       Current = i;
1362*9880d681SAndroid Build Coastguard Worker       ++Column;
1363*9880d681SAndroid Build Coastguard Worker     }
1364*9880d681SAndroid Build Coastguard Worker 
1365*9880d681SAndroid Build Coastguard Worker     // Are we at the end?
1366*9880d681SAndroid Build Coastguard Worker     if (!isBlankOrBreak(Current))
1367*9880d681SAndroid Build Coastguard Worker       break;
1368*9880d681SAndroid Build Coastguard Worker 
1369*9880d681SAndroid Build Coastguard Worker     // Eat blanks.
1370*9880d681SAndroid Build Coastguard Worker     StringRef::iterator Tmp = Current;
1371*9880d681SAndroid Build Coastguard Worker     while (isBlankOrBreak(Tmp)) {
1372*9880d681SAndroid Build Coastguard Worker       StringRef::iterator i = skip_s_white(Tmp);
1373*9880d681SAndroid Build Coastguard Worker       if (i != Tmp) {
1374*9880d681SAndroid Build Coastguard Worker         if (LeadingBlanks && (Column < indent) && *Tmp == '\t') {
1375*9880d681SAndroid Build Coastguard Worker           setError("Found invalid tab character in indentation", Tmp);
1376*9880d681SAndroid Build Coastguard Worker           return false;
1377*9880d681SAndroid Build Coastguard Worker         }
1378*9880d681SAndroid Build Coastguard Worker         Tmp = i;
1379*9880d681SAndroid Build Coastguard Worker         ++Column;
1380*9880d681SAndroid Build Coastguard Worker       } else {
1381*9880d681SAndroid Build Coastguard Worker         i = skip_b_break(Tmp);
1382*9880d681SAndroid Build Coastguard Worker         if (!LeadingBlanks)
1383*9880d681SAndroid Build Coastguard Worker           LeadingBlanks = 1;
1384*9880d681SAndroid Build Coastguard Worker         Tmp = i;
1385*9880d681SAndroid Build Coastguard Worker         Column = 0;
1386*9880d681SAndroid Build Coastguard Worker         ++Line;
1387*9880d681SAndroid Build Coastguard Worker       }
1388*9880d681SAndroid Build Coastguard Worker     }
1389*9880d681SAndroid Build Coastguard Worker 
1390*9880d681SAndroid Build Coastguard Worker     if (!FlowLevel && Column < indent)
1391*9880d681SAndroid Build Coastguard Worker       break;
1392*9880d681SAndroid Build Coastguard Worker 
1393*9880d681SAndroid Build Coastguard Worker     Current = Tmp;
1394*9880d681SAndroid Build Coastguard Worker   }
1395*9880d681SAndroid Build Coastguard Worker   if (Start == Current) {
1396*9880d681SAndroid Build Coastguard Worker     setError("Got empty plain scalar", Start);
1397*9880d681SAndroid Build Coastguard Worker     return false;
1398*9880d681SAndroid Build Coastguard Worker   }
1399*9880d681SAndroid Build Coastguard Worker   Token T;
1400*9880d681SAndroid Build Coastguard Worker   T.Kind = Token::TK_Scalar;
1401*9880d681SAndroid Build Coastguard Worker   T.Range = StringRef(Start, Current - Start);
1402*9880d681SAndroid Build Coastguard Worker   TokenQueue.push_back(T);
1403*9880d681SAndroid Build Coastguard Worker 
1404*9880d681SAndroid Build Coastguard Worker   // Plain scalars can be simple keys.
1405*9880d681SAndroid Build Coastguard Worker   saveSimpleKeyCandidate(--TokenQueue.end(), ColStart, false);
1406*9880d681SAndroid Build Coastguard Worker 
1407*9880d681SAndroid Build Coastguard Worker   IsSimpleKeyAllowed = false;
1408*9880d681SAndroid Build Coastguard Worker 
1409*9880d681SAndroid Build Coastguard Worker   return true;
1410*9880d681SAndroid Build Coastguard Worker }
1411*9880d681SAndroid Build Coastguard Worker 
scanAliasOrAnchor(bool IsAlias)1412*9880d681SAndroid Build Coastguard Worker bool Scanner::scanAliasOrAnchor(bool IsAlias) {
1413*9880d681SAndroid Build Coastguard Worker   StringRef::iterator Start = Current;
1414*9880d681SAndroid Build Coastguard Worker   unsigned ColStart = Column;
1415*9880d681SAndroid Build Coastguard Worker   skip(1);
1416*9880d681SAndroid Build Coastguard Worker   while(true) {
1417*9880d681SAndroid Build Coastguard Worker     if (   *Current == '[' || *Current == ']'
1418*9880d681SAndroid Build Coastguard Worker         || *Current == '{' || *Current == '}'
1419*9880d681SAndroid Build Coastguard Worker         || *Current == ','
1420*9880d681SAndroid Build Coastguard Worker         || *Current == ':')
1421*9880d681SAndroid Build Coastguard Worker       break;
1422*9880d681SAndroid Build Coastguard Worker     StringRef::iterator i = skip_ns_char(Current);
1423*9880d681SAndroid Build Coastguard Worker     if (i == Current)
1424*9880d681SAndroid Build Coastguard Worker       break;
1425*9880d681SAndroid Build Coastguard Worker     Current = i;
1426*9880d681SAndroid Build Coastguard Worker     ++Column;
1427*9880d681SAndroid Build Coastguard Worker   }
1428*9880d681SAndroid Build Coastguard Worker 
1429*9880d681SAndroid Build Coastguard Worker   if (Start == Current) {
1430*9880d681SAndroid Build Coastguard Worker     setError("Got empty alias or anchor", Start);
1431*9880d681SAndroid Build Coastguard Worker     return false;
1432*9880d681SAndroid Build Coastguard Worker   }
1433*9880d681SAndroid Build Coastguard Worker 
1434*9880d681SAndroid Build Coastguard Worker   Token T;
1435*9880d681SAndroid Build Coastguard Worker   T.Kind = IsAlias ? Token::TK_Alias : Token::TK_Anchor;
1436*9880d681SAndroid Build Coastguard Worker   T.Range = StringRef(Start, Current - Start);
1437*9880d681SAndroid Build Coastguard Worker   TokenQueue.push_back(T);
1438*9880d681SAndroid Build Coastguard Worker 
1439*9880d681SAndroid Build Coastguard Worker   // Alias and anchors can be simple keys.
1440*9880d681SAndroid Build Coastguard Worker   saveSimpleKeyCandidate(--TokenQueue.end(), ColStart, false);
1441*9880d681SAndroid Build Coastguard Worker 
1442*9880d681SAndroid Build Coastguard Worker   IsSimpleKeyAllowed = false;
1443*9880d681SAndroid Build Coastguard Worker 
1444*9880d681SAndroid Build Coastguard Worker   return true;
1445*9880d681SAndroid Build Coastguard Worker }
1446*9880d681SAndroid Build Coastguard Worker 
scanBlockChompingIndicator()1447*9880d681SAndroid Build Coastguard Worker char Scanner::scanBlockChompingIndicator() {
1448*9880d681SAndroid Build Coastguard Worker   char Indicator = ' ';
1449*9880d681SAndroid Build Coastguard Worker   if (Current != End && (*Current == '+' || *Current == '-')) {
1450*9880d681SAndroid Build Coastguard Worker     Indicator = *Current;
1451*9880d681SAndroid Build Coastguard Worker     skip(1);
1452*9880d681SAndroid Build Coastguard Worker   }
1453*9880d681SAndroid Build Coastguard Worker   return Indicator;
1454*9880d681SAndroid Build Coastguard Worker }
1455*9880d681SAndroid Build Coastguard Worker 
1456*9880d681SAndroid Build Coastguard Worker /// Get the number of line breaks after chomping.
1457*9880d681SAndroid Build Coastguard Worker ///
1458*9880d681SAndroid Build Coastguard Worker /// Return the number of trailing line breaks to emit, depending on
1459*9880d681SAndroid Build Coastguard Worker /// \p ChompingIndicator.
getChompedLineBreaks(char ChompingIndicator,unsigned LineBreaks,StringRef Str)1460*9880d681SAndroid Build Coastguard Worker static unsigned getChompedLineBreaks(char ChompingIndicator,
1461*9880d681SAndroid Build Coastguard Worker                                      unsigned LineBreaks, StringRef Str) {
1462*9880d681SAndroid Build Coastguard Worker   if (ChompingIndicator == '-') // Strip all line breaks.
1463*9880d681SAndroid Build Coastguard Worker     return 0;
1464*9880d681SAndroid Build Coastguard Worker   if (ChompingIndicator == '+') // Keep all line breaks.
1465*9880d681SAndroid Build Coastguard Worker     return LineBreaks;
1466*9880d681SAndroid Build Coastguard Worker   // Clip trailing lines.
1467*9880d681SAndroid Build Coastguard Worker   return Str.empty() ? 0 : 1;
1468*9880d681SAndroid Build Coastguard Worker }
1469*9880d681SAndroid Build Coastguard Worker 
scanBlockIndentationIndicator()1470*9880d681SAndroid Build Coastguard Worker unsigned Scanner::scanBlockIndentationIndicator() {
1471*9880d681SAndroid Build Coastguard Worker   unsigned Indent = 0;
1472*9880d681SAndroid Build Coastguard Worker   if (Current != End && (*Current >= '1' && *Current <= '9')) {
1473*9880d681SAndroid Build Coastguard Worker     Indent = unsigned(*Current - '0');
1474*9880d681SAndroid Build Coastguard Worker     skip(1);
1475*9880d681SAndroid Build Coastguard Worker   }
1476*9880d681SAndroid Build Coastguard Worker   return Indent;
1477*9880d681SAndroid Build Coastguard Worker }
1478*9880d681SAndroid Build Coastguard Worker 
scanBlockScalarHeader(char & ChompingIndicator,unsigned & IndentIndicator,bool & IsDone)1479*9880d681SAndroid Build Coastguard Worker bool Scanner::scanBlockScalarHeader(char &ChompingIndicator,
1480*9880d681SAndroid Build Coastguard Worker                                     unsigned &IndentIndicator, bool &IsDone) {
1481*9880d681SAndroid Build Coastguard Worker   auto Start = Current;
1482*9880d681SAndroid Build Coastguard Worker 
1483*9880d681SAndroid Build Coastguard Worker   ChompingIndicator = scanBlockChompingIndicator();
1484*9880d681SAndroid Build Coastguard Worker   IndentIndicator = scanBlockIndentationIndicator();
1485*9880d681SAndroid Build Coastguard Worker   // Check for the chomping indicator once again.
1486*9880d681SAndroid Build Coastguard Worker   if (ChompingIndicator == ' ')
1487*9880d681SAndroid Build Coastguard Worker     ChompingIndicator = scanBlockChompingIndicator();
1488*9880d681SAndroid Build Coastguard Worker   Current = skip_while(&Scanner::skip_s_white, Current);
1489*9880d681SAndroid Build Coastguard Worker   skipComment();
1490*9880d681SAndroid Build Coastguard Worker 
1491*9880d681SAndroid Build Coastguard Worker   if (Current == End) { // EOF, we have an empty scalar.
1492*9880d681SAndroid Build Coastguard Worker     Token T;
1493*9880d681SAndroid Build Coastguard Worker     T.Kind = Token::TK_BlockScalar;
1494*9880d681SAndroid Build Coastguard Worker     T.Range = StringRef(Start, Current - Start);
1495*9880d681SAndroid Build Coastguard Worker     TokenQueue.push_back(T);
1496*9880d681SAndroid Build Coastguard Worker     IsDone = true;
1497*9880d681SAndroid Build Coastguard Worker     return true;
1498*9880d681SAndroid Build Coastguard Worker   }
1499*9880d681SAndroid Build Coastguard Worker 
1500*9880d681SAndroid Build Coastguard Worker   if (!consumeLineBreakIfPresent()) {
1501*9880d681SAndroid Build Coastguard Worker     setError("Expected a line break after block scalar header", Current);
1502*9880d681SAndroid Build Coastguard Worker     return false;
1503*9880d681SAndroid Build Coastguard Worker   }
1504*9880d681SAndroid Build Coastguard Worker   return true;
1505*9880d681SAndroid Build Coastguard Worker }
1506*9880d681SAndroid Build Coastguard Worker 
findBlockScalarIndent(unsigned & BlockIndent,unsigned BlockExitIndent,unsigned & LineBreaks,bool & IsDone)1507*9880d681SAndroid Build Coastguard Worker bool Scanner::findBlockScalarIndent(unsigned &BlockIndent,
1508*9880d681SAndroid Build Coastguard Worker                                     unsigned BlockExitIndent,
1509*9880d681SAndroid Build Coastguard Worker                                     unsigned &LineBreaks, bool &IsDone) {
1510*9880d681SAndroid Build Coastguard Worker   unsigned MaxAllSpaceLineCharacters = 0;
1511*9880d681SAndroid Build Coastguard Worker   StringRef::iterator LongestAllSpaceLine;
1512*9880d681SAndroid Build Coastguard Worker 
1513*9880d681SAndroid Build Coastguard Worker   while (true) {
1514*9880d681SAndroid Build Coastguard Worker     advanceWhile(&Scanner::skip_s_space);
1515*9880d681SAndroid Build Coastguard Worker     if (skip_nb_char(Current) != Current) {
1516*9880d681SAndroid Build Coastguard Worker       // This line isn't empty, so try and find the indentation.
1517*9880d681SAndroid Build Coastguard Worker       if (Column <= BlockExitIndent) { // End of the block literal.
1518*9880d681SAndroid Build Coastguard Worker         IsDone = true;
1519*9880d681SAndroid Build Coastguard Worker         return true;
1520*9880d681SAndroid Build Coastguard Worker       }
1521*9880d681SAndroid Build Coastguard Worker       // We found the block's indentation.
1522*9880d681SAndroid Build Coastguard Worker       BlockIndent = Column;
1523*9880d681SAndroid Build Coastguard Worker       if (MaxAllSpaceLineCharacters > BlockIndent) {
1524*9880d681SAndroid Build Coastguard Worker         setError(
1525*9880d681SAndroid Build Coastguard Worker             "Leading all-spaces line must be smaller than the block indent",
1526*9880d681SAndroid Build Coastguard Worker             LongestAllSpaceLine);
1527*9880d681SAndroid Build Coastguard Worker         return false;
1528*9880d681SAndroid Build Coastguard Worker       }
1529*9880d681SAndroid Build Coastguard Worker       return true;
1530*9880d681SAndroid Build Coastguard Worker     }
1531*9880d681SAndroid Build Coastguard Worker     if (skip_b_break(Current) != Current &&
1532*9880d681SAndroid Build Coastguard Worker         Column > MaxAllSpaceLineCharacters) {
1533*9880d681SAndroid Build Coastguard Worker       // Record the longest all-space line in case it's longer than the
1534*9880d681SAndroid Build Coastguard Worker       // discovered block indent.
1535*9880d681SAndroid Build Coastguard Worker       MaxAllSpaceLineCharacters = Column;
1536*9880d681SAndroid Build Coastguard Worker       LongestAllSpaceLine = Current;
1537*9880d681SAndroid Build Coastguard Worker     }
1538*9880d681SAndroid Build Coastguard Worker 
1539*9880d681SAndroid Build Coastguard Worker     // Check for EOF.
1540*9880d681SAndroid Build Coastguard Worker     if (Current == End) {
1541*9880d681SAndroid Build Coastguard Worker       IsDone = true;
1542*9880d681SAndroid Build Coastguard Worker       return true;
1543*9880d681SAndroid Build Coastguard Worker     }
1544*9880d681SAndroid Build Coastguard Worker 
1545*9880d681SAndroid Build Coastguard Worker     if (!consumeLineBreakIfPresent()) {
1546*9880d681SAndroid Build Coastguard Worker       IsDone = true;
1547*9880d681SAndroid Build Coastguard Worker       return true;
1548*9880d681SAndroid Build Coastguard Worker     }
1549*9880d681SAndroid Build Coastguard Worker     ++LineBreaks;
1550*9880d681SAndroid Build Coastguard Worker   }
1551*9880d681SAndroid Build Coastguard Worker   return true;
1552*9880d681SAndroid Build Coastguard Worker }
1553*9880d681SAndroid Build Coastguard Worker 
scanBlockScalarIndent(unsigned BlockIndent,unsigned BlockExitIndent,bool & IsDone)1554*9880d681SAndroid Build Coastguard Worker bool Scanner::scanBlockScalarIndent(unsigned BlockIndent,
1555*9880d681SAndroid Build Coastguard Worker                                     unsigned BlockExitIndent, bool &IsDone) {
1556*9880d681SAndroid Build Coastguard Worker   // Skip the indentation.
1557*9880d681SAndroid Build Coastguard Worker   while (Column < BlockIndent) {
1558*9880d681SAndroid Build Coastguard Worker     auto I = skip_s_space(Current);
1559*9880d681SAndroid Build Coastguard Worker     if (I == Current)
1560*9880d681SAndroid Build Coastguard Worker       break;
1561*9880d681SAndroid Build Coastguard Worker     Current = I;
1562*9880d681SAndroid Build Coastguard Worker     ++Column;
1563*9880d681SAndroid Build Coastguard Worker   }
1564*9880d681SAndroid Build Coastguard Worker 
1565*9880d681SAndroid Build Coastguard Worker   if (skip_nb_char(Current) == Current)
1566*9880d681SAndroid Build Coastguard Worker     return true;
1567*9880d681SAndroid Build Coastguard Worker 
1568*9880d681SAndroid Build Coastguard Worker   if (Column <= BlockExitIndent) { // End of the block literal.
1569*9880d681SAndroid Build Coastguard Worker     IsDone = true;
1570*9880d681SAndroid Build Coastguard Worker     return true;
1571*9880d681SAndroid Build Coastguard Worker   }
1572*9880d681SAndroid Build Coastguard Worker 
1573*9880d681SAndroid Build Coastguard Worker   if (Column < BlockIndent) {
1574*9880d681SAndroid Build Coastguard Worker     if (Current != End && *Current == '#') { // Trailing comment.
1575*9880d681SAndroid Build Coastguard Worker       IsDone = true;
1576*9880d681SAndroid Build Coastguard Worker       return true;
1577*9880d681SAndroid Build Coastguard Worker     }
1578*9880d681SAndroid Build Coastguard Worker     setError("A text line is less indented than the block scalar", Current);
1579*9880d681SAndroid Build Coastguard Worker     return false;
1580*9880d681SAndroid Build Coastguard Worker   }
1581*9880d681SAndroid Build Coastguard Worker   return true; // A normal text line.
1582*9880d681SAndroid Build Coastguard Worker }
1583*9880d681SAndroid Build Coastguard Worker 
scanBlockScalar(bool IsLiteral)1584*9880d681SAndroid Build Coastguard Worker bool Scanner::scanBlockScalar(bool IsLiteral) {
1585*9880d681SAndroid Build Coastguard Worker   // Eat '|' or '>'
1586*9880d681SAndroid Build Coastguard Worker   assert(*Current == '|' || *Current == '>');
1587*9880d681SAndroid Build Coastguard Worker   skip(1);
1588*9880d681SAndroid Build Coastguard Worker 
1589*9880d681SAndroid Build Coastguard Worker   char ChompingIndicator;
1590*9880d681SAndroid Build Coastguard Worker   unsigned BlockIndent;
1591*9880d681SAndroid Build Coastguard Worker   bool IsDone = false;
1592*9880d681SAndroid Build Coastguard Worker   if (!scanBlockScalarHeader(ChompingIndicator, BlockIndent, IsDone))
1593*9880d681SAndroid Build Coastguard Worker     return false;
1594*9880d681SAndroid Build Coastguard Worker   if (IsDone)
1595*9880d681SAndroid Build Coastguard Worker     return true;
1596*9880d681SAndroid Build Coastguard Worker 
1597*9880d681SAndroid Build Coastguard Worker   auto Start = Current;
1598*9880d681SAndroid Build Coastguard Worker   unsigned BlockExitIndent = Indent < 0 ? 0 : (unsigned)Indent;
1599*9880d681SAndroid Build Coastguard Worker   unsigned LineBreaks = 0;
1600*9880d681SAndroid Build Coastguard Worker   if (BlockIndent == 0) {
1601*9880d681SAndroid Build Coastguard Worker     if (!findBlockScalarIndent(BlockIndent, BlockExitIndent, LineBreaks,
1602*9880d681SAndroid Build Coastguard Worker                                IsDone))
1603*9880d681SAndroid Build Coastguard Worker       return false;
1604*9880d681SAndroid Build Coastguard Worker   }
1605*9880d681SAndroid Build Coastguard Worker 
1606*9880d681SAndroid Build Coastguard Worker   // Scan the block's scalars body.
1607*9880d681SAndroid Build Coastguard Worker   SmallString<256> Str;
1608*9880d681SAndroid Build Coastguard Worker   while (!IsDone) {
1609*9880d681SAndroid Build Coastguard Worker     if (!scanBlockScalarIndent(BlockIndent, BlockExitIndent, IsDone))
1610*9880d681SAndroid Build Coastguard Worker       return false;
1611*9880d681SAndroid Build Coastguard Worker     if (IsDone)
1612*9880d681SAndroid Build Coastguard Worker       break;
1613*9880d681SAndroid Build Coastguard Worker 
1614*9880d681SAndroid Build Coastguard Worker     // Parse the current line.
1615*9880d681SAndroid Build Coastguard Worker     auto LineStart = Current;
1616*9880d681SAndroid Build Coastguard Worker     advanceWhile(&Scanner::skip_nb_char);
1617*9880d681SAndroid Build Coastguard Worker     if (LineStart != Current) {
1618*9880d681SAndroid Build Coastguard Worker       Str.append(LineBreaks, '\n');
1619*9880d681SAndroid Build Coastguard Worker       Str.append(StringRef(LineStart, Current - LineStart));
1620*9880d681SAndroid Build Coastguard Worker       LineBreaks = 0;
1621*9880d681SAndroid Build Coastguard Worker     }
1622*9880d681SAndroid Build Coastguard Worker 
1623*9880d681SAndroid Build Coastguard Worker     // Check for EOF.
1624*9880d681SAndroid Build Coastguard Worker     if (Current == End)
1625*9880d681SAndroid Build Coastguard Worker       break;
1626*9880d681SAndroid Build Coastguard Worker 
1627*9880d681SAndroid Build Coastguard Worker     if (!consumeLineBreakIfPresent())
1628*9880d681SAndroid Build Coastguard Worker       break;
1629*9880d681SAndroid Build Coastguard Worker     ++LineBreaks;
1630*9880d681SAndroid Build Coastguard Worker   }
1631*9880d681SAndroid Build Coastguard Worker 
1632*9880d681SAndroid Build Coastguard Worker   if (Current == End && !LineBreaks)
1633*9880d681SAndroid Build Coastguard Worker     // Ensure that there is at least one line break before the end of file.
1634*9880d681SAndroid Build Coastguard Worker     LineBreaks = 1;
1635*9880d681SAndroid Build Coastguard Worker   Str.append(getChompedLineBreaks(ChompingIndicator, LineBreaks, Str), '\n');
1636*9880d681SAndroid Build Coastguard Worker 
1637*9880d681SAndroid Build Coastguard Worker   // New lines may start a simple key.
1638*9880d681SAndroid Build Coastguard Worker   if (!FlowLevel)
1639*9880d681SAndroid Build Coastguard Worker     IsSimpleKeyAllowed = true;
1640*9880d681SAndroid Build Coastguard Worker 
1641*9880d681SAndroid Build Coastguard Worker   Token T;
1642*9880d681SAndroid Build Coastguard Worker   T.Kind = Token::TK_BlockScalar;
1643*9880d681SAndroid Build Coastguard Worker   T.Range = StringRef(Start, Current - Start);
1644*9880d681SAndroid Build Coastguard Worker   T.Value = Str.str().str();
1645*9880d681SAndroid Build Coastguard Worker   TokenQueue.push_back(T);
1646*9880d681SAndroid Build Coastguard Worker   return true;
1647*9880d681SAndroid Build Coastguard Worker }
1648*9880d681SAndroid Build Coastguard Worker 
scanTag()1649*9880d681SAndroid Build Coastguard Worker bool Scanner::scanTag() {
1650*9880d681SAndroid Build Coastguard Worker   StringRef::iterator Start = Current;
1651*9880d681SAndroid Build Coastguard Worker   unsigned ColStart = Column;
1652*9880d681SAndroid Build Coastguard Worker   skip(1); // Eat !.
1653*9880d681SAndroid Build Coastguard Worker   if (Current == End || isBlankOrBreak(Current)); // An empty tag.
1654*9880d681SAndroid Build Coastguard Worker   else if (*Current == '<') {
1655*9880d681SAndroid Build Coastguard Worker     skip(1);
1656*9880d681SAndroid Build Coastguard Worker     scan_ns_uri_char();
1657*9880d681SAndroid Build Coastguard Worker     if (!consume('>'))
1658*9880d681SAndroid Build Coastguard Worker       return false;
1659*9880d681SAndroid Build Coastguard Worker   } else {
1660*9880d681SAndroid Build Coastguard Worker     // FIXME: Actually parse the c-ns-shorthand-tag rule.
1661*9880d681SAndroid Build Coastguard Worker     Current = skip_while(&Scanner::skip_ns_char, Current);
1662*9880d681SAndroid Build Coastguard Worker   }
1663*9880d681SAndroid Build Coastguard Worker 
1664*9880d681SAndroid Build Coastguard Worker   Token T;
1665*9880d681SAndroid Build Coastguard Worker   T.Kind = Token::TK_Tag;
1666*9880d681SAndroid Build Coastguard Worker   T.Range = StringRef(Start, Current - Start);
1667*9880d681SAndroid Build Coastguard Worker   TokenQueue.push_back(T);
1668*9880d681SAndroid Build Coastguard Worker 
1669*9880d681SAndroid Build Coastguard Worker   // Tags can be simple keys.
1670*9880d681SAndroid Build Coastguard Worker   saveSimpleKeyCandidate(--TokenQueue.end(), ColStart, false);
1671*9880d681SAndroid Build Coastguard Worker 
1672*9880d681SAndroid Build Coastguard Worker   IsSimpleKeyAllowed = false;
1673*9880d681SAndroid Build Coastguard Worker 
1674*9880d681SAndroid Build Coastguard Worker   return true;
1675*9880d681SAndroid Build Coastguard Worker }
1676*9880d681SAndroid Build Coastguard Worker 
fetchMoreTokens()1677*9880d681SAndroid Build Coastguard Worker bool Scanner::fetchMoreTokens() {
1678*9880d681SAndroid Build Coastguard Worker   if (IsStartOfStream)
1679*9880d681SAndroid Build Coastguard Worker     return scanStreamStart();
1680*9880d681SAndroid Build Coastguard Worker 
1681*9880d681SAndroid Build Coastguard Worker   scanToNextToken();
1682*9880d681SAndroid Build Coastguard Worker 
1683*9880d681SAndroid Build Coastguard Worker   if (Current == End)
1684*9880d681SAndroid Build Coastguard Worker     return scanStreamEnd();
1685*9880d681SAndroid Build Coastguard Worker 
1686*9880d681SAndroid Build Coastguard Worker   removeStaleSimpleKeyCandidates();
1687*9880d681SAndroid Build Coastguard Worker 
1688*9880d681SAndroid Build Coastguard Worker   unrollIndent(Column);
1689*9880d681SAndroid Build Coastguard Worker 
1690*9880d681SAndroid Build Coastguard Worker   if (Column == 0 && *Current == '%')
1691*9880d681SAndroid Build Coastguard Worker     return scanDirective();
1692*9880d681SAndroid Build Coastguard Worker 
1693*9880d681SAndroid Build Coastguard Worker   if (Column == 0 && Current + 4 <= End
1694*9880d681SAndroid Build Coastguard Worker       && *Current == '-'
1695*9880d681SAndroid Build Coastguard Worker       && *(Current + 1) == '-'
1696*9880d681SAndroid Build Coastguard Worker       && *(Current + 2) == '-'
1697*9880d681SAndroid Build Coastguard Worker       && (Current + 3 == End || isBlankOrBreak(Current + 3)))
1698*9880d681SAndroid Build Coastguard Worker     return scanDocumentIndicator(true);
1699*9880d681SAndroid Build Coastguard Worker 
1700*9880d681SAndroid Build Coastguard Worker   if (Column == 0 && Current + 4 <= End
1701*9880d681SAndroid Build Coastguard Worker       && *Current == '.'
1702*9880d681SAndroid Build Coastguard Worker       && *(Current + 1) == '.'
1703*9880d681SAndroid Build Coastguard Worker       && *(Current + 2) == '.'
1704*9880d681SAndroid Build Coastguard Worker       && (Current + 3 == End || isBlankOrBreak(Current + 3)))
1705*9880d681SAndroid Build Coastguard Worker     return scanDocumentIndicator(false);
1706*9880d681SAndroid Build Coastguard Worker 
1707*9880d681SAndroid Build Coastguard Worker   if (*Current == '[')
1708*9880d681SAndroid Build Coastguard Worker     return scanFlowCollectionStart(true);
1709*9880d681SAndroid Build Coastguard Worker 
1710*9880d681SAndroid Build Coastguard Worker   if (*Current == '{')
1711*9880d681SAndroid Build Coastguard Worker     return scanFlowCollectionStart(false);
1712*9880d681SAndroid Build Coastguard Worker 
1713*9880d681SAndroid Build Coastguard Worker   if (*Current == ']')
1714*9880d681SAndroid Build Coastguard Worker     return scanFlowCollectionEnd(true);
1715*9880d681SAndroid Build Coastguard Worker 
1716*9880d681SAndroid Build Coastguard Worker   if (*Current == '}')
1717*9880d681SAndroid Build Coastguard Worker     return scanFlowCollectionEnd(false);
1718*9880d681SAndroid Build Coastguard Worker 
1719*9880d681SAndroid Build Coastguard Worker   if (*Current == ',')
1720*9880d681SAndroid Build Coastguard Worker     return scanFlowEntry();
1721*9880d681SAndroid Build Coastguard Worker 
1722*9880d681SAndroid Build Coastguard Worker   if (*Current == '-' && isBlankOrBreak(Current + 1))
1723*9880d681SAndroid Build Coastguard Worker     return scanBlockEntry();
1724*9880d681SAndroid Build Coastguard Worker 
1725*9880d681SAndroid Build Coastguard Worker   if (*Current == '?' && (FlowLevel || isBlankOrBreak(Current + 1)))
1726*9880d681SAndroid Build Coastguard Worker     return scanKey();
1727*9880d681SAndroid Build Coastguard Worker 
1728*9880d681SAndroid Build Coastguard Worker   if (*Current == ':' && (FlowLevel || isBlankOrBreak(Current + 1)))
1729*9880d681SAndroid Build Coastguard Worker     return scanValue();
1730*9880d681SAndroid Build Coastguard Worker 
1731*9880d681SAndroid Build Coastguard Worker   if (*Current == '*')
1732*9880d681SAndroid Build Coastguard Worker     return scanAliasOrAnchor(true);
1733*9880d681SAndroid Build Coastguard Worker 
1734*9880d681SAndroid Build Coastguard Worker   if (*Current == '&')
1735*9880d681SAndroid Build Coastguard Worker     return scanAliasOrAnchor(false);
1736*9880d681SAndroid Build Coastguard Worker 
1737*9880d681SAndroid Build Coastguard Worker   if (*Current == '!')
1738*9880d681SAndroid Build Coastguard Worker     return scanTag();
1739*9880d681SAndroid Build Coastguard Worker 
1740*9880d681SAndroid Build Coastguard Worker   if (*Current == '|' && !FlowLevel)
1741*9880d681SAndroid Build Coastguard Worker     return scanBlockScalar(true);
1742*9880d681SAndroid Build Coastguard Worker 
1743*9880d681SAndroid Build Coastguard Worker   if (*Current == '>' && !FlowLevel)
1744*9880d681SAndroid Build Coastguard Worker     return scanBlockScalar(false);
1745*9880d681SAndroid Build Coastguard Worker 
1746*9880d681SAndroid Build Coastguard Worker   if (*Current == '\'')
1747*9880d681SAndroid Build Coastguard Worker     return scanFlowScalar(false);
1748*9880d681SAndroid Build Coastguard Worker 
1749*9880d681SAndroid Build Coastguard Worker   if (*Current == '"')
1750*9880d681SAndroid Build Coastguard Worker     return scanFlowScalar(true);
1751*9880d681SAndroid Build Coastguard Worker 
1752*9880d681SAndroid Build Coastguard Worker   // Get a plain scalar.
1753*9880d681SAndroid Build Coastguard Worker   StringRef FirstChar(Current, 1);
1754*9880d681SAndroid Build Coastguard Worker   if (!(isBlankOrBreak(Current)
1755*9880d681SAndroid Build Coastguard Worker         || FirstChar.find_first_of("-?:,[]{}#&*!|>'\"%@`") != StringRef::npos)
1756*9880d681SAndroid Build Coastguard Worker       || (*Current == '-' && !isBlankOrBreak(Current + 1))
1757*9880d681SAndroid Build Coastguard Worker       || (!FlowLevel && (*Current == '?' || *Current == ':')
1758*9880d681SAndroid Build Coastguard Worker           && isBlankOrBreak(Current + 1))
1759*9880d681SAndroid Build Coastguard Worker       || (!FlowLevel && *Current == ':'
1760*9880d681SAndroid Build Coastguard Worker                       && Current + 2 < End
1761*9880d681SAndroid Build Coastguard Worker                       && *(Current + 1) == ':'
1762*9880d681SAndroid Build Coastguard Worker                       && !isBlankOrBreak(Current + 2)))
1763*9880d681SAndroid Build Coastguard Worker     return scanPlainScalar();
1764*9880d681SAndroid Build Coastguard Worker 
1765*9880d681SAndroid Build Coastguard Worker   setError("Unrecognized character while tokenizing.");
1766*9880d681SAndroid Build Coastguard Worker   return false;
1767*9880d681SAndroid Build Coastguard Worker }
1768*9880d681SAndroid Build Coastguard Worker 
Stream(StringRef Input,SourceMgr & SM,bool ShowColors)1769*9880d681SAndroid Build Coastguard Worker Stream::Stream(StringRef Input, SourceMgr &SM, bool ShowColors)
1770*9880d681SAndroid Build Coastguard Worker     : scanner(new Scanner(Input, SM, ShowColors)), CurrentDoc() {}
1771*9880d681SAndroid Build Coastguard Worker 
Stream(MemoryBufferRef InputBuffer,SourceMgr & SM,bool ShowColors)1772*9880d681SAndroid Build Coastguard Worker Stream::Stream(MemoryBufferRef InputBuffer, SourceMgr &SM, bool ShowColors)
1773*9880d681SAndroid Build Coastguard Worker     : scanner(new Scanner(InputBuffer, SM, ShowColors)), CurrentDoc() {}
1774*9880d681SAndroid Build Coastguard Worker 
~Stream()1775*9880d681SAndroid Build Coastguard Worker Stream::~Stream() {}
1776*9880d681SAndroid Build Coastguard Worker 
failed()1777*9880d681SAndroid Build Coastguard Worker bool Stream::failed() { return scanner->failed(); }
1778*9880d681SAndroid Build Coastguard Worker 
printError(Node * N,const Twine & Msg)1779*9880d681SAndroid Build Coastguard Worker void Stream::printError(Node *N, const Twine &Msg) {
1780*9880d681SAndroid Build Coastguard Worker   scanner->printError( N->getSourceRange().Start
1781*9880d681SAndroid Build Coastguard Worker                      , SourceMgr::DK_Error
1782*9880d681SAndroid Build Coastguard Worker                      , Msg
1783*9880d681SAndroid Build Coastguard Worker                      , N->getSourceRange());
1784*9880d681SAndroid Build Coastguard Worker }
1785*9880d681SAndroid Build Coastguard Worker 
begin()1786*9880d681SAndroid Build Coastguard Worker document_iterator Stream::begin() {
1787*9880d681SAndroid Build Coastguard Worker   if (CurrentDoc)
1788*9880d681SAndroid Build Coastguard Worker     report_fatal_error("Can only iterate over the stream once");
1789*9880d681SAndroid Build Coastguard Worker 
1790*9880d681SAndroid Build Coastguard Worker   // Skip Stream-Start.
1791*9880d681SAndroid Build Coastguard Worker   scanner->getNext();
1792*9880d681SAndroid Build Coastguard Worker 
1793*9880d681SAndroid Build Coastguard Worker   CurrentDoc.reset(new Document(*this));
1794*9880d681SAndroid Build Coastguard Worker   return document_iterator(CurrentDoc);
1795*9880d681SAndroid Build Coastguard Worker }
1796*9880d681SAndroid Build Coastguard Worker 
end()1797*9880d681SAndroid Build Coastguard Worker document_iterator Stream::end() {
1798*9880d681SAndroid Build Coastguard Worker   return document_iterator();
1799*9880d681SAndroid Build Coastguard Worker }
1800*9880d681SAndroid Build Coastguard Worker 
skip()1801*9880d681SAndroid Build Coastguard Worker void Stream::skip() {
1802*9880d681SAndroid Build Coastguard Worker   for (document_iterator i = begin(), e = end(); i != e; ++i)
1803*9880d681SAndroid Build Coastguard Worker     i->skip();
1804*9880d681SAndroid Build Coastguard Worker }
1805*9880d681SAndroid Build Coastguard Worker 
Node(unsigned int Type,std::unique_ptr<Document> & D,StringRef A,StringRef T)1806*9880d681SAndroid Build Coastguard Worker Node::Node(unsigned int Type, std::unique_ptr<Document> &D, StringRef A,
1807*9880d681SAndroid Build Coastguard Worker            StringRef T)
1808*9880d681SAndroid Build Coastguard Worker     : Doc(D), TypeID(Type), Anchor(A), Tag(T) {
1809*9880d681SAndroid Build Coastguard Worker   SMLoc Start = SMLoc::getFromPointer(peekNext().Range.begin());
1810*9880d681SAndroid Build Coastguard Worker   SourceRange = SMRange(Start, Start);
1811*9880d681SAndroid Build Coastguard Worker }
1812*9880d681SAndroid Build Coastguard Worker 
getVerbatimTag() const1813*9880d681SAndroid Build Coastguard Worker std::string Node::getVerbatimTag() const {
1814*9880d681SAndroid Build Coastguard Worker   StringRef Raw = getRawTag();
1815*9880d681SAndroid Build Coastguard Worker   if (!Raw.empty() && Raw != "!") {
1816*9880d681SAndroid Build Coastguard Worker     std::string Ret;
1817*9880d681SAndroid Build Coastguard Worker     if (Raw.find_last_of('!') == 0) {
1818*9880d681SAndroid Build Coastguard Worker       Ret = Doc->getTagMap().find("!")->second;
1819*9880d681SAndroid Build Coastguard Worker       Ret += Raw.substr(1);
1820*9880d681SAndroid Build Coastguard Worker       return Ret;
1821*9880d681SAndroid Build Coastguard Worker     } else if (Raw.startswith("!!")) {
1822*9880d681SAndroid Build Coastguard Worker       Ret = Doc->getTagMap().find("!!")->second;
1823*9880d681SAndroid Build Coastguard Worker       Ret += Raw.substr(2);
1824*9880d681SAndroid Build Coastguard Worker       return Ret;
1825*9880d681SAndroid Build Coastguard Worker     } else {
1826*9880d681SAndroid Build Coastguard Worker       StringRef TagHandle = Raw.substr(0, Raw.find_last_of('!') + 1);
1827*9880d681SAndroid Build Coastguard Worker       std::map<StringRef, StringRef>::const_iterator It =
1828*9880d681SAndroid Build Coastguard Worker           Doc->getTagMap().find(TagHandle);
1829*9880d681SAndroid Build Coastguard Worker       if (It != Doc->getTagMap().end())
1830*9880d681SAndroid Build Coastguard Worker         Ret = It->second;
1831*9880d681SAndroid Build Coastguard Worker       else {
1832*9880d681SAndroid Build Coastguard Worker         Token T;
1833*9880d681SAndroid Build Coastguard Worker         T.Kind = Token::TK_Tag;
1834*9880d681SAndroid Build Coastguard Worker         T.Range = TagHandle;
1835*9880d681SAndroid Build Coastguard Worker         setError(Twine("Unknown tag handle ") + TagHandle, T);
1836*9880d681SAndroid Build Coastguard Worker       }
1837*9880d681SAndroid Build Coastguard Worker       Ret += Raw.substr(Raw.find_last_of('!') + 1);
1838*9880d681SAndroid Build Coastguard Worker       return Ret;
1839*9880d681SAndroid Build Coastguard Worker     }
1840*9880d681SAndroid Build Coastguard Worker   }
1841*9880d681SAndroid Build Coastguard Worker 
1842*9880d681SAndroid Build Coastguard Worker   switch (getType()) {
1843*9880d681SAndroid Build Coastguard Worker   case NK_Null:
1844*9880d681SAndroid Build Coastguard Worker     return "tag:yaml.org,2002:null";
1845*9880d681SAndroid Build Coastguard Worker   case NK_Scalar:
1846*9880d681SAndroid Build Coastguard Worker   case NK_BlockScalar:
1847*9880d681SAndroid Build Coastguard Worker     // TODO: Tag resolution.
1848*9880d681SAndroid Build Coastguard Worker     return "tag:yaml.org,2002:str";
1849*9880d681SAndroid Build Coastguard Worker   case NK_Mapping:
1850*9880d681SAndroid Build Coastguard Worker     return "tag:yaml.org,2002:map";
1851*9880d681SAndroid Build Coastguard Worker   case NK_Sequence:
1852*9880d681SAndroid Build Coastguard Worker     return "tag:yaml.org,2002:seq";
1853*9880d681SAndroid Build Coastguard Worker   }
1854*9880d681SAndroid Build Coastguard Worker 
1855*9880d681SAndroid Build Coastguard Worker   return "";
1856*9880d681SAndroid Build Coastguard Worker }
1857*9880d681SAndroid Build Coastguard Worker 
peekNext()1858*9880d681SAndroid Build Coastguard Worker Token &Node::peekNext() {
1859*9880d681SAndroid Build Coastguard Worker   return Doc->peekNext();
1860*9880d681SAndroid Build Coastguard Worker }
1861*9880d681SAndroid Build Coastguard Worker 
getNext()1862*9880d681SAndroid Build Coastguard Worker Token Node::getNext() {
1863*9880d681SAndroid Build Coastguard Worker   return Doc->getNext();
1864*9880d681SAndroid Build Coastguard Worker }
1865*9880d681SAndroid Build Coastguard Worker 
parseBlockNode()1866*9880d681SAndroid Build Coastguard Worker Node *Node::parseBlockNode() {
1867*9880d681SAndroid Build Coastguard Worker   return Doc->parseBlockNode();
1868*9880d681SAndroid Build Coastguard Worker }
1869*9880d681SAndroid Build Coastguard Worker 
getAllocator()1870*9880d681SAndroid Build Coastguard Worker BumpPtrAllocator &Node::getAllocator() {
1871*9880d681SAndroid Build Coastguard Worker   return Doc->NodeAllocator;
1872*9880d681SAndroid Build Coastguard Worker }
1873*9880d681SAndroid Build Coastguard Worker 
setError(const Twine & Msg,Token & Tok) const1874*9880d681SAndroid Build Coastguard Worker void Node::setError(const Twine &Msg, Token &Tok) const {
1875*9880d681SAndroid Build Coastguard Worker   Doc->setError(Msg, Tok);
1876*9880d681SAndroid Build Coastguard Worker }
1877*9880d681SAndroid Build Coastguard Worker 
failed() const1878*9880d681SAndroid Build Coastguard Worker bool Node::failed() const {
1879*9880d681SAndroid Build Coastguard Worker   return Doc->failed();
1880*9880d681SAndroid Build Coastguard Worker }
1881*9880d681SAndroid Build Coastguard Worker 
1882*9880d681SAndroid Build Coastguard Worker 
1883*9880d681SAndroid Build Coastguard Worker 
getValue(SmallVectorImpl<char> & Storage) const1884*9880d681SAndroid Build Coastguard Worker StringRef ScalarNode::getValue(SmallVectorImpl<char> &Storage) const {
1885*9880d681SAndroid Build Coastguard Worker   // TODO: Handle newlines properly. We need to remove leading whitespace.
1886*9880d681SAndroid Build Coastguard Worker   if (Value[0] == '"') { // Double quoted.
1887*9880d681SAndroid Build Coastguard Worker     // Pull off the leading and trailing "s.
1888*9880d681SAndroid Build Coastguard Worker     StringRef UnquotedValue = Value.substr(1, Value.size() - 2);
1889*9880d681SAndroid Build Coastguard Worker     // Search for characters that would require unescaping the value.
1890*9880d681SAndroid Build Coastguard Worker     StringRef::size_type i = UnquotedValue.find_first_of("\\\r\n");
1891*9880d681SAndroid Build Coastguard Worker     if (i != StringRef::npos)
1892*9880d681SAndroid Build Coastguard Worker       return unescapeDoubleQuoted(UnquotedValue, i, Storage);
1893*9880d681SAndroid Build Coastguard Worker     return UnquotedValue;
1894*9880d681SAndroid Build Coastguard Worker   } else if (Value[0] == '\'') { // Single quoted.
1895*9880d681SAndroid Build Coastguard Worker     // Pull off the leading and trailing 's.
1896*9880d681SAndroid Build Coastguard Worker     StringRef UnquotedValue = Value.substr(1, Value.size() - 2);
1897*9880d681SAndroid Build Coastguard Worker     StringRef::size_type i = UnquotedValue.find('\'');
1898*9880d681SAndroid Build Coastguard Worker     if (i != StringRef::npos) {
1899*9880d681SAndroid Build Coastguard Worker       // We're going to need Storage.
1900*9880d681SAndroid Build Coastguard Worker       Storage.clear();
1901*9880d681SAndroid Build Coastguard Worker       Storage.reserve(UnquotedValue.size());
1902*9880d681SAndroid Build Coastguard Worker       for (; i != StringRef::npos; i = UnquotedValue.find('\'')) {
1903*9880d681SAndroid Build Coastguard Worker         StringRef Valid(UnquotedValue.begin(), i);
1904*9880d681SAndroid Build Coastguard Worker         Storage.insert(Storage.end(), Valid.begin(), Valid.end());
1905*9880d681SAndroid Build Coastguard Worker         Storage.push_back('\'');
1906*9880d681SAndroid Build Coastguard Worker         UnquotedValue = UnquotedValue.substr(i + 2);
1907*9880d681SAndroid Build Coastguard Worker       }
1908*9880d681SAndroid Build Coastguard Worker       Storage.insert(Storage.end(), UnquotedValue.begin(), UnquotedValue.end());
1909*9880d681SAndroid Build Coastguard Worker       return StringRef(Storage.begin(), Storage.size());
1910*9880d681SAndroid Build Coastguard Worker     }
1911*9880d681SAndroid Build Coastguard Worker     return UnquotedValue;
1912*9880d681SAndroid Build Coastguard Worker   }
1913*9880d681SAndroid Build Coastguard Worker   // Plain or block.
1914*9880d681SAndroid Build Coastguard Worker   return Value.rtrim(' ');
1915*9880d681SAndroid Build Coastguard Worker }
1916*9880d681SAndroid Build Coastguard Worker 
unescapeDoubleQuoted(StringRef UnquotedValue,StringRef::size_type i,SmallVectorImpl<char> & Storage) const1917*9880d681SAndroid Build Coastguard Worker StringRef ScalarNode::unescapeDoubleQuoted( StringRef UnquotedValue
1918*9880d681SAndroid Build Coastguard Worker                                           , StringRef::size_type i
1919*9880d681SAndroid Build Coastguard Worker                                           , SmallVectorImpl<char> &Storage)
1920*9880d681SAndroid Build Coastguard Worker                                           const {
1921*9880d681SAndroid Build Coastguard Worker   // Use Storage to build proper value.
1922*9880d681SAndroid Build Coastguard Worker   Storage.clear();
1923*9880d681SAndroid Build Coastguard Worker   Storage.reserve(UnquotedValue.size());
1924*9880d681SAndroid Build Coastguard Worker   for (; i != StringRef::npos; i = UnquotedValue.find_first_of("\\\r\n")) {
1925*9880d681SAndroid Build Coastguard Worker     // Insert all previous chars into Storage.
1926*9880d681SAndroid Build Coastguard Worker     StringRef Valid(UnquotedValue.begin(), i);
1927*9880d681SAndroid Build Coastguard Worker     Storage.insert(Storage.end(), Valid.begin(), Valid.end());
1928*9880d681SAndroid Build Coastguard Worker     // Chop off inserted chars.
1929*9880d681SAndroid Build Coastguard Worker     UnquotedValue = UnquotedValue.substr(i);
1930*9880d681SAndroid Build Coastguard Worker 
1931*9880d681SAndroid Build Coastguard Worker     assert(!UnquotedValue.empty() && "Can't be empty!");
1932*9880d681SAndroid Build Coastguard Worker 
1933*9880d681SAndroid Build Coastguard Worker     // Parse escape or line break.
1934*9880d681SAndroid Build Coastguard Worker     switch (UnquotedValue[0]) {
1935*9880d681SAndroid Build Coastguard Worker     case '\r':
1936*9880d681SAndroid Build Coastguard Worker     case '\n':
1937*9880d681SAndroid Build Coastguard Worker       Storage.push_back('\n');
1938*9880d681SAndroid Build Coastguard Worker       if (   UnquotedValue.size() > 1
1939*9880d681SAndroid Build Coastguard Worker           && (UnquotedValue[1] == '\r' || UnquotedValue[1] == '\n'))
1940*9880d681SAndroid Build Coastguard Worker         UnquotedValue = UnquotedValue.substr(1);
1941*9880d681SAndroid Build Coastguard Worker       UnquotedValue = UnquotedValue.substr(1);
1942*9880d681SAndroid Build Coastguard Worker       break;
1943*9880d681SAndroid Build Coastguard Worker     default:
1944*9880d681SAndroid Build Coastguard Worker       if (UnquotedValue.size() == 1)
1945*9880d681SAndroid Build Coastguard Worker         // TODO: Report error.
1946*9880d681SAndroid Build Coastguard Worker         break;
1947*9880d681SAndroid Build Coastguard Worker       UnquotedValue = UnquotedValue.substr(1);
1948*9880d681SAndroid Build Coastguard Worker       switch (UnquotedValue[0]) {
1949*9880d681SAndroid Build Coastguard Worker       default: {
1950*9880d681SAndroid Build Coastguard Worker           Token T;
1951*9880d681SAndroid Build Coastguard Worker           T.Range = StringRef(UnquotedValue.begin(), 1);
1952*9880d681SAndroid Build Coastguard Worker           setError("Unrecognized escape code!", T);
1953*9880d681SAndroid Build Coastguard Worker           return "";
1954*9880d681SAndroid Build Coastguard Worker         }
1955*9880d681SAndroid Build Coastguard Worker       case '\r':
1956*9880d681SAndroid Build Coastguard Worker       case '\n':
1957*9880d681SAndroid Build Coastguard Worker         // Remove the new line.
1958*9880d681SAndroid Build Coastguard Worker         if (   UnquotedValue.size() > 1
1959*9880d681SAndroid Build Coastguard Worker             && (UnquotedValue[1] == '\r' || UnquotedValue[1] == '\n'))
1960*9880d681SAndroid Build Coastguard Worker           UnquotedValue = UnquotedValue.substr(1);
1961*9880d681SAndroid Build Coastguard Worker         // If this was just a single byte newline, it will get skipped
1962*9880d681SAndroid Build Coastguard Worker         // below.
1963*9880d681SAndroid Build Coastguard Worker         break;
1964*9880d681SAndroid Build Coastguard Worker       case '0':
1965*9880d681SAndroid Build Coastguard Worker         Storage.push_back(0x00);
1966*9880d681SAndroid Build Coastguard Worker         break;
1967*9880d681SAndroid Build Coastguard Worker       case 'a':
1968*9880d681SAndroid Build Coastguard Worker         Storage.push_back(0x07);
1969*9880d681SAndroid Build Coastguard Worker         break;
1970*9880d681SAndroid Build Coastguard Worker       case 'b':
1971*9880d681SAndroid Build Coastguard Worker         Storage.push_back(0x08);
1972*9880d681SAndroid Build Coastguard Worker         break;
1973*9880d681SAndroid Build Coastguard Worker       case 't':
1974*9880d681SAndroid Build Coastguard Worker       case 0x09:
1975*9880d681SAndroid Build Coastguard Worker         Storage.push_back(0x09);
1976*9880d681SAndroid Build Coastguard Worker         break;
1977*9880d681SAndroid Build Coastguard Worker       case 'n':
1978*9880d681SAndroid Build Coastguard Worker         Storage.push_back(0x0A);
1979*9880d681SAndroid Build Coastguard Worker         break;
1980*9880d681SAndroid Build Coastguard Worker       case 'v':
1981*9880d681SAndroid Build Coastguard Worker         Storage.push_back(0x0B);
1982*9880d681SAndroid Build Coastguard Worker         break;
1983*9880d681SAndroid Build Coastguard Worker       case 'f':
1984*9880d681SAndroid Build Coastguard Worker         Storage.push_back(0x0C);
1985*9880d681SAndroid Build Coastguard Worker         break;
1986*9880d681SAndroid Build Coastguard Worker       case 'r':
1987*9880d681SAndroid Build Coastguard Worker         Storage.push_back(0x0D);
1988*9880d681SAndroid Build Coastguard Worker         break;
1989*9880d681SAndroid Build Coastguard Worker       case 'e':
1990*9880d681SAndroid Build Coastguard Worker         Storage.push_back(0x1B);
1991*9880d681SAndroid Build Coastguard Worker         break;
1992*9880d681SAndroid Build Coastguard Worker       case ' ':
1993*9880d681SAndroid Build Coastguard Worker         Storage.push_back(0x20);
1994*9880d681SAndroid Build Coastguard Worker         break;
1995*9880d681SAndroid Build Coastguard Worker       case '"':
1996*9880d681SAndroid Build Coastguard Worker         Storage.push_back(0x22);
1997*9880d681SAndroid Build Coastguard Worker         break;
1998*9880d681SAndroid Build Coastguard Worker       case '/':
1999*9880d681SAndroid Build Coastguard Worker         Storage.push_back(0x2F);
2000*9880d681SAndroid Build Coastguard Worker         break;
2001*9880d681SAndroid Build Coastguard Worker       case '\\':
2002*9880d681SAndroid Build Coastguard Worker         Storage.push_back(0x5C);
2003*9880d681SAndroid Build Coastguard Worker         break;
2004*9880d681SAndroid Build Coastguard Worker       case 'N':
2005*9880d681SAndroid Build Coastguard Worker         encodeUTF8(0x85, Storage);
2006*9880d681SAndroid Build Coastguard Worker         break;
2007*9880d681SAndroid Build Coastguard Worker       case '_':
2008*9880d681SAndroid Build Coastguard Worker         encodeUTF8(0xA0, Storage);
2009*9880d681SAndroid Build Coastguard Worker         break;
2010*9880d681SAndroid Build Coastguard Worker       case 'L':
2011*9880d681SAndroid Build Coastguard Worker         encodeUTF8(0x2028, Storage);
2012*9880d681SAndroid Build Coastguard Worker         break;
2013*9880d681SAndroid Build Coastguard Worker       case 'P':
2014*9880d681SAndroid Build Coastguard Worker         encodeUTF8(0x2029, Storage);
2015*9880d681SAndroid Build Coastguard Worker         break;
2016*9880d681SAndroid Build Coastguard Worker       case 'x': {
2017*9880d681SAndroid Build Coastguard Worker           if (UnquotedValue.size() < 3)
2018*9880d681SAndroid Build Coastguard Worker             // TODO: Report error.
2019*9880d681SAndroid Build Coastguard Worker             break;
2020*9880d681SAndroid Build Coastguard Worker           unsigned int UnicodeScalarValue;
2021*9880d681SAndroid Build Coastguard Worker           if (UnquotedValue.substr(1, 2).getAsInteger(16, UnicodeScalarValue))
2022*9880d681SAndroid Build Coastguard Worker             // TODO: Report error.
2023*9880d681SAndroid Build Coastguard Worker             UnicodeScalarValue = 0xFFFD;
2024*9880d681SAndroid Build Coastguard Worker           encodeUTF8(UnicodeScalarValue, Storage);
2025*9880d681SAndroid Build Coastguard Worker           UnquotedValue = UnquotedValue.substr(2);
2026*9880d681SAndroid Build Coastguard Worker           break;
2027*9880d681SAndroid Build Coastguard Worker         }
2028*9880d681SAndroid Build Coastguard Worker       case 'u': {
2029*9880d681SAndroid Build Coastguard Worker           if (UnquotedValue.size() < 5)
2030*9880d681SAndroid Build Coastguard Worker             // TODO: Report error.
2031*9880d681SAndroid Build Coastguard Worker             break;
2032*9880d681SAndroid Build Coastguard Worker           unsigned int UnicodeScalarValue;
2033*9880d681SAndroid Build Coastguard Worker           if (UnquotedValue.substr(1, 4).getAsInteger(16, UnicodeScalarValue))
2034*9880d681SAndroid Build Coastguard Worker             // TODO: Report error.
2035*9880d681SAndroid Build Coastguard Worker             UnicodeScalarValue = 0xFFFD;
2036*9880d681SAndroid Build Coastguard Worker           encodeUTF8(UnicodeScalarValue, Storage);
2037*9880d681SAndroid Build Coastguard Worker           UnquotedValue = UnquotedValue.substr(4);
2038*9880d681SAndroid Build Coastguard Worker           break;
2039*9880d681SAndroid Build Coastguard Worker         }
2040*9880d681SAndroid Build Coastguard Worker       case 'U': {
2041*9880d681SAndroid Build Coastguard Worker           if (UnquotedValue.size() < 9)
2042*9880d681SAndroid Build Coastguard Worker             // TODO: Report error.
2043*9880d681SAndroid Build Coastguard Worker             break;
2044*9880d681SAndroid Build Coastguard Worker           unsigned int UnicodeScalarValue;
2045*9880d681SAndroid Build Coastguard Worker           if (UnquotedValue.substr(1, 8).getAsInteger(16, UnicodeScalarValue))
2046*9880d681SAndroid Build Coastguard Worker             // TODO: Report error.
2047*9880d681SAndroid Build Coastguard Worker             UnicodeScalarValue = 0xFFFD;
2048*9880d681SAndroid Build Coastguard Worker           encodeUTF8(UnicodeScalarValue, Storage);
2049*9880d681SAndroid Build Coastguard Worker           UnquotedValue = UnquotedValue.substr(8);
2050*9880d681SAndroid Build Coastguard Worker           break;
2051*9880d681SAndroid Build Coastguard Worker         }
2052*9880d681SAndroid Build Coastguard Worker       }
2053*9880d681SAndroid Build Coastguard Worker       UnquotedValue = UnquotedValue.substr(1);
2054*9880d681SAndroid Build Coastguard Worker     }
2055*9880d681SAndroid Build Coastguard Worker   }
2056*9880d681SAndroid Build Coastguard Worker   Storage.insert(Storage.end(), UnquotedValue.begin(), UnquotedValue.end());
2057*9880d681SAndroid Build Coastguard Worker   return StringRef(Storage.begin(), Storage.size());
2058*9880d681SAndroid Build Coastguard Worker }
2059*9880d681SAndroid Build Coastguard Worker 
getKey()2060*9880d681SAndroid Build Coastguard Worker Node *KeyValueNode::getKey() {
2061*9880d681SAndroid Build Coastguard Worker   if (Key)
2062*9880d681SAndroid Build Coastguard Worker     return Key;
2063*9880d681SAndroid Build Coastguard Worker   // Handle implicit null keys.
2064*9880d681SAndroid Build Coastguard Worker   {
2065*9880d681SAndroid Build Coastguard Worker     Token &t = peekNext();
2066*9880d681SAndroid Build Coastguard Worker     if (   t.Kind == Token::TK_BlockEnd
2067*9880d681SAndroid Build Coastguard Worker         || t.Kind == Token::TK_Value
2068*9880d681SAndroid Build Coastguard Worker         || t.Kind == Token::TK_Error) {
2069*9880d681SAndroid Build Coastguard Worker       return Key = new (getAllocator()) NullNode(Doc);
2070*9880d681SAndroid Build Coastguard Worker     }
2071*9880d681SAndroid Build Coastguard Worker     if (t.Kind == Token::TK_Key)
2072*9880d681SAndroid Build Coastguard Worker       getNext(); // skip TK_Key.
2073*9880d681SAndroid Build Coastguard Worker   }
2074*9880d681SAndroid Build Coastguard Worker 
2075*9880d681SAndroid Build Coastguard Worker   // Handle explicit null keys.
2076*9880d681SAndroid Build Coastguard Worker   Token &t = peekNext();
2077*9880d681SAndroid Build Coastguard Worker   if (t.Kind == Token::TK_BlockEnd || t.Kind == Token::TK_Value) {
2078*9880d681SAndroid Build Coastguard Worker     return Key = new (getAllocator()) NullNode(Doc);
2079*9880d681SAndroid Build Coastguard Worker   }
2080*9880d681SAndroid Build Coastguard Worker 
2081*9880d681SAndroid Build Coastguard Worker   // We've got a normal key.
2082*9880d681SAndroid Build Coastguard Worker   return Key = parseBlockNode();
2083*9880d681SAndroid Build Coastguard Worker }
2084*9880d681SAndroid Build Coastguard Worker 
getValue()2085*9880d681SAndroid Build Coastguard Worker Node *KeyValueNode::getValue() {
2086*9880d681SAndroid Build Coastguard Worker   if (Value)
2087*9880d681SAndroid Build Coastguard Worker     return Value;
2088*9880d681SAndroid Build Coastguard Worker   getKey()->skip();
2089*9880d681SAndroid Build Coastguard Worker   if (failed())
2090*9880d681SAndroid Build Coastguard Worker     return Value = new (getAllocator()) NullNode(Doc);
2091*9880d681SAndroid Build Coastguard Worker 
2092*9880d681SAndroid Build Coastguard Worker   // Handle implicit null values.
2093*9880d681SAndroid Build Coastguard Worker   {
2094*9880d681SAndroid Build Coastguard Worker     Token &t = peekNext();
2095*9880d681SAndroid Build Coastguard Worker     if (   t.Kind == Token::TK_BlockEnd
2096*9880d681SAndroid Build Coastguard Worker         || t.Kind == Token::TK_FlowMappingEnd
2097*9880d681SAndroid Build Coastguard Worker         || t.Kind == Token::TK_Key
2098*9880d681SAndroid Build Coastguard Worker         || t.Kind == Token::TK_FlowEntry
2099*9880d681SAndroid Build Coastguard Worker         || t.Kind == Token::TK_Error) {
2100*9880d681SAndroid Build Coastguard Worker       return Value = new (getAllocator()) NullNode(Doc);
2101*9880d681SAndroid Build Coastguard Worker     }
2102*9880d681SAndroid Build Coastguard Worker 
2103*9880d681SAndroid Build Coastguard Worker     if (t.Kind != Token::TK_Value) {
2104*9880d681SAndroid Build Coastguard Worker       setError("Unexpected token in Key Value.", t);
2105*9880d681SAndroid Build Coastguard Worker       return Value = new (getAllocator()) NullNode(Doc);
2106*9880d681SAndroid Build Coastguard Worker     }
2107*9880d681SAndroid Build Coastguard Worker     getNext(); // skip TK_Value.
2108*9880d681SAndroid Build Coastguard Worker   }
2109*9880d681SAndroid Build Coastguard Worker 
2110*9880d681SAndroid Build Coastguard Worker   // Handle explicit null values.
2111*9880d681SAndroid Build Coastguard Worker   Token &t = peekNext();
2112*9880d681SAndroid Build Coastguard Worker   if (t.Kind == Token::TK_BlockEnd || t.Kind == Token::TK_Key) {
2113*9880d681SAndroid Build Coastguard Worker     return Value = new (getAllocator()) NullNode(Doc);
2114*9880d681SAndroid Build Coastguard Worker   }
2115*9880d681SAndroid Build Coastguard Worker 
2116*9880d681SAndroid Build Coastguard Worker   // We got a normal value.
2117*9880d681SAndroid Build Coastguard Worker   return Value = parseBlockNode();
2118*9880d681SAndroid Build Coastguard Worker }
2119*9880d681SAndroid Build Coastguard Worker 
increment()2120*9880d681SAndroid Build Coastguard Worker void MappingNode::increment() {
2121*9880d681SAndroid Build Coastguard Worker   if (failed()) {
2122*9880d681SAndroid Build Coastguard Worker     IsAtEnd = true;
2123*9880d681SAndroid Build Coastguard Worker     CurrentEntry = nullptr;
2124*9880d681SAndroid Build Coastguard Worker     return;
2125*9880d681SAndroid Build Coastguard Worker   }
2126*9880d681SAndroid Build Coastguard Worker   if (CurrentEntry) {
2127*9880d681SAndroid Build Coastguard Worker     CurrentEntry->skip();
2128*9880d681SAndroid Build Coastguard Worker     if (Type == MT_Inline) {
2129*9880d681SAndroid Build Coastguard Worker       IsAtEnd = true;
2130*9880d681SAndroid Build Coastguard Worker       CurrentEntry = nullptr;
2131*9880d681SAndroid Build Coastguard Worker       return;
2132*9880d681SAndroid Build Coastguard Worker     }
2133*9880d681SAndroid Build Coastguard Worker   }
2134*9880d681SAndroid Build Coastguard Worker   Token T = peekNext();
2135*9880d681SAndroid Build Coastguard Worker   if (T.Kind == Token::TK_Key || T.Kind == Token::TK_Scalar) {
2136*9880d681SAndroid Build Coastguard Worker     // KeyValueNode eats the TK_Key. That way it can detect null keys.
2137*9880d681SAndroid Build Coastguard Worker     CurrentEntry = new (getAllocator()) KeyValueNode(Doc);
2138*9880d681SAndroid Build Coastguard Worker   } else if (Type == MT_Block) {
2139*9880d681SAndroid Build Coastguard Worker     switch (T.Kind) {
2140*9880d681SAndroid Build Coastguard Worker     case Token::TK_BlockEnd:
2141*9880d681SAndroid Build Coastguard Worker       getNext();
2142*9880d681SAndroid Build Coastguard Worker       IsAtEnd = true;
2143*9880d681SAndroid Build Coastguard Worker       CurrentEntry = nullptr;
2144*9880d681SAndroid Build Coastguard Worker       break;
2145*9880d681SAndroid Build Coastguard Worker     default:
2146*9880d681SAndroid Build Coastguard Worker       setError("Unexpected token. Expected Key or Block End", T);
2147*9880d681SAndroid Build Coastguard Worker     case Token::TK_Error:
2148*9880d681SAndroid Build Coastguard Worker       IsAtEnd = true;
2149*9880d681SAndroid Build Coastguard Worker       CurrentEntry = nullptr;
2150*9880d681SAndroid Build Coastguard Worker     }
2151*9880d681SAndroid Build Coastguard Worker   } else {
2152*9880d681SAndroid Build Coastguard Worker     switch (T.Kind) {
2153*9880d681SAndroid Build Coastguard Worker     case Token::TK_FlowEntry:
2154*9880d681SAndroid Build Coastguard Worker       // Eat the flow entry and recurse.
2155*9880d681SAndroid Build Coastguard Worker       getNext();
2156*9880d681SAndroid Build Coastguard Worker       return increment();
2157*9880d681SAndroid Build Coastguard Worker     case Token::TK_FlowMappingEnd:
2158*9880d681SAndroid Build Coastguard Worker       getNext();
2159*9880d681SAndroid Build Coastguard Worker     case Token::TK_Error:
2160*9880d681SAndroid Build Coastguard Worker       // Set this to end iterator.
2161*9880d681SAndroid Build Coastguard Worker       IsAtEnd = true;
2162*9880d681SAndroid Build Coastguard Worker       CurrentEntry = nullptr;
2163*9880d681SAndroid Build Coastguard Worker       break;
2164*9880d681SAndroid Build Coastguard Worker     default:
2165*9880d681SAndroid Build Coastguard Worker       setError( "Unexpected token. Expected Key, Flow Entry, or Flow "
2166*9880d681SAndroid Build Coastguard Worker                 "Mapping End."
2167*9880d681SAndroid Build Coastguard Worker               , T);
2168*9880d681SAndroid Build Coastguard Worker       IsAtEnd = true;
2169*9880d681SAndroid Build Coastguard Worker       CurrentEntry = nullptr;
2170*9880d681SAndroid Build Coastguard Worker     }
2171*9880d681SAndroid Build Coastguard Worker   }
2172*9880d681SAndroid Build Coastguard Worker }
2173*9880d681SAndroid Build Coastguard Worker 
increment()2174*9880d681SAndroid Build Coastguard Worker void SequenceNode::increment() {
2175*9880d681SAndroid Build Coastguard Worker   if (failed()) {
2176*9880d681SAndroid Build Coastguard Worker     IsAtEnd = true;
2177*9880d681SAndroid Build Coastguard Worker     CurrentEntry = nullptr;
2178*9880d681SAndroid Build Coastguard Worker     return;
2179*9880d681SAndroid Build Coastguard Worker   }
2180*9880d681SAndroid Build Coastguard Worker   if (CurrentEntry)
2181*9880d681SAndroid Build Coastguard Worker     CurrentEntry->skip();
2182*9880d681SAndroid Build Coastguard Worker   Token T = peekNext();
2183*9880d681SAndroid Build Coastguard Worker   if (SeqType == ST_Block) {
2184*9880d681SAndroid Build Coastguard Worker     switch (T.Kind) {
2185*9880d681SAndroid Build Coastguard Worker     case Token::TK_BlockEntry:
2186*9880d681SAndroid Build Coastguard Worker       getNext();
2187*9880d681SAndroid Build Coastguard Worker       CurrentEntry = parseBlockNode();
2188*9880d681SAndroid Build Coastguard Worker       if (!CurrentEntry) { // An error occurred.
2189*9880d681SAndroid Build Coastguard Worker         IsAtEnd = true;
2190*9880d681SAndroid Build Coastguard Worker         CurrentEntry = nullptr;
2191*9880d681SAndroid Build Coastguard Worker       }
2192*9880d681SAndroid Build Coastguard Worker       break;
2193*9880d681SAndroid Build Coastguard Worker     case Token::TK_BlockEnd:
2194*9880d681SAndroid Build Coastguard Worker       getNext();
2195*9880d681SAndroid Build Coastguard Worker       IsAtEnd = true;
2196*9880d681SAndroid Build Coastguard Worker       CurrentEntry = nullptr;
2197*9880d681SAndroid Build Coastguard Worker       break;
2198*9880d681SAndroid Build Coastguard Worker     default:
2199*9880d681SAndroid Build Coastguard Worker       setError( "Unexpected token. Expected Block Entry or Block End."
2200*9880d681SAndroid Build Coastguard Worker               , T);
2201*9880d681SAndroid Build Coastguard Worker     case Token::TK_Error:
2202*9880d681SAndroid Build Coastguard Worker       IsAtEnd = true;
2203*9880d681SAndroid Build Coastguard Worker       CurrentEntry = nullptr;
2204*9880d681SAndroid Build Coastguard Worker     }
2205*9880d681SAndroid Build Coastguard Worker   } else if (SeqType == ST_Indentless) {
2206*9880d681SAndroid Build Coastguard Worker     switch (T.Kind) {
2207*9880d681SAndroid Build Coastguard Worker     case Token::TK_BlockEntry:
2208*9880d681SAndroid Build Coastguard Worker       getNext();
2209*9880d681SAndroid Build Coastguard Worker       CurrentEntry = parseBlockNode();
2210*9880d681SAndroid Build Coastguard Worker       if (!CurrentEntry) { // An error occurred.
2211*9880d681SAndroid Build Coastguard Worker         IsAtEnd = true;
2212*9880d681SAndroid Build Coastguard Worker         CurrentEntry = nullptr;
2213*9880d681SAndroid Build Coastguard Worker       }
2214*9880d681SAndroid Build Coastguard Worker       break;
2215*9880d681SAndroid Build Coastguard Worker     default:
2216*9880d681SAndroid Build Coastguard Worker     case Token::TK_Error:
2217*9880d681SAndroid Build Coastguard Worker       IsAtEnd = true;
2218*9880d681SAndroid Build Coastguard Worker       CurrentEntry = nullptr;
2219*9880d681SAndroid Build Coastguard Worker     }
2220*9880d681SAndroid Build Coastguard Worker   } else if (SeqType == ST_Flow) {
2221*9880d681SAndroid Build Coastguard Worker     switch (T.Kind) {
2222*9880d681SAndroid Build Coastguard Worker     case Token::TK_FlowEntry:
2223*9880d681SAndroid Build Coastguard Worker       // Eat the flow entry and recurse.
2224*9880d681SAndroid Build Coastguard Worker       getNext();
2225*9880d681SAndroid Build Coastguard Worker       WasPreviousTokenFlowEntry = true;
2226*9880d681SAndroid Build Coastguard Worker       return increment();
2227*9880d681SAndroid Build Coastguard Worker     case Token::TK_FlowSequenceEnd:
2228*9880d681SAndroid Build Coastguard Worker       getNext();
2229*9880d681SAndroid Build Coastguard Worker     case Token::TK_Error:
2230*9880d681SAndroid Build Coastguard Worker       // Set this to end iterator.
2231*9880d681SAndroid Build Coastguard Worker       IsAtEnd = true;
2232*9880d681SAndroid Build Coastguard Worker       CurrentEntry = nullptr;
2233*9880d681SAndroid Build Coastguard Worker       break;
2234*9880d681SAndroid Build Coastguard Worker     case Token::TK_StreamEnd:
2235*9880d681SAndroid Build Coastguard Worker     case Token::TK_DocumentEnd:
2236*9880d681SAndroid Build Coastguard Worker     case Token::TK_DocumentStart:
2237*9880d681SAndroid Build Coastguard Worker       setError("Could not find closing ]!", T);
2238*9880d681SAndroid Build Coastguard Worker       // Set this to end iterator.
2239*9880d681SAndroid Build Coastguard Worker       IsAtEnd = true;
2240*9880d681SAndroid Build Coastguard Worker       CurrentEntry = nullptr;
2241*9880d681SAndroid Build Coastguard Worker       break;
2242*9880d681SAndroid Build Coastguard Worker     default:
2243*9880d681SAndroid Build Coastguard Worker       if (!WasPreviousTokenFlowEntry) {
2244*9880d681SAndroid Build Coastguard Worker         setError("Expected , between entries!", T);
2245*9880d681SAndroid Build Coastguard Worker         IsAtEnd = true;
2246*9880d681SAndroid Build Coastguard Worker         CurrentEntry = nullptr;
2247*9880d681SAndroid Build Coastguard Worker         break;
2248*9880d681SAndroid Build Coastguard Worker       }
2249*9880d681SAndroid Build Coastguard Worker       // Otherwise it must be a flow entry.
2250*9880d681SAndroid Build Coastguard Worker       CurrentEntry = parseBlockNode();
2251*9880d681SAndroid Build Coastguard Worker       if (!CurrentEntry) {
2252*9880d681SAndroid Build Coastguard Worker         IsAtEnd = true;
2253*9880d681SAndroid Build Coastguard Worker       }
2254*9880d681SAndroid Build Coastguard Worker       WasPreviousTokenFlowEntry = false;
2255*9880d681SAndroid Build Coastguard Worker       break;
2256*9880d681SAndroid Build Coastguard Worker     }
2257*9880d681SAndroid Build Coastguard Worker   }
2258*9880d681SAndroid Build Coastguard Worker }
2259*9880d681SAndroid Build Coastguard Worker 
Document(Stream & S)2260*9880d681SAndroid Build Coastguard Worker Document::Document(Stream &S) : stream(S), Root(nullptr) {
2261*9880d681SAndroid Build Coastguard Worker   // Tag maps starts with two default mappings.
2262*9880d681SAndroid Build Coastguard Worker   TagMap["!"] = "!";
2263*9880d681SAndroid Build Coastguard Worker   TagMap["!!"] = "tag:yaml.org,2002:";
2264*9880d681SAndroid Build Coastguard Worker 
2265*9880d681SAndroid Build Coastguard Worker   if (parseDirectives())
2266*9880d681SAndroid Build Coastguard Worker     expectToken(Token::TK_DocumentStart);
2267*9880d681SAndroid Build Coastguard Worker   Token &T = peekNext();
2268*9880d681SAndroid Build Coastguard Worker   if (T.Kind == Token::TK_DocumentStart)
2269*9880d681SAndroid Build Coastguard Worker     getNext();
2270*9880d681SAndroid Build Coastguard Worker }
2271*9880d681SAndroid Build Coastguard Worker 
skip()2272*9880d681SAndroid Build Coastguard Worker bool Document::skip()  {
2273*9880d681SAndroid Build Coastguard Worker   if (stream.scanner->failed())
2274*9880d681SAndroid Build Coastguard Worker     return false;
2275*9880d681SAndroid Build Coastguard Worker   if (!Root)
2276*9880d681SAndroid Build Coastguard Worker     getRoot();
2277*9880d681SAndroid Build Coastguard Worker   Root->skip();
2278*9880d681SAndroid Build Coastguard Worker   Token &T = peekNext();
2279*9880d681SAndroid Build Coastguard Worker   if (T.Kind == Token::TK_StreamEnd)
2280*9880d681SAndroid Build Coastguard Worker     return false;
2281*9880d681SAndroid Build Coastguard Worker   if (T.Kind == Token::TK_DocumentEnd) {
2282*9880d681SAndroid Build Coastguard Worker     getNext();
2283*9880d681SAndroid Build Coastguard Worker     return skip();
2284*9880d681SAndroid Build Coastguard Worker   }
2285*9880d681SAndroid Build Coastguard Worker   return true;
2286*9880d681SAndroid Build Coastguard Worker }
2287*9880d681SAndroid Build Coastguard Worker 
peekNext()2288*9880d681SAndroid Build Coastguard Worker Token &Document::peekNext() {
2289*9880d681SAndroid Build Coastguard Worker   return stream.scanner->peekNext();
2290*9880d681SAndroid Build Coastguard Worker }
2291*9880d681SAndroid Build Coastguard Worker 
getNext()2292*9880d681SAndroid Build Coastguard Worker Token Document::getNext() {
2293*9880d681SAndroid Build Coastguard Worker   return stream.scanner->getNext();
2294*9880d681SAndroid Build Coastguard Worker }
2295*9880d681SAndroid Build Coastguard Worker 
setError(const Twine & Message,Token & Location) const2296*9880d681SAndroid Build Coastguard Worker void Document::setError(const Twine &Message, Token &Location) const {
2297*9880d681SAndroid Build Coastguard Worker   stream.scanner->setError(Message, Location.Range.begin());
2298*9880d681SAndroid Build Coastguard Worker }
2299*9880d681SAndroid Build Coastguard Worker 
failed() const2300*9880d681SAndroid Build Coastguard Worker bool Document::failed() const {
2301*9880d681SAndroid Build Coastguard Worker   return stream.scanner->failed();
2302*9880d681SAndroid Build Coastguard Worker }
2303*9880d681SAndroid Build Coastguard Worker 
parseBlockNode()2304*9880d681SAndroid Build Coastguard Worker Node *Document::parseBlockNode() {
2305*9880d681SAndroid Build Coastguard Worker   Token T = peekNext();
2306*9880d681SAndroid Build Coastguard Worker   // Handle properties.
2307*9880d681SAndroid Build Coastguard Worker   Token AnchorInfo;
2308*9880d681SAndroid Build Coastguard Worker   Token TagInfo;
2309*9880d681SAndroid Build Coastguard Worker parse_property:
2310*9880d681SAndroid Build Coastguard Worker   switch (T.Kind) {
2311*9880d681SAndroid Build Coastguard Worker   case Token::TK_Alias:
2312*9880d681SAndroid Build Coastguard Worker     getNext();
2313*9880d681SAndroid Build Coastguard Worker     return new (NodeAllocator) AliasNode(stream.CurrentDoc, T.Range.substr(1));
2314*9880d681SAndroid Build Coastguard Worker   case Token::TK_Anchor:
2315*9880d681SAndroid Build Coastguard Worker     if (AnchorInfo.Kind == Token::TK_Anchor) {
2316*9880d681SAndroid Build Coastguard Worker       setError("Already encountered an anchor for this node!", T);
2317*9880d681SAndroid Build Coastguard Worker       return nullptr;
2318*9880d681SAndroid Build Coastguard Worker     }
2319*9880d681SAndroid Build Coastguard Worker     AnchorInfo = getNext(); // Consume TK_Anchor.
2320*9880d681SAndroid Build Coastguard Worker     T = peekNext();
2321*9880d681SAndroid Build Coastguard Worker     goto parse_property;
2322*9880d681SAndroid Build Coastguard Worker   case Token::TK_Tag:
2323*9880d681SAndroid Build Coastguard Worker     if (TagInfo.Kind == Token::TK_Tag) {
2324*9880d681SAndroid Build Coastguard Worker       setError("Already encountered a tag for this node!", T);
2325*9880d681SAndroid Build Coastguard Worker       return nullptr;
2326*9880d681SAndroid Build Coastguard Worker     }
2327*9880d681SAndroid Build Coastguard Worker     TagInfo = getNext(); // Consume TK_Tag.
2328*9880d681SAndroid Build Coastguard Worker     T = peekNext();
2329*9880d681SAndroid Build Coastguard Worker     goto parse_property;
2330*9880d681SAndroid Build Coastguard Worker   default:
2331*9880d681SAndroid Build Coastguard Worker     break;
2332*9880d681SAndroid Build Coastguard Worker   }
2333*9880d681SAndroid Build Coastguard Worker 
2334*9880d681SAndroid Build Coastguard Worker   switch (T.Kind) {
2335*9880d681SAndroid Build Coastguard Worker   case Token::TK_BlockEntry:
2336*9880d681SAndroid Build Coastguard Worker     // We got an unindented BlockEntry sequence. This is not terminated with
2337*9880d681SAndroid Build Coastguard Worker     // a BlockEnd.
2338*9880d681SAndroid Build Coastguard Worker     // Don't eat the TK_BlockEntry, SequenceNode needs it.
2339*9880d681SAndroid Build Coastguard Worker     return new (NodeAllocator) SequenceNode( stream.CurrentDoc
2340*9880d681SAndroid Build Coastguard Worker                                            , AnchorInfo.Range.substr(1)
2341*9880d681SAndroid Build Coastguard Worker                                            , TagInfo.Range
2342*9880d681SAndroid Build Coastguard Worker                                            , SequenceNode::ST_Indentless);
2343*9880d681SAndroid Build Coastguard Worker   case Token::TK_BlockSequenceStart:
2344*9880d681SAndroid Build Coastguard Worker     getNext();
2345*9880d681SAndroid Build Coastguard Worker     return new (NodeAllocator)
2346*9880d681SAndroid Build Coastguard Worker       SequenceNode( stream.CurrentDoc
2347*9880d681SAndroid Build Coastguard Worker                   , AnchorInfo.Range.substr(1)
2348*9880d681SAndroid Build Coastguard Worker                   , TagInfo.Range
2349*9880d681SAndroid Build Coastguard Worker                   , SequenceNode::ST_Block);
2350*9880d681SAndroid Build Coastguard Worker   case Token::TK_BlockMappingStart:
2351*9880d681SAndroid Build Coastguard Worker     getNext();
2352*9880d681SAndroid Build Coastguard Worker     return new (NodeAllocator)
2353*9880d681SAndroid Build Coastguard Worker       MappingNode( stream.CurrentDoc
2354*9880d681SAndroid Build Coastguard Worker                  , AnchorInfo.Range.substr(1)
2355*9880d681SAndroid Build Coastguard Worker                  , TagInfo.Range
2356*9880d681SAndroid Build Coastguard Worker                  , MappingNode::MT_Block);
2357*9880d681SAndroid Build Coastguard Worker   case Token::TK_FlowSequenceStart:
2358*9880d681SAndroid Build Coastguard Worker     getNext();
2359*9880d681SAndroid Build Coastguard Worker     return new (NodeAllocator)
2360*9880d681SAndroid Build Coastguard Worker       SequenceNode( stream.CurrentDoc
2361*9880d681SAndroid Build Coastguard Worker                   , AnchorInfo.Range.substr(1)
2362*9880d681SAndroid Build Coastguard Worker                   , TagInfo.Range
2363*9880d681SAndroid Build Coastguard Worker                   , SequenceNode::ST_Flow);
2364*9880d681SAndroid Build Coastguard Worker   case Token::TK_FlowMappingStart:
2365*9880d681SAndroid Build Coastguard Worker     getNext();
2366*9880d681SAndroid Build Coastguard Worker     return new (NodeAllocator)
2367*9880d681SAndroid Build Coastguard Worker       MappingNode( stream.CurrentDoc
2368*9880d681SAndroid Build Coastguard Worker                  , AnchorInfo.Range.substr(1)
2369*9880d681SAndroid Build Coastguard Worker                  , TagInfo.Range
2370*9880d681SAndroid Build Coastguard Worker                  , MappingNode::MT_Flow);
2371*9880d681SAndroid Build Coastguard Worker   case Token::TK_Scalar:
2372*9880d681SAndroid Build Coastguard Worker     getNext();
2373*9880d681SAndroid Build Coastguard Worker     return new (NodeAllocator)
2374*9880d681SAndroid Build Coastguard Worker       ScalarNode( stream.CurrentDoc
2375*9880d681SAndroid Build Coastguard Worker                 , AnchorInfo.Range.substr(1)
2376*9880d681SAndroid Build Coastguard Worker                 , TagInfo.Range
2377*9880d681SAndroid Build Coastguard Worker                 , T.Range);
2378*9880d681SAndroid Build Coastguard Worker   case Token::TK_BlockScalar: {
2379*9880d681SAndroid Build Coastguard Worker     getNext();
2380*9880d681SAndroid Build Coastguard Worker     StringRef NullTerminatedStr(T.Value.c_str(), T.Value.length() + 1);
2381*9880d681SAndroid Build Coastguard Worker     StringRef StrCopy = NullTerminatedStr.copy(NodeAllocator).drop_back();
2382*9880d681SAndroid Build Coastguard Worker     return new (NodeAllocator)
2383*9880d681SAndroid Build Coastguard Worker         BlockScalarNode(stream.CurrentDoc, AnchorInfo.Range.substr(1),
2384*9880d681SAndroid Build Coastguard Worker                         TagInfo.Range, StrCopy, T.Range);
2385*9880d681SAndroid Build Coastguard Worker   }
2386*9880d681SAndroid Build Coastguard Worker   case Token::TK_Key:
2387*9880d681SAndroid Build Coastguard Worker     // Don't eat the TK_Key, KeyValueNode expects it.
2388*9880d681SAndroid Build Coastguard Worker     return new (NodeAllocator)
2389*9880d681SAndroid Build Coastguard Worker       MappingNode( stream.CurrentDoc
2390*9880d681SAndroid Build Coastguard Worker                  , AnchorInfo.Range.substr(1)
2391*9880d681SAndroid Build Coastguard Worker                  , TagInfo.Range
2392*9880d681SAndroid Build Coastguard Worker                  , MappingNode::MT_Inline);
2393*9880d681SAndroid Build Coastguard Worker   case Token::TK_DocumentStart:
2394*9880d681SAndroid Build Coastguard Worker   case Token::TK_DocumentEnd:
2395*9880d681SAndroid Build Coastguard Worker   case Token::TK_StreamEnd:
2396*9880d681SAndroid Build Coastguard Worker   default:
2397*9880d681SAndroid Build Coastguard Worker     // TODO: Properly handle tags. "[!!str ]" should resolve to !!str "", not
2398*9880d681SAndroid Build Coastguard Worker     //       !!null null.
2399*9880d681SAndroid Build Coastguard Worker     return new (NodeAllocator) NullNode(stream.CurrentDoc);
2400*9880d681SAndroid Build Coastguard Worker   case Token::TK_Error:
2401*9880d681SAndroid Build Coastguard Worker     return nullptr;
2402*9880d681SAndroid Build Coastguard Worker   }
2403*9880d681SAndroid Build Coastguard Worker   llvm_unreachable("Control flow shouldn't reach here.");
2404*9880d681SAndroid Build Coastguard Worker   return nullptr;
2405*9880d681SAndroid Build Coastguard Worker }
2406*9880d681SAndroid Build Coastguard Worker 
parseDirectives()2407*9880d681SAndroid Build Coastguard Worker bool Document::parseDirectives() {
2408*9880d681SAndroid Build Coastguard Worker   bool isDirective = false;
2409*9880d681SAndroid Build Coastguard Worker   while (true) {
2410*9880d681SAndroid Build Coastguard Worker     Token T = peekNext();
2411*9880d681SAndroid Build Coastguard Worker     if (T.Kind == Token::TK_TagDirective) {
2412*9880d681SAndroid Build Coastguard Worker       parseTAGDirective();
2413*9880d681SAndroid Build Coastguard Worker       isDirective = true;
2414*9880d681SAndroid Build Coastguard Worker     } else if (T.Kind == Token::TK_VersionDirective) {
2415*9880d681SAndroid Build Coastguard Worker       parseYAMLDirective();
2416*9880d681SAndroid Build Coastguard Worker       isDirective = true;
2417*9880d681SAndroid Build Coastguard Worker     } else
2418*9880d681SAndroid Build Coastguard Worker       break;
2419*9880d681SAndroid Build Coastguard Worker   }
2420*9880d681SAndroid Build Coastguard Worker   return isDirective;
2421*9880d681SAndroid Build Coastguard Worker }
2422*9880d681SAndroid Build Coastguard Worker 
parseYAMLDirective()2423*9880d681SAndroid Build Coastguard Worker void Document::parseYAMLDirective() {
2424*9880d681SAndroid Build Coastguard Worker   getNext(); // Eat %YAML <version>
2425*9880d681SAndroid Build Coastguard Worker }
2426*9880d681SAndroid Build Coastguard Worker 
parseTAGDirective()2427*9880d681SAndroid Build Coastguard Worker void Document::parseTAGDirective() {
2428*9880d681SAndroid Build Coastguard Worker   Token Tag = getNext(); // %TAG <handle> <prefix>
2429*9880d681SAndroid Build Coastguard Worker   StringRef T = Tag.Range;
2430*9880d681SAndroid Build Coastguard Worker   // Strip %TAG
2431*9880d681SAndroid Build Coastguard Worker   T = T.substr(T.find_first_of(" \t")).ltrim(" \t");
2432*9880d681SAndroid Build Coastguard Worker   std::size_t HandleEnd = T.find_first_of(" \t");
2433*9880d681SAndroid Build Coastguard Worker   StringRef TagHandle = T.substr(0, HandleEnd);
2434*9880d681SAndroid Build Coastguard Worker   StringRef TagPrefix = T.substr(HandleEnd).ltrim(" \t");
2435*9880d681SAndroid Build Coastguard Worker   TagMap[TagHandle] = TagPrefix;
2436*9880d681SAndroid Build Coastguard Worker }
2437*9880d681SAndroid Build Coastguard Worker 
expectToken(int TK)2438*9880d681SAndroid Build Coastguard Worker bool Document::expectToken(int TK) {
2439*9880d681SAndroid Build Coastguard Worker   Token T = getNext();
2440*9880d681SAndroid Build Coastguard Worker   if (T.Kind != TK) {
2441*9880d681SAndroid Build Coastguard Worker     setError("Unexpected token", T);
2442*9880d681SAndroid Build Coastguard Worker     return false;
2443*9880d681SAndroid Build Coastguard Worker   }
2444*9880d681SAndroid Build Coastguard Worker   return true;
2445*9880d681SAndroid Build Coastguard Worker }
2446