Added verbose trace flag in peglint

pull/207/head
yhirose 2 years ago
parent 3c745bf581
commit d53f4ecca3
  1. 9
      lint/peglint.cc
  2. 97
      peglib.h

@ -1,7 +1,7 @@
//
// peglint.cc
//
// Copyright (c) 2021 Yuji Hirose. All rights reserved.
// Copyright (c) 2022 Yuji Hirose. All rights reserved.
// MIT License
//
@ -41,6 +41,7 @@ int main(int argc, const char **argv) {
auto opt_source = false;
vector<char> source;
auto opt_trace = false;
auto opt_verbose = false;
vector<const char *> path_list;
auto argi = 1;
@ -66,6 +67,9 @@ int main(int argc, const char **argv) {
}
} else if (string("--trace") == arg) {
opt_trace = true;
} else if (string("--trace-verbose") == arg) {
opt_trace = true;
opt_verbose = true;
} else {
path_list.push_back(arg);
}
@ -81,6 +85,7 @@ int main(int argc, const char **argv) {
--opt, --opt-all: optimize all AST nodes except nodes selected with `no_ast_opt` instruction
--opt-only: optimize only AST nodes selected with `no_ast_opt` instruction
--trace: show trace messages
--trace-verbose: show verbose trace messages
)";
return 1;
@ -176,7 +181,7 @@ int main(int argc, const char **argv) {
}
std::cout << "L " << pos << "\t" << indent << ret << name << " #"
<< c.trace_ids.back() << choice.str() << token << matched << std::endl;
});
}, opt_verbose);
}
if (opt_ast) {

@ -837,18 +837,20 @@ public:
TracerEnter tracer_enter;
TracerLeave tracer_leave;
const bool tracer_verbose;
Log log;
Context(const char *path, const char *s, size_t l, size_t def_count,
std::shared_ptr<Ope> whitespaceOpe, std::shared_ptr<Ope> wordOpe,
bool enablePackratParsing, TracerEnter tracer_enter,
TracerLeave tracer_leave, Log log)
TracerLeave tracer_leave, bool tracer_verbose, Log log)
: path(path), s(s), l(l), whitespaceOpe(whitespaceOpe), wordOpe(wordOpe),
def_count(def_count), enablePackratParsing(enablePackratParsing),
cache_registered(enablePackratParsing ? def_count * (l + 1) : 0),
cache_success(enablePackratParsing ? def_count * (l + 1) : 0),
tracer_enter(tracer_enter), tracer_leave(tracer_leave), log(log) {
tracer_enter(tracer_enter), tracer_leave(tracer_leave),
tracer_verbose(tracer_verbose), log(log) {
args_stack.resize(1);
@ -953,16 +955,15 @@ public:
void set_error_pos(const char *a_s, const char *literal = nullptr);
// void trace_enter(const char *name, const char *a_s, size_t n,
void trace_enter(const Ope &ope, const char *a_s, size_t n,
SemanticValues &vs, std::any &dt) const;
// void trace_leave(const char *name, const char *a_s, size_t n,
void trace_leave(const Ope &ope, const char *a_s, size_t n,
SemanticValues &vs, std::any &dt, size_t len) const;
bool is_traceable(const Ope &ope) const;
mutable size_t next_trace_id = 0;
mutable std::vector<size_t> trace_ids;
bool ignore_trace_state = false;
};
/*
@ -1742,17 +1743,40 @@ struct Ope::Visitor {
virtual void visit(Cut &) {}
};
struct IsReference : public Ope::Visitor {
void visit(Reference &) override { is_reference_ = true; }
static bool check(Ope &ope) {
IsReference vis;
ope.accept(vis);
return vis.is_reference_;
template <typename T>
struct OpeType : public Ope::Visitor {
void visit(Sequence &) override { ret_ = std::is_same<Sequence, T>::value; }
void visit(PrioritizedChoice &) override { ret_ = std::is_same<PrioritizedChoice, T>::value; }
void visit(Repetition &) override { ret_ = std::is_same<Repetition, T>::value; }
void visit(AndPredicate &) override { ret_ = std::is_same<AndPredicate, T>::value; }
void visit(NotPredicate &) override { ret_ = std::is_same<NotPredicate, T>::value; }
void visit(Dictionary &) override { ret_ = std::is_same<Dictionary, T>::value; }
void visit(LiteralString &) override { ret_ = std::is_same<LiteralString, T>::value; }
void visit(CharacterClass &) override { ret_ = std::is_same<CharacterClass, T>::value; }
void visit(Character &) override { ret_ = std::is_same<Character, T>::value; }
void visit(AnyCharacter &) override { ret_ = std::is_same<AnyCharacter, T>::value; }
void visit(CaptureScope &) override { ret_ = std::is_same<CaptureScope, T>::value; }
void visit(Capture &) override { ret_ = std::is_same<Capture, T>::value; }
void visit(TokenBoundary &) override { ret_ = std::is_same<TokenBoundary, T>::value; }
void visit(Ignore &) override { ret_ = std::is_same<Ignore, T>::value; }
void visit(User &) override { ret_ = std::is_same<User, T>::value; }
void visit(WeakHolder &) override { ret_ = std::is_same<WeakHolder, T>::value; }
void visit(Holder &) override { ret_ = std::is_same<Holder, T>::value; }
void visit(Reference &) override { ret_ = std::is_same<Reference, T>::value; }
void visit(Whitespace &) override { ret_ = std::is_same<Whitespace, T>::value; }
void visit(BackReference &) override { ret_ = std::is_same<BackReference, T>::value; }
void visit(PrecedenceClimbing &) override { ret_ = std::is_same<PrecedenceClimbing, T>::value; }
void visit(Recovery &) override { ret_ = std::is_same<Recovery, T>::value; }
void visit(Cut &) override { ret_ = std::is_same<Cut, T>::value; }
static bool check(const Ope &ope) {
OpeType vis;
const_cast<Ope &>(ope).accept(vis);
return vis.ret_;
}
private:
bool is_reference_ = false;
bool ret_ = false;
};
struct TraceOpeName : public Ope::Visitor {
@ -2378,6 +2402,7 @@ public:
std::vector<std::string> params;
TracerEnter tracer_enter;
TracerLeave tracer_leave;
bool tracer_verbose = false;
bool disable_action = false;
std::string error_message;
@ -2405,13 +2430,28 @@ private:
initialize_definition_ids();
std::shared_ptr<Ope> ope = holder_;
if (whitespaceOpe) { ope = std::make_shared<Sequence>(whitespaceOpe, ope); }
Context cxt(path, s, n, definition_ids_.size(), whitespaceOpe, wordOpe,
enablePackratParsing, tracer_enter, tracer_leave, log);
Context c(path, s, n, definition_ids_.size(), whitespaceOpe, wordOpe,
enablePackratParsing, tracer_enter, tracer_leave, tracer_verbose,
log);
size_t i = 0;
if (whitespaceOpe) {
auto save_ignore_trace_state = c.ignore_trace_state;
c.ignore_trace_state = !c.tracer_verbose;
auto se = scope_exit([&]() { c.ignore_trace_state = save_ignore_trace_state; });
auto len = ope->parse(s, n, vs, cxt, dt);
return Result{success(len), cxt.recovered, len, cxt.error_info};
auto len = whitespaceOpe->parse(s, n, vs, c, dt);
if (fail(len)) {
return Result{success(len), c.recovered, len, c.error_info};
}
i = len;
}
auto len = ope->parse(s + i, n - i, vs, c, dt);
return Result{success(i + len), c.recovered, i + len, c.error_info};
}
std::shared_ptr<Holder> holder_;
@ -2441,10 +2481,14 @@ inline size_t parse_literal(const char *s, size_t n, SemanticValues &vs,
// Word check
if (c.wordOpe) {
auto save_ignore_trace_state = c.ignore_trace_state;
c.ignore_trace_state = !c.tracer_verbose;
auto se = scope_exit([&]() { c.ignore_trace_state = save_ignore_trace_state; });
std::call_once(init_is_word, [&]() {
SemanticValues dummy_vs;
Context dummy_c(nullptr, c.s, c.l, 0, nullptr, nullptr, false, nullptr,
nullptr, nullptr);
nullptr, false, nullptr);
std::any dummy_dt;
auto len =
@ -2455,7 +2499,7 @@ inline size_t parse_literal(const char *s, size_t n, SemanticValues &vs,
if (is_word) {
SemanticValues dummy_vs;
Context dummy_c(nullptr, c.s, c.l, 0, nullptr, nullptr, false, nullptr,
nullptr, nullptr);
nullptr, false, nullptr);
std::any dummy_dt;
NotPredicate ope(c.wordOpe);
@ -2468,6 +2512,10 @@ inline size_t parse_literal(const char *s, size_t n, SemanticValues &vs,
// Skip whiltespace
if (!c.in_token_boundary_count) {
if (c.whitespaceOpe) {
auto save_ignore_trace_state = c.ignore_trace_state;
c.ignore_trace_state = !c.tracer_verbose;
auto se = scope_exit([&]() { c.ignore_trace_state = save_ignore_trace_state; });
auto len = c.whitespaceOpe->parse(s + i, n - i, vs, c, dt);
if (fail(len)) { return len; }
i += len;
@ -2513,6 +2561,7 @@ inline void Context::set_error_pos(const char *a_s, const char *literal) {
inline void Context::trace_enter(const Ope &ope, const char *a_s, size_t n,
SemanticValues &vs, std::any &dt) const {
if (ignore_trace_state || peg::OpeType<peg::Ignore>::check(ope)) { return; }
trace_ids.push_back(next_trace_id++);
tracer_enter(ope, a_s, n, vs, *this, dt);
}
@ -2520,13 +2569,14 @@ inline void Context::trace_enter(const Ope &ope, const char *a_s, size_t n,
inline void Context::trace_leave(const Ope &ope, const char *a_s, size_t n,
SemanticValues &vs, std::any &dt,
size_t len) const {
if (ignore_trace_state || peg::OpeType<peg::Ignore>::check(ope)) { return; }
tracer_leave(ope, a_s, n, vs, *this, dt, len);
trace_ids.pop_back();
}
inline bool Context::is_traceable(const Ope &ope) const {
if (tracer_enter && tracer_leave) {
return !IsReference::check(const_cast<Ope &>(ope));
return !OpeType<Reference>::check(ope);
}
return false;
}
@ -2561,6 +2611,10 @@ inline size_t LiteralString::parse_core(const char *s, size_t n,
inline size_t TokenBoundary::parse_core(const char *s, size_t n,
SemanticValues &vs, Context &c,
std::any &dt) const {
auto save_ignore_trace_state = c.ignore_trace_state;
c.ignore_trace_state = !c.tracer_verbose;
auto se = scope_exit([&]() { c.ignore_trace_state = save_ignore_trace_state; });
size_t len;
{
c.in_token_boundary_count++;
@ -4296,11 +4350,12 @@ public:
}
}
void enable_trace(TracerEnter tracer_enter, TracerLeave tracer_leave) {
void enable_trace(TracerEnter tracer_enter, TracerLeave tracer_leave, bool tracer_verbose = false) {
if (grammar_ != nullptr) {
auto &rule = (*grammar_)[start_];
rule.tracer_enter = tracer_enter;
rule.tracer_leave = tracer_leave;
rule.tracer_verbose = tracer_verbose;
}
}

Loading…
Cancel
Save