Merge pull request #296 from WrinklyNinja/useful-conversion-errors

Add more error messages that include the location in a parsed file.
This commit is contained in:
Jesse Beder
2015-04-03 09:41:02 -05:00
10 changed files with 47 additions and 16 deletions

View File

@@ -120,6 +120,10 @@ class Exception : public std::runtime_error {
private: private:
static const std::string build_what(const Mark& mark, static const std::string build_what(const Mark& mark,
const std::string& msg) { const std::string& msg) {
if (mark.is_null()) {
return msg.c_str();
}
std::stringstream output; std::stringstream output;
output << "yaml-cpp: error at line " << mark.line + 1 << ", column " output << "yaml-cpp: error at line " << mark.line + 1 << ", column "
<< mark.column + 1 << ": " << msg; << mark.column + 1 << ": " << msg;
@@ -178,14 +182,14 @@ class InvalidNode : public RepresentationException {
class BadConversion : public RepresentationException { class BadConversion : public RepresentationException {
public: public:
BadConversion() explicit BadConversion(const Mark& mark_)
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_CONVERSION) {} : RepresentationException(mark_, ErrorMsg::BAD_CONVERSION) {}
}; };
template <typename T> template <typename T>
class TypedBadConversion : public BadConversion { class TypedBadConversion : public BadConversion {
public: public:
TypedBadConversion() : BadConversion() {} explicit TypedBadConversion(const Mark& mark_) : BadConversion(mark_) {}
}; };
class BadDereference : public RepresentationException { class BadDereference : public RepresentationException {

View File

@@ -15,6 +15,8 @@ struct YAML_CPP_API Mark {
static const Mark null_mark() { return Mark(-1, -1, -1); } static const Mark null_mark() { return Mark(-1, -1, -1); }
bool is_null() const { return pos == -1 && line == -1 && column == -1; }
int pos; int pos;
int line, column; int line, column;

View File

@@ -25,6 +25,7 @@ class node : private boost::noncopyable {
const node_ref* ref() const { return m_pRef.get(); } const node_ref* ref() const { return m_pRef.get(); }
bool is_defined() const { return m_pRef->is_defined(); } bool is_defined() const { return m_pRef->is_defined(); }
const Mark& mark() const { return m_pRef->mark(); }
NodeType::value type() const { return m_pRef->type(); } NodeType::value type() const { return m_pRef->type(); }
const std::string& scalar() const { return m_pRef->scalar(); } const std::string& scalar() const { return m_pRef->scalar(); }
@@ -64,6 +65,10 @@ class node : private boost::noncopyable {
m_pRef->set_data(*rhs.m_pRef); m_pRef->set_data(*rhs.m_pRef);
} }
void set_mark(const Mark& mark) {
m_pRef->set_mark(mark);
}
void set_type(NodeType::value type) { void set_type(NodeType::value type) {
if (type != NodeType::Undefined) if (type != NodeType::Undefined)
mark_defined(); mark_defined();

View File

@@ -34,6 +34,7 @@ class YAML_CPP_API node_data : private boost::noncopyable {
node_data(); node_data();
void mark_defined(); void mark_defined();
void set_mark(const Mark& mark);
void set_type(NodeType::value type); void set_type(NodeType::value type);
void set_tag(const std::string& tag); void set_tag(const std::string& tag);
void set_null(); void set_null();
@@ -41,6 +42,7 @@ class YAML_CPP_API node_data : private boost::noncopyable {
void set_style(EmitterStyle::value style); void set_style(EmitterStyle::value style);
bool is_defined() const { return m_isDefined; } bool is_defined() const { return m_isDefined; }
const Mark& mark() const { return m_mark; }
NodeType::value type() const { NodeType::value type() const {
return m_isDefined ? m_type : NodeType::Undefined; return m_isDefined ? m_type : NodeType::Undefined;
} }
@@ -97,6 +99,7 @@ class YAML_CPP_API node_data : private boost::noncopyable {
private: private:
bool m_isDefined; bool m_isDefined;
Mark m_mark;
NodeType::value m_type; NodeType::value m_type;
std::string m_tag; std::string m_tag;
EmitterStyle::value m_style; EmitterStyle::value m_style;

View File

@@ -20,6 +20,7 @@ class node_ref : private boost::noncopyable {
node_ref() : m_pData(new node_data) {} node_ref() : m_pData(new node_data) {}
bool is_defined() const { return m_pData->is_defined(); } bool is_defined() const { return m_pData->is_defined(); }
const Mark& mark() const { return m_pData->mark(); }
NodeType::value type() const { return m_pData->type(); } NodeType::value type() const { return m_pData->type(); }
const std::string& scalar() const { return m_pData->scalar(); } const std::string& scalar() const { return m_pData->scalar(); }
const std::string& tag() const { return m_pData->tag(); } const std::string& tag() const { return m_pData->tag(); }
@@ -28,6 +29,7 @@ class node_ref : private boost::noncopyable {
void mark_defined() { m_pData->mark_defined(); } void mark_defined() { m_pData->mark_defined(); }
void set_data(const node_ref& rhs) { m_pData = rhs.m_pData; } void set_data(const node_ref& rhs) { m_pData = rhs.m_pData; }
void set_mark(const Mark& mark) { m_pData->set_mark(mark); }
void set_type(NodeType::value type) { m_pData->set_type(type); } void set_type(NodeType::value type) { m_pData->set_type(type); }
void set_tag(const std::string& tag) { m_pData->set_tag(tag); } void set_tag(const std::string& tag) { m_pData->set_tag(tag); }
void set_null() { m_pData->set_null(); } void set_null() { m_pData->set_null(); }

View File

@@ -66,6 +66,13 @@ inline bool Node::IsDefined() const {
return m_pNode ? m_pNode->is_defined() : true; return m_pNode ? m_pNode->is_defined() : true;
} }
inline Mark Node::Mark() const {
if (!m_isValid) {
throw InvalidNode();
}
return m_pNode ? m_pNode->mark() : Mark::null_mark();
}
inline NodeType::value Node::Type() const { inline NodeType::value Node::Type() const {
if (!m_isValid) if (!m_isValid)
throw InvalidNode(); throw InvalidNode();
@@ -110,12 +117,12 @@ struct as_if<T, void> {
const T operator()() const { const T operator()() const {
if (!node.m_pNode) if (!node.m_pNode)
throw TypedBadConversion<T>(); throw TypedBadConversion<T>(node.Mark());
T t; T t;
if (convert<T>::decode(node, t)) if (convert<T>::decode(node, t))
return t; return t;
throw TypedBadConversion<T>(); throw TypedBadConversion<T>(node.Mark());
} }
}; };
@@ -126,7 +133,7 @@ struct as_if<std::string, void> {
const std::string operator()() const { const std::string operator()() const {
if (node.Type() != NodeType::Scalar) if (node.Type() != NodeType::Scalar)
throw TypedBadConversion<std::string>(); throw TypedBadConversion<std::string>(node.Mark());
return node.Scalar(); return node.Scalar();
} }
}; };

View File

@@ -11,6 +11,7 @@
#include "yaml-cpp/dll.h" #include "yaml-cpp/dll.h"
#include "yaml-cpp/emitterstyle.h" #include "yaml-cpp/emitterstyle.h"
#include "yaml-cpp/mark.h"
#include "yaml-cpp/node/detail/bool_type.h" #include "yaml-cpp/node/detail/bool_type.h"
#include "yaml-cpp/node/detail/iterator_fwd.h" #include "yaml-cpp/node/detail/iterator_fwd.h"
#include "yaml-cpp/node/ptr.h" #include "yaml-cpp/node/ptr.h"
@@ -48,6 +49,7 @@ class YAML_CPP_API Node {
Node(const Node& rhs); Node(const Node& rhs);
~Node(); ~Node();
YAML::Mark Mark() const;
NodeType::value Type() const; NodeType::value Type() const;
bool IsDefined() const; bool IsDefined() const;
bool IsNull() const { return Type() == NodeType::Null; } bool IsNull() const { return Type() == NodeType::Null; }

View File

@@ -17,6 +17,7 @@ std::string node_data::empty_scalar;
node_data::node_data() node_data::node_data()
: m_isDefined(false), : m_isDefined(false),
m_mark(Mark::null_mark()),
m_type(NodeType::Null), m_type(NodeType::Null),
m_style(EmitterStyle::Default), m_style(EmitterStyle::Default),
m_seqSize(0) {} m_seqSize(0) {}
@@ -27,6 +28,10 @@ void node_data::mark_defined() {
m_isDefined = true; m_isDefined = true;
} }
void node_data::set_mark(const Mark& mark) {
m_mark = mark;
}
void node_data::set_type(NodeType::value type) { void node_data::set_type(NodeType::value type) {
if (type == NodeType::Undefined) { if (type == NodeType::Undefined) {
m_type = type; m_type = type;

View File

@@ -28,8 +28,8 @@ void NodeBuilder::OnDocumentStart(const Mark&) {}
void NodeBuilder::OnDocumentEnd() {} void NodeBuilder::OnDocumentEnd() {}
void NodeBuilder::OnNull(const Mark& /* mark */, anchor_t anchor) { void NodeBuilder::OnNull(const Mark& mark, anchor_t anchor) {
detail::node& node = Push(anchor); detail::node& node = Push(mark, anchor);
node.set_null(); node.set_null();
Pop(); Pop();
} }
@@ -40,18 +40,18 @@ void NodeBuilder::OnAlias(const Mark& /* mark */, anchor_t anchor) {
Pop(); Pop();
} }
void NodeBuilder::OnScalar(const Mark& /* mark */, const std::string& tag, void NodeBuilder::OnScalar(const Mark& mark, const std::string& tag,
anchor_t anchor, const std::string& value) { anchor_t anchor, const std::string& value) {
detail::node& node = Push(anchor); detail::node& node = Push(mark, anchor);
node.set_scalar(value); node.set_scalar(value);
node.set_tag(tag); node.set_tag(tag);
Pop(); Pop();
} }
void NodeBuilder::OnSequenceStart(const Mark& /* mark */, void NodeBuilder::OnSequenceStart(const Mark& mark,
const std::string& tag, anchor_t anchor, const std::string& tag, anchor_t anchor,
EmitterStyle::value style) { EmitterStyle::value style) {
detail::node& node = Push(anchor); detail::node& node = Push(mark, anchor);
node.set_tag(tag); node.set_tag(tag);
node.set_type(NodeType::Sequence); node.set_type(NodeType::Sequence);
node.set_style(style); node.set_style(style);
@@ -59,9 +59,9 @@ void NodeBuilder::OnSequenceStart(const Mark& /* mark */,
void NodeBuilder::OnSequenceEnd() { Pop(); } void NodeBuilder::OnSequenceEnd() { Pop(); }
void NodeBuilder::OnMapStart(const Mark& /* mark */, const std::string& tag, void NodeBuilder::OnMapStart(const Mark& mark, const std::string& tag,
anchor_t anchor, EmitterStyle::value style) { anchor_t anchor, EmitterStyle::value style) {
detail::node& node = Push(anchor); detail::node& node = Push(mark, anchor);
node.set_type(NodeType::Map); node.set_type(NodeType::Map);
node.set_tag(tag); node.set_tag(tag);
node.set_style(style); node.set_style(style);
@@ -74,8 +74,9 @@ void NodeBuilder::OnMapEnd() {
Pop(); Pop();
} }
detail::node& NodeBuilder::Push(anchor_t anchor) { detail::node& NodeBuilder::Push(const Mark& mark, anchor_t anchor) {
detail::node& node = m_pMemory->create_node(); detail::node& node = m_pMemory->create_node();
node.set_mark(mark);
RegisterAnchor(anchor, node); RegisterAnchor(anchor, node);
Push(node); Push(node);
return node; return node;

View File

@@ -48,7 +48,7 @@ class NodeBuilder : public EventHandler {
virtual void OnMapEnd(); virtual void OnMapEnd();
private: private:
detail::node& Push(anchor_t anchor); detail::node& Push(const Mark& mark, anchor_t anchor);
void Push(detail::node& node); void Push(detail::node& node);
void Pop(); void Pop();
void RegisterAnchor(anchor_t anchor, detail::node& node); void RegisterAnchor(anchor_t anchor, detail::node& node);