diff --git a/lint/peglint.cc b/lint/peglint.cc index 63d16cd..994be01 100644 --- a/lint/peglint.cc +++ b/lint/peglint.cc @@ -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 source; auto opt_trace = false; + auto opt_verbose = false; vector 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) { diff --git a/peglib.h b/peglib.h index d93f26e..f51f8b2 100644 --- a/peglib.h +++ b/peglib.h @@ -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 whitespaceOpe, std::shared_ptr 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 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 +struct OpeType : public Ope::Visitor { + void visit(Sequence &) override { ret_ = std::is_same::value; } + void visit(PrioritizedChoice &) override { ret_ = std::is_same::value; } + void visit(Repetition &) override { ret_ = std::is_same::value; } + void visit(AndPredicate &) override { ret_ = std::is_same::value; } + void visit(NotPredicate &) override { ret_ = std::is_same::value; } + void visit(Dictionary &) override { ret_ = std::is_same::value; } + void visit(LiteralString &) override { ret_ = std::is_same::value; } + void visit(CharacterClass &) override { ret_ = std::is_same::value; } + void visit(Character &) override { ret_ = std::is_same::value; } + void visit(AnyCharacter &) override { ret_ = std::is_same::value; } + void visit(CaptureScope &) override { ret_ = std::is_same::value; } + void visit(Capture &) override { ret_ = std::is_same::value; } + void visit(TokenBoundary &) override { ret_ = std::is_same::value; } + void visit(Ignore &) override { ret_ = std::is_same::value; } + void visit(User &) override { ret_ = std::is_same::value; } + void visit(WeakHolder &) override { ret_ = std::is_same::value; } + void visit(Holder &) override { ret_ = std::is_same::value; } + void visit(Reference &) override { ret_ = std::is_same::value; } + void visit(Whitespace &) override { ret_ = std::is_same::value; } + void visit(BackReference &) override { ret_ = std::is_same::value; } + void visit(PrecedenceClimbing &) override { ret_ = std::is_same::value; } + void visit(Recovery &) override { ret_ = std::is_same::value; } + void visit(Cut &) override { ret_ = std::is_same::value; } + + static bool check(const Ope &ope) { + OpeType vis; + const_cast(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 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 = holder_; - if (whitespaceOpe) { ope = std::make_shared(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_; @@ -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::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::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)); + return !OpeType::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; } }