Improved location info of error report.

This commit is contained in:
yhirose 2015-04-01 13:36:03 -04:00
parent 26060c0f00
commit 1f48b4ca82

View File

@ -189,6 +189,13 @@ struct SemanticValues : protected std::vector<SemanticValue>
SemanticValues() : s(nullptr), n(0), choice(0) {} 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; typedef SemanticValue T;
using std::vector<T>::iterator; using std::vector<T>::iterator;
using std::vector<T>::const_iterator; using std::vector<T>::const_iterator;
@ -442,8 +449,9 @@ struct Context
const char* s; const char* s;
size_t l; size_t l;
const char* error_ptr; const char* error_pos;
const char* msg; // TODO: should be `int`. const char* message_pos;
std::string message; // TODO: should be `int`.
size_t def_count; size_t def_count;
std::vector<bool> cache_register; std::vector<bool> cache_register;
@ -457,6 +465,8 @@ struct Context
Context(const char* _s, size_t _l, size_t _def_count, bool enablePackratParsing) Context(const char* _s, size_t _l, size_t _def_count, bool enablePackratParsing)
: s(_s) : s(_s)
, l(_l) , l(_l)
, error_pos(nullptr)
, message_pos(nullptr)
, def_count(_def_count) , def_count(_def_count)
, cache_register(enablePackratParsing ? def_count * (l + 1) : 0) , cache_register(enablePackratParsing ? def_count * (l + 1) : 0)
, cache_success(enablePackratParsing ? def_count * (l + 1) : 0) , cache_success(enablePackratParsing ? def_count * (l + 1) : 0)
@ -512,6 +522,10 @@ struct Context
void pop() { void pop() {
stack_size--; 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; const auto& rule = *ope;
auto len = rule.parse(s + i, n - i, sv, c, dt); auto len = rule.parse(s + i, n - i, sv, c, dt);
if (fail(len)) { if (fail(len)) {
if (!c.msg) {
c.msg = "missing an element in the 'sequence'";
}
return -1; return -1;
} }
i += len; i += len;
@ -614,8 +625,6 @@ public:
id++; id++;
c.pop(); c.pop();
} }
c.error_ptr = s;
c.msg = "nothing was matched in the 'prioritized choice'";
return -1; return -1;
} }
@ -660,9 +669,6 @@ public:
const auto& rule = *ope_; const auto& rule = *ope_;
auto len = rule.parse(s, n, sv, c, dt); auto len = rule.parse(s, n, sv, c, dt);
if (fail(len)) { if (fail(len)) {
if (!c.msg) {
c.msg = "nothing occurred in the 'one-or-more'";
}
return -1; return -1;
} }
auto i = len; auto i = len;
@ -728,11 +734,13 @@ public:
int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override { int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
const auto& rule = *ope_; const auto& rule = *ope_;
auto error_pos = c.error_pos;
auto len = rule.parse(s, n, sv, c, dt); auto len = rule.parse(s, n, sv, c, dt);
if (success(len)) { if (success(len)) {
c.error_ptr = s; c.set_error_pos(s);
return -1; return -1;
} else { } else {
c.error_pos = error_pos;
return 0; return 0;
} }
} }
@ -752,7 +760,7 @@ public:
auto i = 0u; auto i = 0u;
for (; i < lit_.size(); i++) { for (; i < lit_.size(); i++) {
if (i >= n || s[i] != lit_[i]) { if (i >= n || s[i] != lit_[i]) {
c.error_ptr = s; c.set_error_pos(s);
return -1; return -1;
} }
} }
@ -773,7 +781,7 @@ public:
int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override { int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
// TODO: UTF8 support // TODO: UTF8 support
if (n < 1) { if (n < 1) {
c.error_ptr = s; c.set_error_pos(s);
return -1; return -1;
} }
auto ch = s[0]; auto ch = s[0];
@ -791,7 +799,7 @@ public:
i += 1; i += 1;
} }
} }
c.error_ptr = s; c.set_error_pos(s);
return -1; return -1;
} }
@ -809,7 +817,7 @@ public:
int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override { int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
// TODO: UTF8 support // TODO: UTF8 support
if (n < 1 || s[0] != ch_) { if (n < 1 || s[0] != ch_) {
c.error_ptr = s; c.set_error_pos(s);
return -1; return -1;
} }
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 { int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
// TODO: UTF8 support // TODO: UTF8 support
if (n < 1) { if (n < 1) {
c.error_ptr = s; c.set_error_pos(s);
return -1; return -1;
} }
return 1; return 1;
@ -1046,10 +1054,11 @@ class Definition
{ {
public: public:
struct Result { struct Result {
bool ret; bool ret;
int len; int len;
const char* error_ptr; const char* error_pos;
const char* msg; const char* message_pos;
const std::string message;
}; };
Definition() Definition()
@ -1176,11 +1185,12 @@ public:
holder_->accept(v); holder_->accept(v);
} }
std::string name; std::string name;
size_t id; size_t id;
std::vector<Action> actions; std::vector<Action> actions;
bool ignoreSemanticValue; std::function<std::string ()> error_message;
bool enablePackratParsing; bool ignoreSemanticValue;
bool enablePackratParsing;
private: private:
friend class DefinitionReference; friend class DefinitionReference;
@ -1194,7 +1204,7 @@ private:
Context c(s, n, defIds.ids.size(), enablePackratParsing); Context c(s, n, defIds.ids.size(), enablePackratParsing);
auto len = holder_->parse(s, n, sv, c, dt); 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> holder_; std::shared_ptr<Holder> 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); 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; return len;
} }
@ -1379,8 +1394,8 @@ inline std::shared_ptr<Ope> ref(const std::unordered_map<std::string, Definition
* PEG parser generator * PEG parser generator
*---------------------------------------------------------------------------*/ *---------------------------------------------------------------------------*/
inline std::pair<size_t, size_t> line_info(const char* beg, const char* cur) { inline std::pair<size_t, size_t> line_info(const char* start, const char* cur) {
auto p = beg; auto p = start;
auto col_ptr = p; auto col_ptr = p;
auto no = 1; auto no = 1;
@ -1659,8 +1674,8 @@ private:
if (!r.ret) { if (!r.ret) {
if (log) { if (log) {
auto line = line_info(s, r.error_ptr); auto line = line_info(s, r.error_pos);
log(line.first, line.second, r.msg ? "syntax error" : r.msg); log(line.first, line.second, r.message.empty() ? "syntax error" : r.message);
} }
return nullptr; return nullptr;
} }
@ -1951,8 +1966,8 @@ private:
void output_log(const char* s, size_t n, Log log, const Definition::Result& r) const { void output_log(const char* s, size_t n, Log log, const Definition::Result& r) const {
if (log) { if (log) {
if (!r.ret) { if (!r.ret) {
auto line = line_info(s, r.error_ptr); auto line = line_info(s, r.error_pos);
log(line.first, line.second, r.msg ? "syntax error" : r.msg); log(line.first, line.second, r.message.empty() ? "syntax error" : r.message);
} else if (r.len != n) { } else if (r.len != n) {
auto line = line_info(s, s + r.len); auto line = line_info(s, s + r.len);
log(line.first, line.second, "syntax error"); log(line.first, line.second, "syntax error");