mirror of
https://github.com/yhirose/cpp-peglib.git
synced 2024-12-22 20:05:31 +00:00
Merge pull request #88 from yhirose/trace
Improved peglint trace format
This commit is contained in:
commit
748e82dae0
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include <peglib.h>
|
#include <peglib.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -99,28 +100,59 @@ int main(int argc, const char** argv)
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (opt_trace) {
|
if (opt_trace) {
|
||||||
std::cout << "pos:lev\trule/ope" << std::endl;
|
|
||||||
std::cout << "-------\t--------" << std::endl;
|
|
||||||
size_t prev_pos = 0;
|
size_t prev_pos = 0;
|
||||||
parser.enable_trace([&](
|
parser.enable_trace(
|
||||||
const char* name,
|
[&](const char* name,
|
||||||
const char* s,
|
const char* s,
|
||||||
size_t /*n*/,
|
size_t /*n*/,
|
||||||
const peg::SemanticValues& /*sv*/,
|
const peg::SemanticValues& /*sv*/,
|
||||||
const peg::Context& c,
|
const peg::Context& c,
|
||||||
const peg::any& /*dt*/) {
|
const peg::any& /*dt*/) {
|
||||||
auto pos = static_cast<size_t>(s - c.s);
|
auto pos = static_cast<size_t>(s - c.s);
|
||||||
auto backtrack = (pos < prev_pos ? "*" : "");
|
auto backtrack = (pos < prev_pos ? "*" : "");
|
||||||
string indent;
|
string indent;
|
||||||
auto level = c.nest_level;
|
auto level = c.trace_ids.size() - 1;
|
||||||
while (level--) {
|
while (level--) { indent += "│"; }
|
||||||
indent += " ";
|
std::cout
|
||||||
|
<< "E " << pos << backtrack << "\t"
|
||||||
|
<< indent << "┌" << name
|
||||||
|
<< " #" << c.trace_ids.back()
|
||||||
|
<< std::endl;
|
||||||
|
prev_pos = static_cast<size_t>(pos);
|
||||||
|
},
|
||||||
|
[&](const char* name,
|
||||||
|
const char* s,
|
||||||
|
size_t /*n*/,
|
||||||
|
const peg::SemanticValues& sv,
|
||||||
|
const peg::Context& c,
|
||||||
|
const peg::any& /*dt*/,
|
||||||
|
size_t len) {
|
||||||
|
auto pos = static_cast<size_t>(s - c.s);
|
||||||
|
if (len != -1) {
|
||||||
|
pos += len;
|
||||||
|
}
|
||||||
|
string indent;
|
||||||
|
auto level = c.trace_ids.size() - 1;
|
||||||
|
while (level--) { indent += "│"; }
|
||||||
|
auto ret = len != -1 ? "└o " : "└x ";
|
||||||
|
std::stringstream choice;
|
||||||
|
if (sv.choice_count() > 0) {
|
||||||
|
choice << " " << sv.choice() << "/" << sv.choice_count();
|
||||||
|
}
|
||||||
|
std::string token;
|
||||||
|
if (!sv.tokens.empty()) {
|
||||||
|
const auto& tok = sv.tokens[0];
|
||||||
|
token += " '" + std::string(tok.first, tok.second) + "'";
|
||||||
|
}
|
||||||
|
std::cout
|
||||||
|
<< "L " << pos << "\t"
|
||||||
|
<< indent << ret << name
|
||||||
|
<< " #" << c.trace_ids.back()
|
||||||
|
<< choice.str()
|
||||||
|
<< token
|
||||||
|
<< std::endl;
|
||||||
}
|
}
|
||||||
std::cout
|
);
|
||||||
<< pos << ":" << c.nest_level << backtrack << "\t"
|
|
||||||
<< indent << name << std::endl;
|
|
||||||
prev_pos = static_cast<size_t>(pos);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opt_ast) {
|
if (opt_ast) {
|
||||||
|
213
peglib.h
213
peglib.h
@ -777,7 +777,9 @@ class Context;
|
|||||||
class Ope;
|
class Ope;
|
||||||
class Definition;
|
class Definition;
|
||||||
|
|
||||||
typedef std::function<void (const char* name, const char* s, size_t n, const SemanticValues& sv, const Context& c, const any& dt)> Tracer;
|
typedef std::function<void (const char* name, const char* s, size_t n, const SemanticValues& sv, const Context& c, const any& dt)> TracerEnter;
|
||||||
|
|
||||||
|
typedef std::function<void (const char* name, const char* s, size_t n, const SemanticValues& sv, const Context& c, const any& dt, size_t)> TracerLeave;
|
||||||
|
|
||||||
class Context
|
class Context
|
||||||
{
|
{
|
||||||
@ -795,8 +797,6 @@ public:
|
|||||||
size_t value_stack_size = 0;
|
size_t value_stack_size = 0;
|
||||||
std::vector<std::vector<std::shared_ptr<Ope>>> args_stack;
|
std::vector<std::vector<std::shared_ptr<Ope>>> args_stack;
|
||||||
|
|
||||||
size_t nest_level = 0;
|
|
||||||
|
|
||||||
bool in_token = false;
|
bool in_token = false;
|
||||||
|
|
||||||
std::shared_ptr<Ope> whitespaceOpe;
|
std::shared_ptr<Ope> whitespaceOpe;
|
||||||
@ -814,7 +814,8 @@ public:
|
|||||||
|
|
||||||
std::map<std::pair<size_t, size_t>, std::tuple<size_t, any>> cache_values;
|
std::map<std::pair<size_t, size_t>, std::tuple<size_t, any>> cache_values;
|
||||||
|
|
||||||
std::function<void (const char*, const char*, size_t, const SemanticValues&, const Context&, const any&)> tracer;
|
TracerEnter tracer_enter;
|
||||||
|
TracerLeave tracer_leave;
|
||||||
|
|
||||||
Context(
|
Context(
|
||||||
const char* a_path,
|
const char* a_path,
|
||||||
@ -824,7 +825,8 @@ public:
|
|||||||
std::shared_ptr<Ope> a_whitespaceOpe,
|
std::shared_ptr<Ope> a_whitespaceOpe,
|
||||||
std::shared_ptr<Ope> a_wordOpe,
|
std::shared_ptr<Ope> a_wordOpe,
|
||||||
bool a_enablePackratParsing,
|
bool a_enablePackratParsing,
|
||||||
Tracer a_tracer)
|
TracerEnter a_tracer_enter,
|
||||||
|
TracerLeave a_tracer_leave)
|
||||||
: path(a_path)
|
: path(a_path)
|
||||||
, s(a_s)
|
, s(a_s)
|
||||||
, l(a_l)
|
, l(a_l)
|
||||||
@ -834,7 +836,8 @@ public:
|
|||||||
, enablePackratParsing(a_enablePackratParsing)
|
, enablePackratParsing(a_enablePackratParsing)
|
||||||
, cache_registered(enablePackratParsing ? def_count * (l + 1) : 0)
|
, cache_registered(enablePackratParsing ? def_count * (l + 1) : 0)
|
||||||
, cache_success(enablePackratParsing ? def_count * (l + 1) : 0)
|
, cache_success(enablePackratParsing ? def_count * (l + 1) : 0)
|
||||||
, tracer(a_tracer) {
|
, tracer_enter(a_tracer_enter)
|
||||||
|
, tracer_leave(a_tracer_leave) {
|
||||||
|
|
||||||
for (size_t pos = 0; pos < l; pos++) {
|
for (size_t pos = 0; pos < l; pos++) {
|
||||||
if (s[pos] == '\n') {
|
if (s[pos] == '\n') {
|
||||||
@ -955,9 +958,12 @@ public:
|
|||||||
if (error_pos < a_s) error_pos = a_s;
|
if (error_pos < a_s) error_pos = a_s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void trace(const char* name, const char* a_s, size_t n, SemanticValues& sv, any& dt) const {
|
void trace_enter(const char* name, const char* a_s, size_t n, SemanticValues& sv, any& dt) const;
|
||||||
if (tracer) tracer(name, a_s, n, sv, *this, dt);
|
void trace_leave(const char* name, const char* a_s, size_t n, SemanticValues& sv, any& dt, size_t len) const;
|
||||||
}
|
bool is_traceable(const Ope& ope) const;
|
||||||
|
|
||||||
|
mutable size_t next_trace_id = 0;
|
||||||
|
mutable std::list<size_t> trace_ids;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -969,7 +975,8 @@ public:
|
|||||||
struct Visitor;
|
struct Visitor;
|
||||||
|
|
||||||
virtual ~Ope() {}
|
virtual ~Ope() {}
|
||||||
virtual size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const = 0;
|
size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const;
|
||||||
|
virtual size_t parse_core(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const = 0;
|
||||||
virtual void accept(Visitor& v) = 0;
|
virtual void accept(Visitor& v) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -981,14 +988,11 @@ public:
|
|||||||
Sequence(const std::vector<std::shared_ptr<Ope>>& opes) : opes_(opes) {}
|
Sequence(const std::vector<std::shared_ptr<Ope>>& opes) : opes_(opes) {}
|
||||||
Sequence(std::vector<std::shared_ptr<Ope>>&& opes) : opes_(opes) {}
|
Sequence(std::vector<std::shared_ptr<Ope>>&& opes) : opes_(opes) {}
|
||||||
|
|
||||||
size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
size_t parse_core(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
c.trace("Sequence", s, n, sv, dt);
|
|
||||||
auto& chldsv = c.push();
|
auto& chldsv = c.push();
|
||||||
auto pop_se = make_scope_exit([&]() { c.pop(); });
|
auto pop_se = make_scope_exit([&]() { c.pop(); });
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (const auto& ope : opes_) {
|
for (const auto& ope : opes_) {
|
||||||
c.nest_level++;
|
|
||||||
auto se = make_scope_exit([&]() { c.nest_level--; });
|
|
||||||
const auto& rule = *ope;
|
const auto& rule = *ope;
|
||||||
auto len = rule.parse(s + i, n - i, chldsv, c, dt);
|
auto len = rule.parse(s + i, n - i, chldsv, c, dt);
|
||||||
if (fail(len)) {
|
if (fail(len)) {
|
||||||
@ -1029,15 +1033,12 @@ public:
|
|||||||
PrioritizedChoice(const std::vector<std::shared_ptr<Ope>>& opes) : opes_(opes) {}
|
PrioritizedChoice(const std::vector<std::shared_ptr<Ope>>& opes) : opes_(opes) {}
|
||||||
PrioritizedChoice(std::vector<std::shared_ptr<Ope>>&& opes) : opes_(opes) {}
|
PrioritizedChoice(std::vector<std::shared_ptr<Ope>>&& opes) : opes_(opes) {}
|
||||||
|
|
||||||
size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
size_t parse_core(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
c.trace("PrioritizedChoice", s, n, sv, dt);
|
|
||||||
size_t id = 0;
|
size_t id = 0;
|
||||||
for (const auto& ope : opes_) {
|
for (const auto& ope : opes_) {
|
||||||
c.nest_level++;
|
|
||||||
auto& chldsv = c.push();
|
auto& chldsv = c.push();
|
||||||
c.push_capture_scope();
|
c.push_capture_scope();
|
||||||
auto se = make_scope_exit([&]() {
|
auto se = make_scope_exit([&]() {
|
||||||
c.nest_level--;
|
|
||||||
c.pop();
|
c.pop();
|
||||||
c.pop_capture_scope();
|
c.pop_capture_scope();
|
||||||
});
|
});
|
||||||
@ -1084,15 +1085,12 @@ class ZeroOrMore : public Ope
|
|||||||
public:
|
public:
|
||||||
ZeroOrMore(const std::shared_ptr<Ope>& ope) : ope_(ope) {}
|
ZeroOrMore(const std::shared_ptr<Ope>& ope) : ope_(ope) {}
|
||||||
|
|
||||||
size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
size_t parse_core(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
c.trace("ZeroOrMore", s, n, sv, dt);
|
|
||||||
auto save_error_pos = c.error_pos;
|
auto save_error_pos = c.error_pos;
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
while (n - i > 0) {
|
while (n - i > 0) {
|
||||||
c.nest_level++;
|
|
||||||
c.push_capture_scope();
|
c.push_capture_scope();
|
||||||
auto se = make_scope_exit([&]() {
|
auto se = make_scope_exit([&]() {
|
||||||
c.nest_level--;
|
|
||||||
c.pop_capture_scope();
|
c.pop_capture_scope();
|
||||||
});
|
});
|
||||||
auto save_sv_size = sv.size();
|
auto save_sv_size = sv.size();
|
||||||
@ -1127,14 +1125,11 @@ class OneOrMore : public Ope
|
|||||||
public:
|
public:
|
||||||
OneOrMore(const std::shared_ptr<Ope>& ope) : ope_(ope) {}
|
OneOrMore(const std::shared_ptr<Ope>& ope) : ope_(ope) {}
|
||||||
|
|
||||||
size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
size_t parse_core(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
c.trace("OneOrMore", s, n, sv, dt);
|
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
{
|
{
|
||||||
c.nest_level++;
|
|
||||||
c.push_capture_scope();
|
c.push_capture_scope();
|
||||||
auto se = make_scope_exit([&]() {
|
auto se = make_scope_exit([&]() {
|
||||||
c.nest_level--;
|
|
||||||
c.pop_capture_scope();
|
c.pop_capture_scope();
|
||||||
});
|
});
|
||||||
const auto& rule = *ope_;
|
const auto& rule = *ope_;
|
||||||
@ -1148,10 +1143,8 @@ public:
|
|||||||
auto save_error_pos = c.error_pos;
|
auto save_error_pos = c.error_pos;
|
||||||
auto i = len;
|
auto i = len;
|
||||||
while (n - i > 0) {
|
while (n - i > 0) {
|
||||||
c.nest_level++;
|
|
||||||
c.push_capture_scope();
|
c.push_capture_scope();
|
||||||
auto se = make_scope_exit([&]() {
|
auto se = make_scope_exit([&]() {
|
||||||
c.nest_level--;
|
|
||||||
c.pop_capture_scope();
|
c.pop_capture_scope();
|
||||||
});
|
});
|
||||||
auto save_sv_size = sv.size();
|
auto save_sv_size = sv.size();
|
||||||
@ -1186,15 +1179,12 @@ class Option : public Ope
|
|||||||
public:
|
public:
|
||||||
Option(const std::shared_ptr<Ope>& ope) : ope_(ope) {}
|
Option(const std::shared_ptr<Ope>& ope) : ope_(ope) {}
|
||||||
|
|
||||||
size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
size_t parse_core(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
c.trace("Option", s, n, sv, dt);
|
|
||||||
auto save_error_pos = c.error_pos;
|
auto save_error_pos = c.error_pos;
|
||||||
c.nest_level++;
|
|
||||||
auto save_sv_size = sv.size();
|
auto save_sv_size = sv.size();
|
||||||
auto save_tok_size = sv.tokens.size();
|
auto save_tok_size = sv.tokens.size();
|
||||||
c.push_capture_scope();
|
c.push_capture_scope();
|
||||||
auto se = make_scope_exit([&]() {
|
auto se = make_scope_exit([&]() {
|
||||||
c.nest_level--;
|
|
||||||
c.pop_capture_scope();
|
c.pop_capture_scope();
|
||||||
});
|
});
|
||||||
const auto& rule = *ope_;
|
const auto& rule = *ope_;
|
||||||
@ -1225,13 +1215,10 @@ class AndPredicate : public Ope
|
|||||||
public:
|
public:
|
||||||
AndPredicate(const std::shared_ptr<Ope>& ope) : ope_(ope) {}
|
AndPredicate(const std::shared_ptr<Ope>& ope) : ope_(ope) {}
|
||||||
|
|
||||||
size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
size_t parse_core(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
c.trace("AndPredicate", s, n, sv, dt);
|
|
||||||
c.nest_level++;
|
|
||||||
auto& chldsv = c.push();
|
auto& chldsv = c.push();
|
||||||
c.push_capture_scope();
|
c.push_capture_scope();
|
||||||
auto se = make_scope_exit([&]() {
|
auto se = make_scope_exit([&]() {
|
||||||
c.nest_level--;
|
|
||||||
c.pop();
|
c.pop();
|
||||||
c.pop_capture_scope();
|
c.pop_capture_scope();
|
||||||
});
|
});
|
||||||
@ -1254,14 +1241,11 @@ class NotPredicate : public Ope
|
|||||||
public:
|
public:
|
||||||
NotPredicate(const std::shared_ptr<Ope>& ope) : ope_(ope) {}
|
NotPredicate(const std::shared_ptr<Ope>& ope) : ope_(ope) {}
|
||||||
|
|
||||||
size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
size_t parse_core(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
c.trace("NotPredicate", s, n, sv, dt);
|
|
||||||
auto save_error_pos = c.error_pos;
|
auto save_error_pos = c.error_pos;
|
||||||
c.nest_level++;
|
|
||||||
auto& chldsv = c.push();
|
auto& chldsv = c.push();
|
||||||
c.push_capture_scope();
|
c.push_capture_scope();
|
||||||
auto se = make_scope_exit([&]() {
|
auto se = make_scope_exit([&]() {
|
||||||
c.nest_level--;
|
|
||||||
c.pop();
|
c.pop();
|
||||||
c.pop_capture_scope();
|
c.pop_capture_scope();
|
||||||
});
|
});
|
||||||
@ -1292,7 +1276,7 @@ public:
|
|||||||
, is_word_(false)
|
, is_word_(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override;
|
size_t parse_core(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override;
|
||||||
|
|
||||||
void accept(Visitor& v) override;
|
void accept(Visitor& v) override;
|
||||||
|
|
||||||
@ -1328,9 +1312,7 @@ public:
|
|||||||
assert(!ranges_.empty());
|
assert(!ranges_.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
size_t parse_core(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
c.trace("CharacterClass", s, n, sv, dt);
|
|
||||||
|
|
||||||
if (n < 1) {
|
if (n < 1) {
|
||||||
c.set_error_pos(s);
|
c.set_error_pos(s);
|
||||||
return static_cast<size_t>(-1);
|
return static_cast<size_t>(-1);
|
||||||
@ -1370,8 +1352,7 @@ class Character : public Ope
|
|||||||
public:
|
public:
|
||||||
Character(char ch) : ch_(ch) {}
|
Character(char ch) : ch_(ch) {}
|
||||||
|
|
||||||
size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
size_t parse_core(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
c.trace("Character", s, n, sv, dt);
|
|
||||||
if (n < 1 || s[0] != ch_) {
|
if (n < 1 || s[0] != ch_) {
|
||||||
c.set_error_pos(s);
|
c.set_error_pos(s);
|
||||||
return static_cast<size_t>(-1);
|
return static_cast<size_t>(-1);
|
||||||
@ -1388,8 +1369,7 @@ class AnyCharacter : public Ope
|
|||||||
, public std::enable_shared_from_this<AnyCharacter>
|
, public std::enable_shared_from_this<AnyCharacter>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
size_t parse_core(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
c.trace("AnyCharacter", s, n, sv, dt);
|
|
||||||
auto len = codepoint_length(s, n);
|
auto len = codepoint_length(s, n);
|
||||||
if (len < 1) {
|
if (len < 1) {
|
||||||
c.set_error_pos(s);
|
c.set_error_pos(s);
|
||||||
@ -1407,7 +1387,7 @@ public:
|
|||||||
CaptureScope(const std::shared_ptr<Ope>& ope)
|
CaptureScope(const std::shared_ptr<Ope>& ope)
|
||||||
: ope_(ope) {}
|
: ope_(ope) {}
|
||||||
|
|
||||||
size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
size_t parse_core(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
c.push_capture_scope();
|
c.push_capture_scope();
|
||||||
auto se = make_scope_exit([&]() {
|
auto se = make_scope_exit([&]() {
|
||||||
c.pop_capture_scope();
|
c.pop_capture_scope();
|
||||||
@ -1430,7 +1410,7 @@ public:
|
|||||||
Capture(const std::shared_ptr<Ope>& ope, MatchAction ma)
|
Capture(const std::shared_ptr<Ope>& ope, MatchAction ma)
|
||||||
: ope_(ope), match_action_(ma) {}
|
: ope_(ope), match_action_(ma) {}
|
||||||
|
|
||||||
size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
size_t parse_core(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
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 (success(len) && match_action_) {
|
if (success(len) && match_action_) {
|
||||||
@ -1450,7 +1430,7 @@ class TokenBoundary : public Ope
|
|||||||
public:
|
public:
|
||||||
TokenBoundary(const std::shared_ptr<Ope>& ope) : ope_(ope) {}
|
TokenBoundary(const std::shared_ptr<Ope>& ope) : ope_(ope) {}
|
||||||
|
|
||||||
size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override;
|
size_t parse_core(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override;
|
||||||
|
|
||||||
void accept(Visitor& v) override;
|
void accept(Visitor& v) override;
|
||||||
|
|
||||||
@ -1462,7 +1442,7 @@ class Ignore : public Ope
|
|||||||
public:
|
public:
|
||||||
Ignore(const std::shared_ptr<Ope>& ope) : ope_(ope) {}
|
Ignore(const std::shared_ptr<Ope>& ope) : ope_(ope) {}
|
||||||
|
|
||||||
size_t parse(const char* s, size_t n, SemanticValues& /*sv*/, Context& c, any& dt) const override {
|
size_t parse_core(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
const auto& rule = *ope_;
|
const auto& rule = *ope_;
|
||||||
auto& chldsv = c.push();
|
auto& chldsv = c.push();
|
||||||
auto se = make_scope_exit([&]() {
|
auto se = make_scope_exit([&]() {
|
||||||
@ -1482,8 +1462,7 @@ class User : public Ope
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
User(Parser fn) : fn_(fn) {}
|
User(Parser fn) : fn_(fn) {}
|
||||||
size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
size_t parse_core(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
c.trace("User", s, n, sv, dt);
|
|
||||||
assert(fn_);
|
assert(fn_);
|
||||||
return fn_(s, n, sv, dt);
|
return fn_(s, n, sv, dt);
|
||||||
}
|
}
|
||||||
@ -1496,7 +1475,7 @@ class WeakHolder : public Ope
|
|||||||
public:
|
public:
|
||||||
WeakHolder(const std::shared_ptr<Ope>& ope) : weak_(ope) {}
|
WeakHolder(const std::shared_ptr<Ope>& ope) : weak_(ope) {}
|
||||||
|
|
||||||
size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
size_t parse_core(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
auto ope = weak_.lock();
|
auto ope = weak_.lock();
|
||||||
assert(ope);
|
assert(ope);
|
||||||
const auto& rule = *ope;
|
const auto& rule = *ope;
|
||||||
@ -1514,14 +1493,17 @@ public:
|
|||||||
Holder(Definition* outer)
|
Holder(Definition* outer)
|
||||||
: outer_(outer) {}
|
: outer_(outer) {}
|
||||||
|
|
||||||
size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override;
|
size_t parse_core(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override;
|
||||||
|
|
||||||
void accept(Visitor& v) override;
|
void accept(Visitor& v) override;
|
||||||
|
|
||||||
any reduce(SemanticValues& sv, any& dt) const;
|
any reduce(SemanticValues& sv, any& dt) const;
|
||||||
|
|
||||||
|
const char* trace_name() const;
|
||||||
|
|
||||||
std::shared_ptr<Ope> ope_;
|
std::shared_ptr<Ope> ope_;
|
||||||
Definition* outer_;
|
Definition* outer_;
|
||||||
|
mutable std::string trace_name_;
|
||||||
|
|
||||||
friend class Definition;
|
friend class Definition;
|
||||||
};
|
};
|
||||||
@ -1547,7 +1529,7 @@ public:
|
|||||||
, iarg_(0)
|
, iarg_(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override;
|
size_t parse_core(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override;
|
||||||
|
|
||||||
void accept(Visitor& v) override;
|
void accept(Visitor& v) override;
|
||||||
|
|
||||||
@ -1569,7 +1551,7 @@ class Whitespace : public Ope
|
|||||||
public:
|
public:
|
||||||
Whitespace(const std::shared_ptr<Ope>& ope) : ope_(ope) {}
|
Whitespace(const std::shared_ptr<Ope>& ope) : ope_(ope) {}
|
||||||
|
|
||||||
size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
size_t parse_core(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
if (c.in_whitespace) {
|
if (c.in_whitespace) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1589,7 +1571,7 @@ class BackReference : public Ope
|
|||||||
public:
|
public:
|
||||||
BackReference(const std::string& name) : name_(name) {}
|
BackReference(const std::string& name) : name_(name) {}
|
||||||
|
|
||||||
size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override;
|
size_t parse_core(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override;
|
||||||
|
|
||||||
void accept(Visitor& v) override;
|
void accept(Visitor& v) override;
|
||||||
|
|
||||||
@ -1722,6 +1704,45 @@ struct Ope::Visitor
|
|||||||
virtual void visit(BackReference& /*ope*/) {}
|
virtual void visit(BackReference& /*ope*/) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct IsReference : public Ope::Visitor
|
||||||
|
{
|
||||||
|
void visit(Reference& ope) override {
|
||||||
|
is_reference = true;
|
||||||
|
}
|
||||||
|
bool is_reference = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TraceOpeName : public Ope::Visitor
|
||||||
|
{
|
||||||
|
void visit(Sequence& ope) override { name = "Sequence"; }
|
||||||
|
void visit(PrioritizedChoice& ope) override { name = "PrioritizedChoice"; }
|
||||||
|
void visit(ZeroOrMore& ope) override { name = "ZeroOrMore"; }
|
||||||
|
void visit(OneOrMore& ope) override { name = "OneOrMore"; }
|
||||||
|
void visit(Option& ope) override { name = "Option"; }
|
||||||
|
void visit(AndPredicate& ope) override { name = "AndPredicate"; }
|
||||||
|
void visit(NotPredicate& ope) override { name = "NotPredicate"; }
|
||||||
|
void visit(LiteralString& ope) override { name = "LiteralString"; }
|
||||||
|
void visit(CharacterClass& ope) override { name = "CharacterClass"; }
|
||||||
|
void visit(Character& ope) override { name = "Character"; }
|
||||||
|
void visit(AnyCharacter& ope) override { name = "AnyCharacter"; }
|
||||||
|
void visit(CaptureScope& ope) override { name = "CaptureScope"; }
|
||||||
|
void visit(Capture& ope) override { name = "Capture"; }
|
||||||
|
void visit(TokenBoundary& ope) override { name = "TokenBoundary"; }
|
||||||
|
void visit(Ignore& ope) override { name = "Ignore"; }
|
||||||
|
void visit(User& ope) override { name = "User"; }
|
||||||
|
void visit(WeakHolder& ope) override { name = "WeakHolder"; }
|
||||||
|
void visit(Holder& ope) override {
|
||||||
|
name = ope.trace_name();
|
||||||
|
}
|
||||||
|
void visit(Reference& ope) override {
|
||||||
|
name = "Reference";
|
||||||
|
}
|
||||||
|
void visit(Whitespace& ope) override { name = "Whitespace"; }
|
||||||
|
void visit(BackReference& ope) override { name = "BackReference"; }
|
||||||
|
|
||||||
|
const char* name = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
struct AssignIDToDefinition : public Ope::Visitor
|
struct AssignIDToDefinition : public Ope::Visitor
|
||||||
{
|
{
|
||||||
void visit(Sequence& ope) override {
|
void visit(Sequence& ope) override {
|
||||||
@ -2253,7 +2274,8 @@ public:
|
|||||||
bool enablePackratParsing = false;
|
bool enablePackratParsing = false;
|
||||||
bool is_macro = false;
|
bool is_macro = false;
|
||||||
std::vector<std::string> params;
|
std::vector<std::string> params;
|
||||||
Tracer tracer;
|
TracerEnter tracer_enter;
|
||||||
|
TracerLeave tracer_leave;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class Reference;
|
friend class Reference;
|
||||||
@ -2283,7 +2305,13 @@ private:
|
|||||||
ope = std::make_shared<Sequence>(whitespaceOpe, ope);
|
ope = std::make_shared<Sequence>(whitespaceOpe, ope);
|
||||||
}
|
}
|
||||||
|
|
||||||
Context cxt(path, s, n, definition_ids_.size(), whitespaceOpe, wordOpe, enablePackratParsing, tracer);
|
Context cxt(
|
||||||
|
path, s, n,
|
||||||
|
definition_ids_.size(),
|
||||||
|
whitespaceOpe, wordOpe,
|
||||||
|
enablePackratParsing,
|
||||||
|
tracer_enter, tracer_leave);
|
||||||
|
|
||||||
auto len = ope->parse(s, n, sv, cxt, dt);
|
auto len = ope->parse(s, n, sv, cxt, dt);
|
||||||
return Result{ success(len), len, cxt.error_pos, cxt.message_pos, cxt.message };
|
return Result{ success(len), len, cxt.error_pos, cxt.message_pos, cxt.message };
|
||||||
}
|
}
|
||||||
@ -2312,7 +2340,7 @@ inline size_t parse_literal(const char* s, size_t n, SemanticValues& sv, Context
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Word check
|
// Word check
|
||||||
static Context dummy_c(nullptr, c.s, c.l, 0, nullptr, nullptr, false, nullptr);
|
static Context dummy_c(nullptr, c.s, c.l, 0, nullptr, nullptr, false, nullptr, nullptr);
|
||||||
static SemanticValues dummy_sv;
|
static SemanticValues dummy_sv;
|
||||||
static any dummy_dt;
|
static any dummy_dt;
|
||||||
|
|
||||||
@ -2347,12 +2375,42 @@ inline size_t parse_literal(const char* s, size_t n, SemanticValues& sv, Context
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t LiteralString::parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const {
|
inline void Context::trace_enter(const char* name, const char* a_s, size_t n, SemanticValues& sv, any& dt) const {
|
||||||
c.trace("LiteralString", s, n, sv, dt);
|
trace_ids.push_back(next_trace_id++);
|
||||||
|
tracer_enter(name, a_s, n, sv, *this, dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Context::trace_leave(const char* name, const char* a_s, size_t n, SemanticValues& sv, any& dt, size_t len) const {
|
||||||
|
tracer_leave(name, a_s, n, sv, *this, dt, len);
|
||||||
|
trace_ids.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool Context::is_traceable(const Ope& ope) const {
|
||||||
|
if (tracer_enter && tracer_leave) {
|
||||||
|
IsReference vis;
|
||||||
|
const_cast<Ope&>(ope).accept(vis);
|
||||||
|
return !vis.is_reference;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t Ope::parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const {
|
||||||
|
if (c.is_traceable(*this)) {
|
||||||
|
TraceOpeName vis;
|
||||||
|
const_cast<Ope&>(*this).accept(vis);
|
||||||
|
c.trace_enter(vis.name, s, n, sv, dt);
|
||||||
|
auto len = parse_core(s, n, sv, c, dt);
|
||||||
|
c.trace_leave(vis.name, s, n, sv, dt, len);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
return parse_core(s, n, sv, c, dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t LiteralString::parse_core(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const {
|
||||||
return parse_literal(s, n, sv, c, dt, lit_, init_is_word_, is_word_, ignore_case_);
|
return parse_literal(s, n, sv, c, dt, lit_, init_is_word_, is_word_, ignore_case_);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t TokenBoundary::parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const {
|
inline size_t TokenBoundary::parse_core(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const {
|
||||||
c.in_token = true;
|
c.in_token = true;
|
||||||
auto se = make_scope_exit([&]() { c.in_token = false; });
|
auto se = make_scope_exit([&]() { c.in_token = false; });
|
||||||
const auto& rule = *ope_;
|
const auto& rule = *ope_;
|
||||||
@ -2371,17 +2429,11 @@ inline size_t TokenBoundary::parse(const char* s, size_t n, SemanticValues& sv,
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t Holder::parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const {
|
inline size_t Holder::parse_core(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const {
|
||||||
if (!ope_) {
|
if (!ope_) {
|
||||||
throw std::logic_error("Uninitialized definition ope was used...");
|
throw std::logic_error("Uninitialized definition ope was used...");
|
||||||
}
|
}
|
||||||
|
|
||||||
c.trace(outer_->name.c_str(), s, n, sv, dt);
|
|
||||||
c.nest_level++;
|
|
||||||
auto se = make_scope_exit([&]() {
|
|
||||||
c.nest_level--;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Macro reference
|
// Macro reference
|
||||||
// TODO: need packrat support
|
// TODO: need packrat support
|
||||||
if (outer_->is_macro) {
|
if (outer_->is_macro) {
|
||||||
@ -2460,7 +2512,14 @@ inline any Holder::reduce(SemanticValues& sv, any& dt) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t Reference::parse(
|
inline const char* Holder::trace_name() const {
|
||||||
|
if (trace_name_.empty()) {
|
||||||
|
trace_name_ = "[" + outer_->name + "]";
|
||||||
|
}
|
||||||
|
return trace_name_.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t Reference::parse_core(
|
||||||
const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const {
|
const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const {
|
||||||
if (rule_) {
|
if (rule_) {
|
||||||
// Reference rule
|
// Reference rule
|
||||||
@ -2495,8 +2554,7 @@ inline std::shared_ptr<Ope> Reference::get_core_operator() const {
|
|||||||
return rule_->holder_;
|
return rule_->holder_;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t BackReference::parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const {
|
inline size_t BackReference::parse_core(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const {
|
||||||
c.trace("BackReference", s, n, sv, dt);
|
|
||||||
for (int i = c.capture_scope_stack_size - 1; i >= 0; i--) {
|
for (int i = c.capture_scope_stack_size - 1; i >= 0; i--) {
|
||||||
const auto& cs = c.capture_scope_stack[i];
|
const auto& cs = c.capture_scope_stack[i];
|
||||||
if (cs.find(name_) != cs.end()) {
|
if (cs.find(name_) != cs.end()) {
|
||||||
@ -3523,10 +3581,11 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void enable_trace(Tracer tracer) {
|
void enable_trace(TracerEnter tracer_enter, TracerLeave tracer_leave) {
|
||||||
if (grammar_ != nullptr) {
|
if (grammar_ != nullptr) {
|
||||||
auto& rule = (*grammar_)[start_];
|
auto& rule = (*grammar_)[start_];
|
||||||
rule.tracer = tracer;
|
rule.tracer_enter = tracer_enter;
|
||||||
|
rule.tracer_leave = tracer_leave;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user