1 //===--- YAMLParser.h - Simple YAML parser --------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This is a YAML 1.2 parser. 11 // 12 // See http://www.yaml.org/spec/1.2/spec.html for the full standard. 13 // 14 // This currently does not implement the following: 15 // * Multi-line literal folding. 16 // * Tag resolution. 17 // * UTF-16. 18 // * BOMs anywhere other than the first Unicode scalar value in the file. 19 // 20 // The most important class here is Stream. This represents a YAML stream with 21 // 0, 1, or many documents. 22 // 23 // SourceMgr sm; 24 // StringRef input = getInput(); 25 // yaml::Stream stream(input, sm); 26 // 27 // for (yaml::document_iterator di = stream.begin(), de = stream.end(); 28 // di != de; ++di) { 29 // yaml::Node *n = di->getRoot(); 30 // if (n) { 31 // // Do something with n... 32 // } else 33 // break; 34 // } 35 // 36 //===----------------------------------------------------------------------===// 37 38 #ifndef LLVM_SUPPORT_YAMLPARSER_H 39 #define LLVM_SUPPORT_YAMLPARSER_H 40 41 #include "llvm/ADT/OwningPtr.h" 42 #include "llvm/ADT/SmallString.h" 43 #include "llvm/ADT/StringRef.h" 44 #include "llvm/Support/Allocator.h" 45 #include "llvm/Support/SMLoc.h" 46 #include <limits> 47 #include <map> 48 #include <utility> 49 50 namespace llvm { 51 class MemoryBuffer; 52 class SourceMgr; 53 class raw_ostream; 54 class Twine; 55 56 namespace yaml { 57 58 class document_iterator; 59 class Document; 60 class Node; 61 class Scanner; 62 struct Token; 63 64 /// @brief Dump all the tokens in this stream to OS. 65 /// @returns true if there was an error, false otherwise. 66 bool dumpTokens(StringRef Input, raw_ostream &); 67 68 /// @brief Scans all tokens in input without outputting anything. This is used 69 /// for benchmarking the tokenizer. 70 /// @returns true if there was an error, false otherwise. 71 bool scanTokens(StringRef Input); 72 73 /// @brief Escape \a Input for a double quoted scalar. 74 std::string escape(StringRef Input); 75 76 /// @brief This class represents a YAML stream potentially containing multiple 77 /// documents. 78 class Stream { 79 public: 80 /// @brief This keeps a reference to the string referenced by \p Input. 81 Stream(StringRef Input, SourceMgr &); 82 83 /// @brief This takes ownership of \p InputBuffer. 84 Stream(MemoryBuffer *InputBuffer, SourceMgr &); 85 ~Stream(); 86 87 document_iterator begin(); 88 document_iterator end(); 89 void skip(); 90 bool failed(); 91 bool validate() { 92 skip(); 93 return !failed(); 94 } 95 96 void printError(Node *N, const Twine &Msg); 97 98 private: 99 OwningPtr<Scanner> scanner; 100 OwningPtr<Document> CurrentDoc; 101 102 friend class Document; 103 }; 104 105 /// @brief Abstract base class for all Nodes. 106 class Node { 107 virtual void anchor(); 108 public: 109 enum NodeKind { 110 NK_Null, 111 NK_Scalar, 112 NK_KeyValue, 113 NK_Mapping, 114 NK_Sequence, 115 NK_Alias 116 }; 117 118 Node(unsigned int Type, OwningPtr<Document> &, StringRef Anchor, 119 StringRef Tag); 120 121 /// @brief Get the value of the anchor attached to this node. If it does not 122 /// have one, getAnchor().size() will be 0. 123 StringRef getAnchor() const { return Anchor; } 124 125 /// \brief Get the tag as it was written in the document. This does not 126 /// perform tag resolution. 127 StringRef getRawTag() const { return Tag; } 128 129 /// \brief Get the verbatium tag for a given Node. This performs tag resoluton 130 /// and substitution. 131 std::string getVerbatimTag() const; 132 133 SMRange getSourceRange() const { return SourceRange; } 134 void setSourceRange(SMRange SR) { SourceRange = SR; } 135 136 // These functions forward to Document and Scanner. 137 Token &peekNext(); 138 Token getNext(); 139 Node *parseBlockNode(); 140 BumpPtrAllocator &getAllocator(); 141 void setError(const Twine &Message, Token &Location) const; 142 bool failed() const; 143 144 virtual void skip() {} 145 146 unsigned int getType() const { return TypeID; } 147 148 void *operator new ( size_t Size 149 , BumpPtrAllocator &Alloc 150 , size_t Alignment = 16) throw() { 151 return Alloc.Allocate(Size, Alignment); 152 } 153 154 void operator delete(void *Ptr, BumpPtrAllocator &Alloc, size_t) throw() { 155 Alloc.Deallocate(Ptr); 156 } 157 158 protected: 159 OwningPtr<Document> &Doc; 160 SMRange SourceRange; 161 162 void operator delete(void *) throw() {} 163 164 virtual ~Node() {} 165 166 private: 167 unsigned int TypeID; 168 StringRef Anchor; 169 /// \brief The tag as typed in the document. 170 StringRef Tag; 171 }; 172 173 /// @brief A null value. 174 /// 175 /// Example: 176 /// !!null null 177 class NullNode : public Node { 178 virtual void anchor(); 179 public: 180 NullNode(OwningPtr<Document> &D) 181 : Node(NK_Null, D, StringRef(), StringRef()) {} 182 183 static inline bool classof(const Node *N) { 184 return N->getType() == NK_Null; 185 } 186 }; 187 188 /// @brief A scalar node is an opaque datum that can be presented as a 189 /// series of zero or more Unicode scalar values. 190 /// 191 /// Example: 192 /// Adena 193 class ScalarNode : public Node { 194 virtual void anchor(); 195 public: 196 ScalarNode(OwningPtr<Document> &D, StringRef Anchor, StringRef Tag, 197 StringRef Val) 198 : Node(NK_Scalar, D, Anchor, Tag), Value(Val) { 199 SMLoc Start = SMLoc::getFromPointer(Val.begin()); 200 SMLoc End = SMLoc::getFromPointer(Val.end()); 201 SourceRange = SMRange(Start, End); 202 } 203 204 // Return Value without any escaping or folding or other fun YAML stuff. This 205 // is the exact bytes that are contained in the file (after conversion to 206 // utf8). 207 StringRef getRawValue() const { return Value; } 208 209 /// @brief Gets the value of this node as a StringRef. 210 /// 211 /// @param Storage is used to store the content of the returned StringRef iff 212 /// it requires any modification from how it appeared in the source. 213 /// This happens with escaped characters and multi-line literals. 214 StringRef getValue(SmallVectorImpl<char> &Storage) const; 215 216 static inline bool classof(const Node *N) { 217 return N->getType() == NK_Scalar; 218 } 219 220 private: 221 StringRef Value; 222 223 StringRef unescapeDoubleQuoted( StringRef UnquotedValue 224 , StringRef::size_type Start 225 , SmallVectorImpl<char> &Storage) const; 226 }; 227 228 /// @brief A key and value pair. While not technically a Node under the YAML 229 /// representation graph, it is easier to treat them this way. 230 /// 231 /// TODO: Consider making this not a child of Node. 232 /// 233 /// Example: 234 /// Section: .text 235 class KeyValueNode : public Node { 236 virtual void anchor(); 237 public: 238 KeyValueNode(OwningPtr<Document> &D) 239 : Node(NK_KeyValue, D, StringRef(), StringRef()) 240 , Key(0) 241 , Value(0) 242 {} 243 244 /// @brief Parse and return the key. 245 /// 246 /// This may be called multiple times. 247 /// 248 /// @returns The key, or nullptr if failed() == true. 249 Node *getKey(); 250 251 /// @brief Parse and return the value. 252 /// 253 /// This may be called multiple times. 254 /// 255 /// @returns The value, or nullptr if failed() == true. 256 Node *getValue(); 257 258 virtual void skip() LLVM_OVERRIDE { 259 getKey()->skip(); 260 getValue()->skip(); 261 } 262 263 static inline bool classof(const Node *N) { 264 return N->getType() == NK_KeyValue; 265 } 266 267 private: 268 Node *Key; 269 Node *Value; 270 }; 271 272 /// @brief This is an iterator abstraction over YAML collections shared by both 273 /// sequences and maps. 274 /// 275 /// BaseT must have a ValueT* member named CurrentEntry and a member function 276 /// increment() which must set CurrentEntry to 0 to create an end iterator. 277 template <class BaseT, class ValueT> 278 class basic_collection_iterator 279 : public std::iterator<std::forward_iterator_tag, ValueT> { 280 public: 281 basic_collection_iterator() : Base(0) {} 282 basic_collection_iterator(BaseT *B) : Base(B) {} 283 284 ValueT *operator ->() const { 285 assert(Base && Base->CurrentEntry && "Attempted to access end iterator!"); 286 return Base->CurrentEntry; 287 } 288 289 ValueT &operator *() const { 290 assert(Base && Base->CurrentEntry && 291 "Attempted to dereference end iterator!"); 292 return *Base->CurrentEntry; 293 } 294 295 operator ValueT*() const { 296 assert(Base && Base->CurrentEntry && "Attempted to access end iterator!"); 297 return Base->CurrentEntry; 298 } 299 300 bool operator !=(const basic_collection_iterator &Other) const { 301 if(Base != Other.Base) 302 return true; 303 return (Base && Other.Base) && Base->CurrentEntry 304 != Other.Base->CurrentEntry; 305 } 306 307 basic_collection_iterator &operator++() { 308 assert(Base && "Attempted to advance iterator past end!"); 309 Base->increment(); 310 // Create an end iterator. 311 if (Base->CurrentEntry == 0) 312 Base = 0; 313 return *this; 314 } 315 316 private: 317 BaseT *Base; 318 }; 319 320 // The following two templates are used for both MappingNode and Sequence Node. 321 template <class CollectionType> 322 typename CollectionType::iterator begin(CollectionType &C) { 323 assert(C.IsAtBeginning && "You may only iterate over a collection once!"); 324 C.IsAtBeginning = false; 325 typename CollectionType::iterator ret(&C); 326 ++ret; 327 return ret; 328 } 329 330 template <class CollectionType> 331 void skip(CollectionType &C) { 332 // TODO: support skipping from the middle of a parsed collection ;/ 333 assert((C.IsAtBeginning || C.IsAtEnd) && "Cannot skip mid parse!"); 334 if (C.IsAtBeginning) 335 for (typename CollectionType::iterator i = begin(C), e = C.end(); 336 i != e; ++i) 337 i->skip(); 338 } 339 340 /// @brief Represents a YAML map created from either a block map for a flow map. 341 /// 342 /// This parses the YAML stream as increment() is called. 343 /// 344 /// Example: 345 /// Name: _main 346 /// Scope: Global 347 class MappingNode : public Node { 348 virtual void anchor(); 349 public: 350 enum MappingType { 351 MT_Block, 352 MT_Flow, 353 MT_Inline ///< An inline mapping node is used for "[key: value]". 354 }; 355 356 MappingNode(OwningPtr<Document> &D, StringRef Anchor, StringRef Tag, 357 MappingType MT) 358 : Node(NK_Mapping, D, Anchor, Tag), Type(MT), IsAtBeginning(true), 359 IsAtEnd(false), CurrentEntry(0) {} 360 361 friend class basic_collection_iterator<MappingNode, KeyValueNode>; 362 typedef basic_collection_iterator<MappingNode, KeyValueNode> iterator; 363 template <class T> friend typename T::iterator yaml::begin(T &); 364 template <class T> friend void yaml::skip(T &); 365 366 iterator begin() { 367 return yaml::begin(*this); 368 } 369 370 iterator end() { return iterator(); } 371 372 virtual void skip() LLVM_OVERRIDE { 373 yaml::skip(*this); 374 } 375 376 static inline bool classof(const Node *N) { 377 return N->getType() == NK_Mapping; 378 } 379 380 private: 381 MappingType Type; 382 bool IsAtBeginning; 383 bool IsAtEnd; 384 KeyValueNode *CurrentEntry; 385 386 void increment(); 387 }; 388 389 /// @brief Represents a YAML sequence created from either a block sequence for a 390 /// flow sequence. 391 /// 392 /// This parses the YAML stream as increment() is called. 393 /// 394 /// Example: 395 /// - Hello 396 /// - World 397 class SequenceNode : public Node { 398 virtual void anchor(); 399 public: 400 enum SequenceType { 401 ST_Block, 402 ST_Flow, 403 // Use for: 404 // 405 // key: 406 // - val1 407 // - val2 408 // 409 // As a BlockMappingEntry and BlockEnd are not created in this case. 410 ST_Indentless 411 }; 412 413 SequenceNode(OwningPtr<Document> &D, StringRef Anchor, StringRef Tag, 414 SequenceType ST) 415 : Node(NK_Sequence, D, Anchor, Tag), SeqType(ST), IsAtBeginning(true), 416 IsAtEnd(false), 417 WasPreviousTokenFlowEntry(true), // Start with an imaginary ','. 418 CurrentEntry(0) {} 419 420 friend class basic_collection_iterator<SequenceNode, Node>; 421 typedef basic_collection_iterator<SequenceNode, Node> iterator; 422 template <class T> friend typename T::iterator yaml::begin(T &); 423 template <class T> friend void yaml::skip(T &); 424 425 void increment(); 426 427 iterator begin() { 428 return yaml::begin(*this); 429 } 430 431 iterator end() { return iterator(); } 432 433 virtual void skip() LLVM_OVERRIDE { 434 yaml::skip(*this); 435 } 436 437 static inline bool classof(const Node *N) { 438 return N->getType() == NK_Sequence; 439 } 440 441 private: 442 SequenceType SeqType; 443 bool IsAtBeginning; 444 bool IsAtEnd; 445 bool WasPreviousTokenFlowEntry; 446 Node *CurrentEntry; 447 }; 448 449 /// @brief Represents an alias to a Node with an anchor. 450 /// 451 /// Example: 452 /// *AnchorName 453 class AliasNode : public Node { 454 virtual void anchor(); 455 public: 456 AliasNode(OwningPtr<Document> &D, StringRef Val) 457 : Node(NK_Alias, D, StringRef(), StringRef()), Name(Val) {} 458 459 StringRef getName() const { return Name; } 460 Node *getTarget(); 461 462 static inline bool classof(const Node *N) { 463 return N->getType() == NK_Alias; 464 } 465 466 private: 467 StringRef Name; 468 }; 469 470 /// @brief A YAML Stream is a sequence of Documents. A document contains a root 471 /// node. 472 class Document { 473 public: 474 /// @brief Root for parsing a node. Returns a single node. 475 Node *parseBlockNode(); 476 477 Document(Stream &ParentStream); 478 479 /// @brief Finish parsing the current document and return true if there are 480 /// more. Return false otherwise. 481 bool skip(); 482 483 /// @brief Parse and return the root level node. 484 Node *getRoot() { 485 if (Root) 486 return Root; 487 return Root = parseBlockNode(); 488 } 489 490 const std::map<StringRef, StringRef> &getTagMap() const { 491 return TagMap; 492 } 493 494 private: 495 friend class Node; 496 friend class document_iterator; 497 498 /// @brief Stream to read tokens from. 499 Stream &stream; 500 501 /// @brief Used to allocate nodes to. All are destroyed without calling their 502 /// destructor when the document is destroyed. 503 BumpPtrAllocator NodeAllocator; 504 505 /// @brief The root node. Used to support skipping a partially parsed 506 /// document. 507 Node *Root; 508 509 /// \brief Maps tag prefixes to their expansion. 510 std::map<StringRef, StringRef> TagMap; 511 512 Token &peekNext(); 513 Token getNext(); 514 void setError(const Twine &Message, Token &Location) const; 515 bool failed() const; 516 517 /// @brief Parse %BLAH directives and return true if any were encountered. 518 bool parseDirectives(); 519 520 /// \brief Parse %YAML 521 void parseYAMLDirective(); 522 523 /// \brief Parse %TAG 524 void parseTAGDirective(); 525 526 /// @brief Consume the next token and error if it is not \a TK. 527 bool expectToken(int TK); 528 }; 529 530 /// @brief Iterator abstraction for Documents over a Stream. 531 class document_iterator { 532 public: 533 document_iterator() : Doc(0) {} 534 document_iterator(OwningPtr<Document> &D) : Doc(&D) {} 535 536 bool operator ==(const document_iterator &Other) { 537 if (isAtEnd() || Other.isAtEnd()) 538 return isAtEnd() && Other.isAtEnd(); 539 540 return Doc == Other.Doc; 541 } 542 bool operator !=(const document_iterator &Other) { 543 return !(*this == Other); 544 } 545 546 document_iterator operator ++() { 547 assert(Doc != 0 && "incrementing iterator past the end."); 548 if (!(*Doc)->skip()) { 549 Doc->reset(0); 550 } else { 551 Stream &S = (*Doc)->stream; 552 Doc->reset(new Document(S)); 553 } 554 return *this; 555 } 556 557 Document &operator *() { 558 return *Doc->get(); 559 } 560 561 OwningPtr<Document> &operator ->() { 562 return *Doc; 563 } 564 565 private: 566 bool isAtEnd() const { 567 return !Doc || !*Doc; 568 } 569 570 OwningPtr<Document> *Doc; 571 }; 572 573 } 574 } 575 576 #endif 577