mirror of
https://github.com/yhirose/cpp-peglib.git
synced 2024-12-22 11:55:30 +00:00
Added profile feature (Resolve #200)
This commit is contained in:
parent
26877dc456
commit
34a859a6a1
@ -609,6 +609,7 @@ usage: grammar_file_path [source_file_path]
|
||||
--opt-only: optimize only AST nodes selected with `no_ast_opt` instruction
|
||||
--trace: show concise trace messages
|
||||
--trace-verbose: show verbose trace messages
|
||||
--profile: show profile report
|
||||
```
|
||||
|
||||
### Grammar check
|
||||
|
@ -14,6 +14,7 @@ usage: grammar_file_path [source_file_path]
|
||||
--source: source text
|
||||
--trace: show concise trace messages
|
||||
--trace-verbose: show verbose trace messages
|
||||
--profile: show profile report
|
||||
```
|
||||
|
||||
### Build peglint
|
||||
|
@ -41,7 +41,8 @@ int main(int argc, const char **argv) {
|
||||
auto opt_source = false;
|
||||
vector<char> source;
|
||||
auto opt_trace = false;
|
||||
auto opt_verbose = false;
|
||||
auto opt_trace_verbose = false;
|
||||
auto opt_profile = false;
|
||||
vector<const char *> path_list;
|
||||
|
||||
auto argi = 1;
|
||||
@ -68,8 +69,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;
|
||||
opt_trace_verbose = true;
|
||||
} else if (string("--profile") == arg) {
|
||||
opt_profile = true;
|
||||
} else {
|
||||
path_list.push_back(arg);
|
||||
}
|
||||
@ -86,6 +88,7 @@ int main(int argc, const char **argv) {
|
||||
--opt-only: optimize only AST nodes selected with `no_ast_opt` instruction
|
||||
--trace: show concise trace messages
|
||||
--trace-verbose: show verbose trace messages
|
||||
--profile: show profile report
|
||||
)";
|
||||
|
||||
return 1;
|
||||
@ -126,12 +129,10 @@ int main(int argc, const char **argv) {
|
||||
|
||||
if (opt_packrat) { parser.enable_packrat_parsing(); }
|
||||
|
||||
if (opt_trace) {
|
||||
if (opt_trace || opt_trace_verbose) {
|
||||
size_t prev_pos = 0;
|
||||
parser.enable_trace(
|
||||
[&](const peg::Ope &ope, const char *s, size_t /*n*/,
|
||||
const peg::SemanticValues & /*sv*/, const peg::Context &c,
|
||||
const std::any & /*dt*/) {
|
||||
[&](auto &ope, auto s, auto, auto &, auto &c, auto &) {
|
||||
auto pos = static_cast<size_t>(s - c.s);
|
||||
auto backtrack = (pos < prev_pos ? "*" : "");
|
||||
string indent;
|
||||
@ -150,9 +151,7 @@ int main(int argc, const char **argv) {
|
||||
<< " #" << c.trace_ids.back() << std::endl;
|
||||
prev_pos = static_cast<size_t>(pos);
|
||||
},
|
||||
[&](const peg::Ope &ope, const char *s, size_t /*n*/,
|
||||
const peg::SemanticValues &sv, const peg::Context &c,
|
||||
const std::any & /*dt*/, size_t len) {
|
||||
[&](auto &ope, auto s, auto, auto &sv, auto &c, auto &, auto len) {
|
||||
auto pos = static_cast<size_t>(s - c.s);
|
||||
if (len != static_cast<size_t>(-1)) { pos += len; }
|
||||
string indent;
|
||||
@ -181,7 +180,58 @@ int main(int argc, const char **argv) {
|
||||
<< c.trace_ids.back() << choice.str() << token << matched
|
||||
<< std::endl;
|
||||
},
|
||||
opt_verbose);
|
||||
opt_trace_verbose);
|
||||
}
|
||||
|
||||
struct StatsItem {
|
||||
std::string name;
|
||||
size_t success;
|
||||
size_t fail;
|
||||
};
|
||||
std::vector<StatsItem> stats;
|
||||
std::map<std::string, size_t> stats_index;
|
||||
size_t stats_item_total = false;
|
||||
|
||||
if (opt_profile) {
|
||||
parser.enable_trace(
|
||||
[&](auto &ope, auto, auto, auto &, auto &, auto &) {
|
||||
if (peg::IsOpeType<peg::Holder>::check(ope)) {
|
||||
auto &name = dynamic_cast<const peg::Holder &>(ope).name();
|
||||
if (stats_index.find(name) == stats_index.end()) {
|
||||
stats_index[name] = stats_index.size();
|
||||
stats.push_back({name, 0, 0});
|
||||
}
|
||||
stats_item_total++;
|
||||
}
|
||||
},
|
||||
[&](auto &ope, auto, auto, auto &, auto &, auto &, auto len) {
|
||||
if (peg::IsOpeType<peg::Holder>::check(ope)) {
|
||||
auto &name = dynamic_cast<const peg::Holder &>(ope).name();
|
||||
auto index = stats_index[name];
|
||||
auto &stat = stats[index];
|
||||
if (len != static_cast<size_t>(-1)) {
|
||||
stat.success++;
|
||||
} else {
|
||||
stat.fail++;
|
||||
}
|
||||
if (index == 0) {
|
||||
size_t id = 0;
|
||||
std::cout << " id total % success fail "
|
||||
"definition"
|
||||
<< std::endl;
|
||||
for (auto &[name, success, fail] : stats) {
|
||||
char buff[BUFSIZ];
|
||||
auto total = success + fail;
|
||||
auto ratio = total * 100.0 / stats_item_total;
|
||||
sprintf(buff, "%4zu %10lu %5.2f %10lu %10lu %s", id, total,
|
||||
ratio, success, fail, name.c_str());
|
||||
std::cout << buff << std::endl;
|
||||
id++;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
if (opt_ast) {
|
||||
|
19
peglib.h
19
peglib.h
@ -1467,7 +1467,8 @@ public:
|
||||
|
||||
std::any reduce(SemanticValues &vs, std::any &dt) const;
|
||||
|
||||
const char *trace_name() const;
|
||||
const std::string &name() const;
|
||||
const std::string &trace_name() const;
|
||||
|
||||
std::shared_ptr<Ope> ope_;
|
||||
Definition *outer_;
|
||||
@ -1825,7 +1826,7 @@ struct TraceOpeName : public Ope::Visitor {
|
||||
void visit(Ignore &) override { name_ = "Ignore"; }
|
||||
void visit(User &) override { name_ = "User"; }
|
||||
void visit(WeakHolder &) override { name_ = "WeakHolder"; }
|
||||
void visit(Holder &ope) override { name_ = ope.trace_name(); }
|
||||
void visit(Holder &ope) override { name_ = ope.trace_name().data(); }
|
||||
void visit(Reference &) override { name_ = "Reference"; }
|
||||
void visit(Whitespace &) override { name_ = "Whitespace"; }
|
||||
void visit(BackReference &) override { name_ = "BackReference"; }
|
||||
@ -1929,7 +1930,7 @@ private:
|
||||
};
|
||||
|
||||
struct FindLiteralToken : public Ope::Visitor {
|
||||
void visit(LiteralString &ope) override { token_ = ope.lit_.c_str(); }
|
||||
void visit(LiteralString &ope) override { token_ = ope.lit_.data(); }
|
||||
void visit(TokenBoundary &ope) override { ope.ope_->accept(*this); }
|
||||
void visit(Ignore &ope) override { ope.ope_->accept(*this); }
|
||||
void visit(Reference &ope) override;
|
||||
@ -2491,7 +2492,7 @@ inline size_t parse_literal(const char *s, size_t n, SemanticValues &vs,
|
||||
for (; i < lit.size(); i++) {
|
||||
if (i >= n || (ignore_case ? (std::tolower(s[i]) != std::tolower(lit[i]))
|
||||
: (s[i] != lit[i]))) {
|
||||
c.set_error_pos(s, lit.c_str());
|
||||
c.set_error_pos(s, lit.data());
|
||||
return static_cast<size_t>(-1);
|
||||
}
|
||||
}
|
||||
@ -2574,7 +2575,7 @@ inline void Context::set_error_pos(const char *a_s, const char *literal) {
|
||||
token && token[0] != '\0') {
|
||||
error_info.add(token, true);
|
||||
} else {
|
||||
error_info.add(rule->name.c_str(), false);
|
||||
error_info.add(rule->name.data(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2735,9 +2736,13 @@ inline std::any Holder::reduce(SemanticValues &vs, std::any &dt) const {
|
||||
}
|
||||
}
|
||||
|
||||
inline const char *Holder::trace_name() const {
|
||||
inline const std::string &Holder::name() const {
|
||||
return outer_->name;
|
||||
}
|
||||
|
||||
inline const std::string &Holder::trace_name() const {
|
||||
if (trace_name_.empty()) { trace_name_ = "[" + outer_->name + "]"; }
|
||||
return trace_name_.data();
|
||||
return trace_name_;
|
||||
}
|
||||
|
||||
inline size_t Reference::parse_core(const char *s, size_t n, SemanticValues &vs,
|
||||
|
Loading…
Reference in New Issue
Block a user