[llvm] r193004 - [Support][YAML] Add support for accessing tags and tag handle substitution.
Lang Hames
lhames at gmail.com
Fri Oct 18 15:55:12 PDT 2013
Hi Michael,
This has some std::move calls in it. Does they need to be conditionalized
on LLVM_HAS_RVALUE_REFERENCES? Currently this doesn't compile on C++03.
- Lang.
On Fri, Oct 18, 2013 at 3:38 PM, Michael J. Spencer
<bigcheesegs at gmail.com>wrote:
> Author: mspencer
> Date: Fri Oct 18 17:38:04 2013
> New Revision: 193004
>
> URL: http://llvm.org/viewvc/llvm-project?rev=193004&view=rev
> Log:
> [Support][YAML] Add support for accessing tags and tag handle substitution.
>
> Modified:
> llvm/trunk/include/llvm/Support/YAMLParser.h
> llvm/trunk/lib/Support/YAMLParser.cpp
> llvm/trunk/test/YAMLParser/spec-02-24.data
> llvm/trunk/test/YAMLParser/spec-07-04.data
> llvm/trunk/test/YAMLParser/yaml.data
> llvm/trunk/utils/yaml-bench/YAMLBench.cpp
>
> Modified: llvm/trunk/include/llvm/Support/YAMLParser.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/YAMLParser.h?rev=193004&r1=193003&r2=193004&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/Support/YAMLParser.h (original)
> +++ llvm/trunk/include/llvm/Support/YAMLParser.h Fri Oct 18 17:38:04 2013
> @@ -43,6 +43,8 @@
> #include "llvm/ADT/StringRef.h"
> #include "llvm/Support/Allocator.h"
> #include "llvm/Support/SMLoc.h"
> +
> +#include <map>
> #include <limits>
> #include <utility>
>
> @@ -99,9 +101,6 @@ private:
> OwningPtr<Document> CurrentDoc;
>
> friend class Document;
> -
> - /// @brief Validate a %YAML x.x directive.
> - void handleYAMLDirective(const Token &);
> };
>
> /// @brief Abstract base class for all Nodes.
> @@ -116,12 +115,21 @@ public:
> NK_Alias
> };
>
> - Node(unsigned int Type, OwningPtr<Document>&, StringRef Anchor);
> + Node(unsigned int Type, OwningPtr<Document> &, StringRef Anchor,
> + StringRef Tag);
>
> /// @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; }
>
> @@ -158,6 +166,8 @@ protected:
> private:
> unsigned int TypeID;
> StringRef Anchor;
> + /// \brief The tag as typed in the document.
> + StringRef Tag;
> };
>
> /// @brief A null value.
> @@ -166,7 +176,8 @@ private:
> /// !!null null
> class NullNode : public Node {
> public:
> - NullNode(OwningPtr<Document> &D) : Node(NK_Null, D, StringRef()) {}
> + NullNode(OwningPtr<Document> &D)
> + : Node(NK_Null, D, StringRef(), StringRef()) {}
>
> static inline bool classof(const Node *N) {
> return N->getType() == NK_Null;
> @@ -180,9 +191,9 @@ public:
> /// Adena
> class ScalarNode : public Node {
> public:
> - ScalarNode(OwningPtr<Document> &D, StringRef Anchor, StringRef Val)
> - : Node(NK_Scalar, D, Anchor)
> - , Value(Val) {
> + ScalarNode(OwningPtr<Document> &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());
> SourceRange = SMRange(Start, End);
> @@ -222,7 +233,7 @@ private:
> class KeyValueNode : public Node {
> public:
> KeyValueNode(OwningPtr<Document> &D)
> - : Node(NK_KeyValue, D, StringRef())
> + : Node(NK_KeyValue, D, StringRef(), StringRef())
> , Key(0)
> , Value(0)
> {}
> @@ -338,13 +349,10 @@ public:
> MT_Inline ///< An inline mapping node is used for "[key: value]".
> };
>
> - MappingNode(OwningPtr<Document> &D, StringRef Anchor, MappingType MT)
> - : Node(NK_Mapping, D, Anchor)
> - , Type(MT)
> - , IsAtBeginning(true)
> - , IsAtEnd(false)
> - , CurrentEntry(0)
> - {}
> + MappingNode(OwningPtr<Document> &D, StringRef Anchor, StringRef Tag,
> + MappingType MT)
> + : Node(NK_Mapping, D, Anchor, Tag), Type(MT), IsAtBeginning(true),
> + IsAtEnd(false), CurrentEntry(0) {}
>
> friend class basic_collection_iterator<MappingNode, KeyValueNode>;
> typedef basic_collection_iterator<MappingNode, KeyValueNode> iterator;
> @@ -397,14 +405,12 @@ public:
> ST_Indentless
> };
>
> - SequenceNode(OwningPtr<Document> &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(OwningPtr<Document> &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(0) {}
>
> friend class basic_collection_iterator<SequenceNode, Node>;
> typedef basic_collection_iterator<SequenceNode, Node> iterator;
> @@ -442,7 +448,7 @@ private:
> class AliasNode : public Node {
> public:
> AliasNode(OwningPtr<Document> &D, StringRef Val)
> - : Node(NK_Alias, D, StringRef()), Name(Val) {}
> + : Node(NK_Alias, D, StringRef(), StringRef()), Name(Val) {}
>
> StringRef getName() const { return Name; }
> Node *getTarget();
> @@ -475,6 +481,10 @@ public:
> return Root = parseBlockNode();
> }
>
> + const std::map<StringRef, StringRef> &getTagMap() const {
> + return TagMap;
> + }
> +
> private:
> friend class Node;
> friend class document_iterator;
> @@ -490,18 +500,23 @@ private:
> /// document.
> Node *Root;
>
> + /// \brief Maps tag prefixes to their expansion.
> + std::map<StringRef, StringRef> 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.
> bool parseDirectives();
>
> + /// \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);
> };
>
> Modified: llvm/trunk/lib/Support/YAMLParser.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/YAMLParser.cpp?rev=193004&r1=193003&r2=193004&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Support/YAMLParser.cpp (original)
> +++ llvm/trunk/lib/Support/YAMLParser.cpp Fri Oct 18 17:38:04 2013
> @@ -1070,14 +1070,22 @@ bool Scanner::scanDirective() {
> Current = skip_while(&Scanner::skip_ns_char, Current);
> StringRef Name(NameStart, Current - NameStart);
> Current = skip_while(&Scanner::skip_s_white, Current);
> -
> +
> + Token T;
> if (Name == "YAML") {
> Current = skip_while(&Scanner::skip_ns_char, Current);
> - Token T;
> T.Kind = Token::TK_VersionDirective;
> T.Range = StringRef(Start, Current - Start);
> TokenQueue.push_back(T);
> return true;
> + } else if(Name == "TAG") {
> + Current = skip_while(&Scanner::skip_ns_char, Current);
> + Current = skip_while(&Scanner::skip_s_white, Current);
> + Current = skip_while(&Scanner::skip_ns_char, Current);
> + T.Kind = Token::TK_TagDirective;
> + T.Range = StringRef(Start, Current - Start);
> + TokenQueue.push_back(T);
> + return true;
> }
> return false;
> }
> @@ -1564,10 +1572,6 @@ void Stream::printError(Node *N, const T
> , Ranges);
> }
>
> -void Stream::handleYAMLDirective(const Token &t) {
> - // TODO: Ensure version is 1.x.
> -}
> -
> document_iterator Stream::begin() {
> if (CurrentDoc)
> report_fatal_error("Can only iterate over the stream once");
> @@ -1588,14 +1592,59 @@ void Stream::skip() {
> i->skip();
> }
>
> -Node::Node(unsigned int Type, OwningPtr<Document> &D, StringRef A)
> +Node::Node(unsigned int Type, OwningPtr<Document> &D, StringRef A,
> StringRef T)
> : Doc(D)
> , TypeID(Type)
> - , Anchor(A) {
> + , Anchor(A)
> + , Tag(T) {
> SMLoc Start = SMLoc::getFromPointer(peekNext().Range.begin());
> SourceRange = SMRange(Start, Start);
> }
>
> +std::string Node::getVerbatimTag() const {
> + StringRef Raw = getRawTag();
> + if (!Raw.empty() && Raw != "!") {
> + std::string Ret;
> + if (Raw.find_last_of('!') == 0) {
> + Ret = Doc->getTagMap().find("!")->second;
> + Ret += Raw.substr(1);
> + return std::move(Ret);
> + } else if (Raw.startswith("!!")) {
> + Ret = Doc->getTagMap().find("!!")->second;
> + Ret += Raw.substr(2);
> + return std::move(Ret);
> + } else {
> + StringRef TagHandle = Raw.substr(0, Raw.find_last_of('!') + 1);
> + std::map<StringRef, StringRef>::const_iterator It =
> + Doc->getTagMap().find(TagHandle);
> + if (It != Doc->getTagMap().end())
> + Ret = It->second;
> + else {
> + Token T;
> + T.Kind = Token::TK_Tag;
> + T.Range = TagHandle;
> + setError(Twine("Unknown tag handle ") + TagHandle, T);
> + }
> + Ret += Raw.substr(Raw.find_last_of('!') + 1);
> + return std::move(Ret);
> + }
> + }
> +
> + switch (getType()) {
> + case NK_Null:
> + return "tag:yaml.org,2002:null";
> + case NK_Scalar:
> + // TODO: Tag resolution.
> + return "tag:yaml.org,2002:str";
> + case NK_Mapping:
> + return "tag:yaml.org,2002:map";
> + case NK_Sequence:
> + return "tag:yaml.org,2002:seq";
> + }
> +
> + return "";
> +}
> +
> Token &Node::peekNext() {
> return Doc->peekNext();
> }
> @@ -1999,6 +2048,10 @@ void SequenceNode::increment() {
> }
>
> Document::Document(Stream &S) : stream(S), Root(0) {
> + // Tag maps starts with two default mappings.
> + TagMap["!"] = "!";
> + TagMap["!!"] = "tag:yaml.org,2002:";
> +
> if (parseDirectives())
> expectToken(Token::TK_DocumentStart);
> Token &T = peekNext();
> @@ -2042,6 +2095,7 @@ Node *Document::parseBlockNode() {
> Token T = peekNext();
> // Handle properties.
> Token AnchorInfo;
> + Token TagInfo;
> parse_property:
> switch (T.Kind) {
> case Token::TK_Alias:
> @@ -2056,7 +2110,11 @@ parse_property:
> T = peekNext();
> goto parse_property;
> case Token::TK_Tag:
> - getNext(); // Skip TK_Tag.
> + if (TagInfo.Kind == Token::TK_Tag) {
> + setError("Already encountered a tag for this node!", T);
> + return 0;
> + }
> + TagInfo = getNext(); // Consume TK_Tag.
> T = peekNext();
> goto parse_property;
> default:
> @@ -2070,42 +2128,49 @@ parse_property:
> // Don't eat the TK_BlockEntry, SequenceNode needs it.
> return new (NodeAllocator) SequenceNode( stream.CurrentDoc
> , AnchorInfo.Range.substr(1)
> + , TagInfo.Range
> , SequenceNode::ST_Indentless);
> case Token::TK_BlockSequenceStart:
> getNext();
> return new (NodeAllocator)
> SequenceNode( stream.CurrentDoc
> , AnchorInfo.Range.substr(1)
> + , TagInfo.Range
> , SequenceNode::ST_Block);
> case Token::TK_BlockMappingStart:
> getNext();
> return new (NodeAllocator)
> MappingNode( stream.CurrentDoc
> , AnchorInfo.Range.substr(1)
> + , TagInfo.Range
> , MappingNode::MT_Block);
> case Token::TK_FlowSequenceStart:
> getNext();
> return new (NodeAllocator)
> SequenceNode( stream.CurrentDoc
> , AnchorInfo.Range.substr(1)
> + , TagInfo.Range
> , SequenceNode::ST_Flow);
> case Token::TK_FlowMappingStart:
> getNext();
> return new (NodeAllocator)
> MappingNode( stream.CurrentDoc
> , AnchorInfo.Range.substr(1)
> + , TagInfo.Range
> , MappingNode::MT_Flow);
> case Token::TK_Scalar:
> getNext();
> return new (NodeAllocator)
> ScalarNode( stream.CurrentDoc
> , AnchorInfo.Range.substr(1)
> + , TagInfo.Range
> , T.Range);
> case Token::TK_Key:
> // Don't eat the TK_Key, KeyValueNode expects it.
> return new (NodeAllocator)
> MappingNode( stream.CurrentDoc
> , AnchorInfo.Range.substr(1)
> + , TagInfo.Range
> , MappingNode::MT_Inline);
> case Token::TK_DocumentStart:
> case Token::TK_DocumentEnd:
> @@ -2126,10 +2191,10 @@ bool Document::parseDirectives() {
> while (true) {
> Token T = peekNext();
> if (T.Kind == Token::TK_TagDirective) {
> - handleTagDirective(getNext());
> + parseTAGDirective();
> isDirective = true;
> } else if (T.Kind == Token::TK_VersionDirective) {
> - stream.handleYAMLDirective(getNext());
> + parseYAMLDirective();
> isDirective = true;
> } else
> break;
> @@ -2137,6 +2202,21 @@ bool Document::parseDirectives() {
> return isDirective;
> }
>
> +void Document::parseYAMLDirective() {
> + getNext(); // Eat %YAML <version>
> +}
> +
> +void Document::parseTAGDirective() {
> + Token Tag = getNext(); // %TAG <handle> <prefix>
> + StringRef T = Tag.Range;
> + // Strip %TAG
> + T = T.substr(T.find_first_of(" \t")).ltrim(" \t");
> + std::size_t HandleEnd = T.find_first_of(" \t");
> + StringRef TagHandle = T.substr(0, HandleEnd);
> + StringRef TagPrefix = T.substr(HandleEnd).ltrim(" \t");
> + TagMap[TagHandle] = TagPrefix;
> +}
> +
> bool Document::expectToken(int TK) {
> Token T = getNext();
> if (T.Kind != TK) {
>
> Modified: llvm/trunk/test/YAMLParser/spec-02-24.data
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/YAMLParser/spec-02-24.data?rev=193004&r1=193003&r2=193004&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/YAMLParser/spec-02-24.data (original)
> +++ llvm/trunk/test/YAMLParser/spec-02-24.data Fri Oct 18 17:38:04 2013
> @@ -1,4 +1,4 @@
> -# RUN: yaml-bench -canonical %s
> +# RUN: yaml-bench -canonical %s | FileCheck %s
>
> %TAG ! tag:clarkevans.com,2002:
> --- !shape
> @@ -14,3 +14,8 @@
> start: *ORIGIN
> color: 0xFFEEBB
> text: Pretty vector drawing.
> +
> +#CHECK: !<tag:clarkevans.com,2002:shape>
> +#CHECK: !<tag:clarkevans.com,2002:circle>
> +#CHECK: !<tag:clarkevans.com,2002:line>
> +#CHECK: !<tag:clarkevans.com,2002:label>
>
> Modified: llvm/trunk/test/YAMLParser/spec-07-04.data
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/YAMLParser/spec-07-04.data?rev=193004&r1=193003&r2=193004&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/YAMLParser/spec-07-04.data (original)
> +++ llvm/trunk/test/YAMLParser/spec-07-04.data Fri Oct 18 17:38:04 2013
> @@ -1,5 +1,7 @@
> -# RUN: yaml-bench -canonical %s
> +# RUN: yaml-bench -canonical %s | FileCheck %s
>
> %TAG !yaml! tag:yaml.org,2002:
> ---
> !yaml!str "foo"
> +
> +#CHECK: !!str "foo"
>
> Modified: llvm/trunk/test/YAMLParser/yaml.data
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/YAMLParser/yaml.data?rev=193004&r1=193003&r2=193004&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/YAMLParser/yaml.data (original)
> +++ llvm/trunk/test/YAMLParser/yaml.data Fri Oct 18 17:38:04 2013
> @@ -1,5 +1,11 @@
> -# RUN: yaml-bench -canonical %s
> +# RUN: yaml-bench -canonical %s | FileCheck %s
>
> - !!yaml '!'
> - !!yaml '&'
> - !!yaml '*'
> +
> +# CHECK: !!seq [
> +# CHECK: !!yaml "!",
> +# CHECK: !!yaml "&",
> +# CHECK: !!yaml "*",
> +# CHECK: ]
>
> Modified: llvm/trunk/utils/yaml-bench/YAMLBench.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/yaml-bench/YAMLBench.cpp?rev=193004&r1=193003&r2=193004&view=diff
>
> ==============================================================================
> --- llvm/trunk/utils/yaml-bench/YAMLBench.cpp (original)
> +++ llvm/trunk/utils/yaml-bench/YAMLBench.cpp Fri Oct 18 17:38:04 2013
> @@ -63,6 +63,20 @@ static raw_ostream &operator <<(raw_ostr
> return os;
> }
>
> +/// \brief Pretty print a tag by replacing tag:yaml.org,2002: with !!.
> +static std::string prettyTag(yaml::Node *N) {
> + std::string Tag = N->getVerbatimTag();
> + if (StringRef(Tag).startswith("tag:yaml.org,2002:")) {
> + std::string Ret = "!!";
> + Ret += StringRef(Tag).substr(18);
> + return std::move(Ret);
> + }
> + std::string Ret = "!<";
> + Ret += Tag;
> + Ret += ">";
> + return Ret;
> +}
> +
> static void dumpNode( yaml::Node *n
> , unsigned Indent = 0
> , bool SuppressFirstIndent = false) {
> @@ -76,9 +90,9 @@ static void dumpNode( yaml::Node *n
> if (yaml::ScalarNode *sn = dyn_cast<yaml::ScalarNode>(n)) {
> SmallString<32> Storage;
> StringRef Val = sn->getValue(Storage);
> - outs() << "!!str \"" << yaml::escape(Val) << "\"";
> + outs() << prettyTag(n) << " \"" << yaml::escape(Val) << "\"";
> } else if (yaml::SequenceNode *sn = dyn_cast<yaml::SequenceNode>(n)) {
> - outs() << "!!seq [\n";
> + outs() << prettyTag(n) << " [\n";
> ++Indent;
> for (yaml::SequenceNode::iterator i = sn->begin(), e = sn->end();
> i != e; ++i) {
> @@ -88,7 +102,7 @@ static void dumpNode( yaml::Node *n
> --Indent;
> outs() << indent(Indent) << "]";
> } else if (yaml::MappingNode *mn = dyn_cast<yaml::MappingNode>(n)) {
> - outs() << "!!map {\n";
> + outs() << prettyTag(n) << " {\n";
> ++Indent;
> for (yaml::MappingNode::iterator i = mn->begin(), e = mn->end();
> i != e; ++i) {
> @@ -104,7 +118,7 @@ static void dumpNode( yaml::Node *n
> } else if (yaml::AliasNode *an = dyn_cast<yaml::AliasNode>(n)){
> outs() << "*" << an->getName();
> } else if (dyn_cast<yaml::NullNode>(n)) {
> - outs() << "!!null null";
> + outs() << prettyTag(n) << " null";
> }
> }
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20131018/3b655b0e/attachment.html>
More information about the llvm-commits
mailing list