From 1f48b4ca82dce203f542b7a09fe3c09bae1ed2a1 Mon Sep 17 00:00:00 2001 From: yhirose Date: Wed, 1 Apr 2015 13:36:03 -0400 Subject: [PATCH] Improved location info of error report. --- peglib.h | 79 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 47 insertions(+), 32 deletions(-) diff --git a/peglib.h b/peglib.h index 722764f..a8a85a1 100644 --- a/peglib.h +++ b/peglib.h @@ -189,6 +189,13 @@ struct SemanticValues : protected std::vector SemanticValues() : s(nullptr), n(0), choice(0) {} + std::string str(size_t i = 0) const { + if (i > 0) { + return (*this)[i].str(); + } + return std::string(s, n); + } + typedef SemanticValue T; using std::vector::iterator; using std::vector::const_iterator; @@ -442,8 +449,9 @@ struct Context const char* s; size_t l; - const char* error_ptr; - const char* msg; // TODO: should be `int`. + const char* error_pos; + const char* message_pos; + std::string message; // TODO: should be `int`. size_t def_count; std::vector cache_register; @@ -457,6 +465,8 @@ struct Context Context(const char* _s, size_t _l, size_t _def_count, bool enablePackratParsing) : s(_s) , l(_l) + , error_pos(nullptr) + , message_pos(nullptr) , def_count(_def_count) , cache_register(enablePackratParsing ? def_count * (l + 1) : 0) , cache_success(enablePackratParsing ? def_count * (l + 1) : 0) @@ -512,6 +522,10 @@ struct Context void pop() { stack_size--; } + + void set_error_pos(const char* s) { + if (error_pos < s) error_pos = s; + } }; /* @@ -557,9 +571,6 @@ public: const auto& rule = *ope; auto len = rule.parse(s + i, n - i, sv, c, dt); if (fail(len)) { - if (!c.msg) { - c.msg = "missing an element in the 'sequence'"; - } return -1; } i += len; @@ -614,8 +625,6 @@ public: id++; c.pop(); } - c.error_ptr = s; - c.msg = "nothing was matched in the 'prioritized choice'"; return -1; } @@ -660,9 +669,6 @@ public: const auto& rule = *ope_; auto len = rule.parse(s, n, sv, c, dt); if (fail(len)) { - if (!c.msg) { - c.msg = "nothing occurred in the 'one-or-more'"; - } return -1; } auto i = len; @@ -728,11 +734,13 @@ public: int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override { const auto& rule = *ope_; + auto error_pos = c.error_pos; auto len = rule.parse(s, n, sv, c, dt); if (success(len)) { - c.error_ptr = s; + c.set_error_pos(s); return -1; } else { + c.error_pos = error_pos; return 0; } } @@ -752,7 +760,7 @@ public: auto i = 0u; for (; i < lit_.size(); i++) { if (i >= n || s[i] != lit_[i]) { - c.error_ptr = s; + c.set_error_pos(s); return -1; } } @@ -773,7 +781,7 @@ public: int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override { // TODO: UTF8 support if (n < 1) { - c.error_ptr = s; + c.set_error_pos(s); return -1; } auto ch = s[0]; @@ -791,7 +799,7 @@ public: i += 1; } } - c.error_ptr = s; + c.set_error_pos(s); return -1; } @@ -809,7 +817,7 @@ public: int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override { // TODO: UTF8 support if (n < 1 || s[0] != ch_) { - c.error_ptr = s; + c.set_error_pos(s); return -1; } return 1; @@ -827,7 +835,7 @@ public: int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override { // TODO: UTF8 support if (n < 1) { - c.error_ptr = s; + c.set_error_pos(s); return -1; } return 1; @@ -1046,10 +1054,11 @@ class Definition { public: struct Result { - bool ret; - int len; - const char* error_ptr; - const char* msg; + bool ret; + int len; + const char* error_pos; + const char* message_pos; + const std::string message; }; Definition() @@ -1176,11 +1185,12 @@ public: holder_->accept(v); } - std::string name; - size_t id; - std::vector actions; - bool ignoreSemanticValue; - bool enablePackratParsing; + std::string name; + size_t id; + std::vector actions; + std::function error_message; + bool ignoreSemanticValue; + bool enablePackratParsing; private: friend class DefinitionReference; @@ -1194,7 +1204,7 @@ private: Context c(s, n, defIds.ids.size(), enablePackratParsing); auto len = holder_->parse(s, n, sv, c, dt); - return Result { success(len), len, c.error_ptr, c.msg }; + return Result{ success(len), len, c.error_pos, c.message_pos, c.message }; } std::shared_ptr holder_; @@ -1248,6 +1258,11 @@ inline int Holder::parse(const char* s, size_t n, SemanticValues& sv, Context& c sv.emplace_back(val, outer_->name.c_str(), ancs, ancn); } + if (fail(len) && outer_->error_message && !c.message_pos) { + c.message_pos = s; + c.message = outer_->error_message(); + } + return len; } @@ -1379,8 +1394,8 @@ inline std::shared_ptr ref(const std::unordered_map line_info(const char* beg, const char* cur) { - auto p = beg; +inline std::pair line_info(const char* start, const char* cur) { + auto p = start; auto col_ptr = p; auto no = 1; @@ -1659,8 +1674,8 @@ private: if (!r.ret) { if (log) { - auto line = line_info(s, r.error_ptr); - log(line.first, line.second, r.msg ? "syntax error" : r.msg); + auto line = line_info(s, r.error_pos); + log(line.first, line.second, r.message.empty() ? "syntax error" : r.message); } return nullptr; } @@ -1951,8 +1966,8 @@ private: void output_log(const char* s, size_t n, Log log, const Definition::Result& r) const { if (log) { if (!r.ret) { - auto line = line_info(s, r.error_ptr); - log(line.first, line.second, r.msg ? "syntax error" : r.msg); + auto line = line_info(s, r.error_pos); + log(line.first, line.second, r.message.empty() ? "syntax error" : r.message); } else if (r.len != n) { auto line = line_info(s, s + r.len); log(line.first, line.second, "syntax error");