//
//===----------------------------------------------------------------------===//
-#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/Support/Allocator.h"
#include "llvm/Support/SMLoc.h"
+#include <map>
#include <limits>
#include <utility>
OwningPtr<Document> CurrentDoc;
friend class Document;
-
- /// @brief Validate a %YAML x.x directive.
- void handleYAMLDirective(const Token &);
};
/// @brief Abstract base class for all Nodes.
class Node {
+ virtual void anchor();
public:
enum NodeKind {
NK_Null,
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; }
private:
unsigned int TypeID;
StringRef Anchor;
+ /// \brief The tag as typed in the document.
+ StringRef Tag;
};
/// @brief A null value.
/// Example:
/// !!null null
class NullNode : public Node {
+ virtual void anchor();
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;
/// Example:
/// Adena
class ScalarNode : public Node {
+ virtual void anchor();
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() - 1);
+ SMLoc End = SMLoc::getFromPointer(Val.end());
SourceRange = SMRange(Start, End);
}
/// Example:
/// Section: .text
class KeyValueNode : public Node {
+ virtual void anchor();
public:
KeyValueNode(OwningPtr<Document> &D)
- : Node(NK_KeyValue, D, StringRef())
+ : Node(NK_KeyValue, D, StringRef(), StringRef())
, Key(0)
, Value(0)
{}
/// Name: _main
/// Scope: Global
class MappingNode : public Node {
+ virtual void anchor();
public:
enum MappingType {
MT_Block,
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;
/// - Hello
/// - World
class SequenceNode : public Node {
+ virtual void anchor();
public:
enum SequenceType {
ST_Block,
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;
/// Example:
/// *AnchorName
class AliasNode : public Node {
+ virtual void anchor();
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();
return Root = parseBlockNode();
}
+ const std::map<StringRef, StringRef> &getTagMap() const {
+ return TagMap;
+ }
+
private:
friend class Node;
friend class document_iterator;
/// 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);
};
if (isAtEnd() || Other.isAtEnd())
return isAtEnd() && Other.isAtEnd();
- return *Doc == *Other.Doc;
+ return Doc == Other.Doc;
}
bool operator !=(const document_iterator &Other) {
return !(*this == Other);
private:
bool isAtEnd() const {
- return Doc == 0 || *Doc == 0;
+ return !Doc || !*Doc;
}
OwningPtr<Document> *Doc;