X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FSupport%2FYAMLParser.h;h=0fbb7d2e6c7e3fc3afe452333f35f1e3188ca8b4;hb=00552e3875ee5f382db6c98286a241a7d0efe1b8;hp=b24cacd3c3282c2089f86b037c5659c89257acff;hpb=42730cec0b6b19986bf83db2490f70de8c8139fa;p=oota-llvm.git diff --git a/include/llvm/Support/YAMLParser.h b/include/llvm/Support/YAMLParser.h index b24cacd3c32..0fbb7d2e6c7 100644 --- a/include/llvm/Support/YAMLParser.h +++ b/include/llvm/Support/YAMLParser.h @@ -35,23 +35,21 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_YAML_PARSER_H -#define LLVM_SUPPORT_YAML_PARSER_H +#ifndef LLVM_SUPPORT_YAMLPARSER_H +#define LLVM_SUPPORT_YAMLPARSER_H -#include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/SMLoc.h" - #include +#include #include namespace llvm { -class MemoryBuffer; +class MemoryBufferRef; class SourceMgr; -class raw_ostream; class Twine; +class raw_ostream; namespace yaml { @@ -61,23 +59,26 @@ class Node; class Scanner; struct Token; -/// @brief Dump all the tokens in this stream to OS. -/// @returns true if there was an error, false otherwise. +/// \brief Dump all the tokens in this stream to OS. +/// \returns true if there was an error, false otherwise. bool dumpTokens(StringRef Input, raw_ostream &); -/// @brief Scans all tokens in input without outputting anything. This is used +/// \brief Scans all tokens in input without outputting anything. This is used /// for benchmarking the tokenizer. -/// @returns true if there was an error, false otherwise. +/// \returns true if there was an error, false otherwise. bool scanTokens(StringRef Input); -/// @brief Escape \a Input for a double quoted scalar. +/// \brief Escape \a Input for a double quoted scalar. std::string escape(StringRef Input); -/// @brief This class represents a YAML stream potentially containing multiple +/// \brief This class represents a YAML stream potentially containing multiple /// documents. class Stream { public: - Stream(StringRef Input, SourceMgr &); + /// \brief This keeps a reference to the string referenced by \p Input. + Stream(StringRef Input, SourceMgr &, bool ShowColors = true); + + Stream(MemoryBufferRef InputBuffer, SourceMgr &, bool ShowColors = true); ~Stream(); document_iterator begin(); @@ -92,33 +93,42 @@ public: void printError(Node *N, const Twine &Msg); private: - OwningPtr scanner; - OwningPtr CurrentDoc; + std::unique_ptr scanner; + std::unique_ptr CurrentDoc; friend class Document; - - /// @brief Validate a %YAML x.x directive. - void handleYAMLDirective(const Token &); }; -/// @brief Abstract base class for all Nodes. +/// \brief Abstract base class for all Nodes. class Node { + virtual void anchor(); + public: enum NodeKind { NK_Null, NK_Scalar, + NK_BlockScalar, NK_KeyValue, NK_Mapping, NK_Sequence, NK_Alias }; - Node(unsigned int Type, OwningPtr&, StringRef Anchor); + Node(unsigned int Type, std::unique_ptr &, StringRef Anchor, + StringRef Tag); - /// @brief Get the value of the anchor attached to this node. If it does not + /// \brief Get the value of the anchor attached to this node. If it does not /// have one, getAnchor().size() will be 0. StringRef getAnchor() const { return Anchor; } + /// \brief Get the tag as it was written in the document. This does not + /// perform tag resolution. + StringRef getRawTag() const { return Tag; } + + /// \brief Get the verbatium tag for a given Node. This performs tag resoluton + /// and substitution. + std::string getVerbatimTag() const; + SMRange getSourceRange() const { return SourceRange; } void setSourceRange(SMRange SR) { SourceRange = SR; } @@ -130,60 +140,62 @@ public: void setError(const Twine &Message, Token &Location) const; bool failed() const; - virtual void skip() {}; + virtual void skip() {} unsigned int getType() const { return TypeID; } - static inline bool classof(const Node *) { return true; } - void *operator new ( size_t Size - , BumpPtrAllocator &Alloc - , size_t Alignment = 16) throw() { + void *operator new(size_t Size, BumpPtrAllocator &Alloc, + size_t Alignment = 16) throw() { return Alloc.Allocate(Size, Alignment); } - void operator delete(void *Ptr, BumpPtrAllocator &Alloc, size_t) throw() { - Alloc.Deallocate(Ptr); + void operator delete(void *Ptr, BumpPtrAllocator &Alloc, size_t Size) throw() { + Alloc.Deallocate(Ptr, Size); } protected: - OwningPtr &Doc; + std::unique_ptr &Doc; SMRange SourceRange; void operator delete(void *) throw() {} - virtual ~Node() {} + ~Node() = default; private: unsigned int TypeID; StringRef Anchor; + /// \brief The tag as typed in the document. + StringRef Tag; }; -/// @brief A null value. +/// \brief A null value. /// /// Example: /// !!null null -class NullNode : public Node { +class NullNode final : public Node { + void anchor() override; + public: - NullNode(OwningPtr &D) : Node(NK_Null, D, StringRef()) {} + NullNode(std::unique_ptr &D) + : Node(NK_Null, D, StringRef(), StringRef()) {} - static inline bool classof(const NullNode *) { return true; } - static inline bool classof(const Node *N) { - return N->getType() == NK_Null; - } + static inline bool classof(const Node *N) { return N->getType() == NK_Null; } }; -/// @brief A scalar node is an opaque datum that can be presented as a +/// \brief A scalar node is an opaque datum that can be presented as a /// series of zero or more Unicode scalar values. /// /// Example: /// Adena -class ScalarNode : public Node { +class ScalarNode final : public Node { + void anchor() override; + public: - ScalarNode(OwningPtr &D, StringRef Anchor, StringRef Val) - : Node(NK_Scalar, D, Anchor) - , Value(Val) { + ScalarNode(std::unique_ptr &D, StringRef Anchor, StringRef Tag, + StringRef Val) + : Node(NK_Scalar, D, Anchor, Tag), Value(Val) { SMLoc Start = SMLoc::getFromPointer(Val.begin()); - SMLoc End = SMLoc::getFromPointer(Val.end() - 1); + SMLoc End = SMLoc::getFromPointer(Val.end()); SourceRange = SMRange(Start, End); } @@ -192,14 +204,13 @@ public: // utf8). StringRef getRawValue() const { return Value; } - /// @brief Gets the value of this node as a StringRef. + /// \brief Gets the value of this node as a StringRef. /// - /// @param Storage is used to store the content of the returned StringRef iff + /// \param Storage is used to store the content of the returned StringRef iff /// it requires any modification from how it appeared in the source. /// This happens with escaped characters and multi-line literals. StringRef getValue(SmallVectorImpl &Storage) const; - static inline bool classof(const ScalarNode *) { return true; } static inline bool classof(const Node *N) { return N->getType() == NK_Scalar; } @@ -207,46 +218,76 @@ public: private: StringRef Value; - StringRef unescapeDoubleQuoted( StringRef UnquotedValue - , StringRef::size_type Start - , SmallVectorImpl &Storage) const; + StringRef unescapeDoubleQuoted(StringRef UnquotedValue, + StringRef::size_type Start, + SmallVectorImpl &Storage) const; +}; + +/// \brief A block scalar node is an opaque datum that can be presented as a +/// series of zero or more Unicode scalar values. +/// +/// Example: +/// | +/// Hello +/// World +class BlockScalarNode final : public Node { + void anchor() override; + +public: + BlockScalarNode(std::unique_ptr &D, StringRef Anchor, StringRef Tag, + StringRef Value, StringRef RawVal) + : Node(NK_BlockScalar, D, Anchor, Tag), Value(Value) { + SMLoc Start = SMLoc::getFromPointer(RawVal.begin()); + SMLoc End = SMLoc::getFromPointer(RawVal.end()); + SourceRange = SMRange(Start, End); + } + + /// \brief Gets the value of this node as a StringRef. + StringRef getValue() const { return Value; } + + static inline bool classof(const Node *N) { + return N->getType() == NK_BlockScalar; + } + +private: + StringRef Value; }; -/// @brief A key and value pair. While not technically a Node under the YAML +/// \brief A key and value pair. While not technically a Node under the YAML /// representation graph, it is easier to treat them this way. /// /// TODO: Consider making this not a child of Node. /// /// Example: /// Section: .text -class KeyValueNode : public Node { +class KeyValueNode final : public Node { + void anchor() override; + public: - KeyValueNode(OwningPtr &D) - : Node(NK_KeyValue, D, StringRef()) - , Key(0) - , Value(0) - {} + KeyValueNode(std::unique_ptr &D) + : Node(NK_KeyValue, D, StringRef(), StringRef()), Key(nullptr), + Value(nullptr) {} - /// @brief Parse and return the key. + /// \brief Parse and return the key. /// /// This may be called multiple times. /// - /// @returns The key, or nullptr if failed() == true. + /// \returns The key, or nullptr if failed() == true. Node *getKey(); - /// @brief Parse and return the value. + /// \brief Parse and return the value. /// /// This may be called multiple times. /// - /// @returns The value, or nullptr if failed() == true. + /// \returns The value, or nullptr if failed() == true. Node *getValue(); - virtual void skip() { + void skip() override { getKey()->skip(); - getValue()->skip(); + if (Node *Val = getValue()) + Val->skip(); } - static inline bool classof(const KeyValueNode *) { return true; } static inline bool classof(const Node *N) { return N->getType() == NK_KeyValue; } @@ -256,47 +297,47 @@ private: Node *Value; }; -/// @brief This is an iterator abstraction over YAML collections shared by both +/// \brief This is an iterator abstraction over YAML collections shared by both /// sequences and maps. /// /// BaseT must have a ValueT* member named CurrentEntry and a member function /// increment() which must set CurrentEntry to 0 to create an end iterator. template class basic_collection_iterator - : public std::iterator { + : public std::iterator { public: - basic_collection_iterator() : Base(0) {} + basic_collection_iterator() : Base(nullptr) {} basic_collection_iterator(BaseT *B) : Base(B) {} - ValueT *operator ->() const { + ValueT *operator->() const { assert(Base && Base->CurrentEntry && "Attempted to access end iterator!"); return Base->CurrentEntry; } - ValueT &operator *() const { + ValueT &operator*() const { assert(Base && Base->CurrentEntry && "Attempted to dereference end iterator!"); return *Base->CurrentEntry; } - operator ValueT*() const { + operator ValueT *() const { assert(Base && Base->CurrentEntry && "Attempted to access end iterator!"); return Base->CurrentEntry; } - bool operator !=(const basic_collection_iterator &Other) const { - if(Base != Other.Base) + bool operator!=(const basic_collection_iterator &Other) const { + if (Base != Other.Base) return true; - return (Base && Other.Base) && Base->CurrentEntry - != Other.Base->CurrentEntry; + return (Base && Other.Base) && + Base->CurrentEntry != Other.Base->CurrentEntry; } basic_collection_iterator &operator++() { assert(Base && "Attempted to advance iterator past end!"); Base->increment(); // Create an end iterator. - if (Base->CurrentEntry == 0) - Base = 0; + if (!Base->CurrentEntry) + Base = nullptr; return *this; } @@ -314,55 +355,48 @@ typename CollectionType::iterator begin(CollectionType &C) { return ret; } -template -void skip(CollectionType &C) { +template void skip(CollectionType &C) { // TODO: support skipping from the middle of a parsed collection ;/ assert((C.IsAtBeginning || C.IsAtEnd) && "Cannot skip mid parse!"); if (C.IsAtBeginning) - for (typename CollectionType::iterator i = begin(C), e = C.end(); - i != e; ++i) + for (typename CollectionType::iterator i = begin(C), e = C.end(); i != e; + ++i) i->skip(); } -/// @brief Represents a YAML map created from either a block map for a flow map. +/// \brief Represents a YAML map created from either a block map for a flow map. /// /// This parses the YAML stream as increment() is called. /// /// Example: /// Name: _main /// Scope: Global -class MappingNode : public Node { +class MappingNode final : public Node { + void anchor() override; + public: enum MappingType { MT_Block, MT_Flow, - MT_Inline //< An inline mapping node is used for "[key: value]". + MT_Inline ///< An inline mapping node is used for "[key: value]". }; - MappingNode(OwningPtr &D, StringRef Anchor, MappingType MT) - : Node(NK_Mapping, D, Anchor) - , Type(MT) - , IsAtBeginning(true) - , IsAtEnd(false) - , CurrentEntry(0) - {} + MappingNode(std::unique_ptr &D, StringRef Anchor, StringRef Tag, + MappingType MT) + : Node(NK_Mapping, D, Anchor, Tag), Type(MT), IsAtBeginning(true), + IsAtEnd(false), CurrentEntry(nullptr) {} friend class basic_collection_iterator; typedef basic_collection_iterator iterator; template friend typename T::iterator yaml::begin(T &); template friend void yaml::skip(T &); - iterator begin() { - return yaml::begin(*this); - } + iterator begin() { return yaml::begin(*this); } iterator end() { return iterator(); } - virtual void skip() { - yaml::skip(*this); - } + void skip() override { yaml::skip(*this); } - static inline bool classof(const MappingNode *) { return true; } static inline bool classof(const Node *N) { return N->getType() == NK_Mapping; } @@ -376,7 +410,7 @@ private: void increment(); }; -/// @brief Represents a YAML sequence created from either a block sequence for a +/// \brief Represents a YAML sequence created from either a block sequence for a /// flow sequence. /// /// This parses the YAML stream as increment() is called. @@ -384,7 +418,9 @@ private: /// Example: /// - Hello /// - World -class SequenceNode : public Node { +class SequenceNode final : public Node { + void anchor() override; + public: enum SequenceType { ST_Block, @@ -399,14 +435,12 @@ public: ST_Indentless }; - SequenceNode(OwningPtr &D, StringRef Anchor, SequenceType ST) - : Node(NK_Sequence, D, Anchor) - , SeqType(ST) - , IsAtBeginning(true) - , IsAtEnd(false) - , WasPreviousTokenFlowEntry(true) // Start with an imaginary ','. - , CurrentEntry(0) - {} + SequenceNode(std::unique_ptr &D, StringRef Anchor, StringRef Tag, + SequenceType ST) + : Node(NK_Sequence, D, Anchor, Tag), SeqType(ST), IsAtBeginning(true), + IsAtEnd(false), + WasPreviousTokenFlowEntry(true), // Start with an imaginary ','. + CurrentEntry(nullptr) {} friend class basic_collection_iterator; typedef basic_collection_iterator iterator; @@ -415,17 +449,12 @@ public: void increment(); - iterator begin() { - return yaml::begin(*this); - } + iterator begin() { return yaml::begin(*this); } iterator end() { return iterator(); } - virtual void skip() { - yaml::skip(*this); - } + void skip() override { yaml::skip(*this); } - static inline bool classof(const SequenceNode *) { return true; } static inline bool classof(const Node *N) { return N->getType() == NK_Sequence; } @@ -438,112 +467,121 @@ private: Node *CurrentEntry; }; -/// @brief Represents an alias to a Node with an anchor. +/// \brief Represents an alias to a Node with an anchor. /// /// Example: /// *AnchorName -class AliasNode : public Node { +class AliasNode final : public Node { + void anchor() override; + public: - AliasNode(OwningPtr &D, StringRef Val) - : Node(NK_Alias, D, StringRef()), Name(Val) {} + AliasNode(std::unique_ptr &D, StringRef Val) + : Node(NK_Alias, D, StringRef(), StringRef()), Name(Val) {} StringRef getName() const { return Name; } Node *getTarget(); - static inline bool classof(const ScalarNode *) { return true; } - static inline bool classof(const Node *N) { - return N->getType() == NK_Alias; - } + static inline bool classof(const Node *N) { return N->getType() == NK_Alias; } private: StringRef Name; }; -/// @brief A YAML Stream is a sequence of Documents. A document contains a root +/// \brief A YAML Stream is a sequence of Documents. A document contains a root /// node. class Document { public: - /// @brief Root for parsing a node. Returns a single node. + /// \brief Root for parsing a node. Returns a single node. Node *parseBlockNode(); Document(Stream &ParentStream); - /// @brief Finish parsing the current document and return true if there are + /// \brief Finish parsing the current document and return true if there are /// more. Return false otherwise. bool skip(); - /// @brief Parse and return the root level node. + /// \brief Parse and return the root level node. Node *getRoot() { if (Root) return Root; return Root = parseBlockNode(); } + const std::map &getTagMap() const { return TagMap; } + private: friend class Node; friend class document_iterator; - /// @brief Stream to read tokens from. + /// \brief Stream to read tokens from. Stream &stream; - /// @brief Used to allocate nodes to. All are destroyed without calling their + /// \brief Used to allocate nodes to. All are destroyed without calling their /// destructor when the document is destroyed. BumpPtrAllocator NodeAllocator; - /// @brief The root node. Used to support skipping a partially parsed + /// \brief The root node. Used to support skipping a partially parsed /// document. Node *Root; + /// \brief Maps tag prefixes to their expansion. + std::map TagMap; + Token &peekNext(); Token getNext(); void setError(const Twine &Message, Token &Location) const; bool failed() const; - void handleTagDirective(const Token &Tag) { - // TODO: Track tags. - } - - /// @brief Parse %BLAH directives and return true if any were encountered. + /// \brief Parse %BLAH directives and return true if any were encountered. bool parseDirectives(); - /// @brief Consume the next token and error if it is not \a TK. + /// \brief Parse %YAML + void parseYAMLDirective(); + + /// \brief Parse %TAG + void parseTAGDirective(); + + /// \brief Consume the next token and error if it is not \a TK. bool expectToken(int TK); }; -/// @brief Iterator abstraction for Documents over a Stream. +/// \brief Iterator abstraction for Documents over a Stream. class document_iterator { public: - document_iterator() : Doc(NullDoc) {} - document_iterator(OwningPtr &D) : Doc(D) {} + document_iterator() : Doc(nullptr) {} + document_iterator(std::unique_ptr &D) : Doc(&D) {} + + bool operator==(const document_iterator &Other) { + if (isAtEnd() || Other.isAtEnd()) + return isAtEnd() && Other.isAtEnd(); - bool operator !=(const document_iterator &Other) { - return Doc != Other.Doc; + return Doc == Other.Doc; } + bool operator!=(const document_iterator &Other) { return !(*this == Other); } - document_iterator operator ++() { - if (!Doc->skip()) { - Doc.reset(0); + document_iterator operator++() { + assert(Doc && "incrementing iterator past the end."); + if (!(*Doc)->skip()) { + Doc->reset(nullptr); } else { - Stream &S = Doc->stream; - Doc.reset(new Document(S)); + Stream &S = (*Doc)->stream; + Doc->reset(new Document(S)); } return *this; } - Document &operator *() { - return *Doc; - } + Document &operator*() { return *Doc->get(); } - OwningPtr &operator ->() { - return Doc; - } + std::unique_ptr &operator->() { return *Doc; } private: - static OwningPtr NullDoc; - OwningPtr &Doc; + bool isAtEnd() const { return !Doc || !*Doc; } + + std::unique_ptr *Doc; }; -} -} +} // End namespace yaml. + +} // End namespace llvm. #endif