Improved location info of error report.

pull/3/head
yhirose 9 years ago
parent 26060c0f00
commit 1f48b4ca82
  1. 79
      peglib.h

@ -189,6 +189,13 @@ struct SemanticValues : protected std::vector<SemanticValue>
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<T>::iterator;
using std::vector<T>::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<bool> 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<Action> actions;
bool ignoreSemanticValue;
bool enablePackratParsing;
std::string name;
size_t id;
std::vector<Action> actions;
std::function<std::string ()> 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> 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<Ope> ref(const std::unordered_map<std::string, Definition
* PEG parser generator
*---------------------------------------------------------------------------*/
inline std::pair<size_t, size_t> line_info(const char* beg, const char* cur) {
auto p = beg;
inline std::pair<size_t, size_t> 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");

Loading…
Cancel
Save