diff --git a/docs/index.html b/docs/index.html
index 8dd89eb..f33c676 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -20,13 +20,21 @@
Valid
{{source}}
+
+
+
diff --git a/docs/index.js b/docs/index.js
index 0efddd8..e4eba47 100644
--- a/docs/index.js
+++ b/docs/index.js
@@ -1,34 +1,34 @@
// Setup editros
-const grammar = ace.edit("grammar-editor");
-grammar.setShowPrintMargin(false);
-grammar.setValue(localStorage.getItem('grammarText') || '');
-grammar.moveCursorTo(0, 0);
+function setupInfoArea(id) {
+ const e = ace.edit(id);
+ e.setShowPrintMargin(false);
+ e.setOptions({
+ readOnly: true,
+ highlightActiveLine: false,
+ highlightGutterLine: false
+ })
+ e.renderer.$cursorLayer.element.style.opacity=0;
+ return e;
+}
-const code = ace.edit("code-editor");
-code.setShowPrintMargin(false);
-code.setValue(localStorage.getItem('codeText') || '');
-code.moveCursorTo(0, 0);
+function setupEditorArea(id, lsKey) {
+ const e = ace.edit(id);
+ e.setShowPrintMargin(false);
+ e.setValue(localStorage.getItem(lsKey) || '');
+ e.moveCursorTo(0, 0);
+ return e;
+}
-const codeAst = ace.edit("code-ast");
-codeAst.setShowPrintMargin(false);
-codeAst.setOptions({
- readOnly: true,
- highlightActiveLine: false,
- highlightGutterLine: false
-})
-codeAst.renderer.$cursorLayer.element.style.opacity=0;
+const grammar = setupEditorArea("grammar-editor", "grammarText");
+const code = setupEditorArea("code-editor", "codeText");
-const codeAstOptimized = ace.edit("code-ast-optimized");
-codeAstOptimized.setShowPrintMargin(false);
-codeAstOptimized.setOptions({
- readOnly: true,
- highlightActiveLine: false,
- highlightGutterLine: false
-})
-codeAstOptimized.renderer.$cursorLayer.element.style.opacity=0;
+const codeAst = setupInfoArea("code-ast");
+const codeAstOptimized = setupInfoArea("code-ast-optimized");
+const profile = setupInfoArea("profile");
$('#opt_mode').val(localStorage.getItem('optimazationMode') || 'all');
+// Parse
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&")
@@ -71,6 +71,7 @@ function parse() {
$codeValidation.hide();
codeAst.setValue('');
codeAstOptimized.setValue('');
+ profile.setValue('');
if (grammarText.length === 0) {
return;
@@ -84,6 +85,7 @@ function parse() {
codeAst.insert(data.ast);
codeAstOptimized.insert(data.astOptimized);
+ profile.insert(data.profile);
if (data.source_valid) {
$codeValidation.removeClass('editor-validation-invalid').text('Valid').show();
diff --git a/docs/native.cpp b/docs/native.cpp
index 8f56a21..04d4f1b 100644
--- a/docs/native.cpp
+++ b/docs/native.cpp
@@ -59,14 +59,21 @@ std::string lint(const std::string &grammarText, const std::string &codeText, bo
std::string codeResult;
std::string astResult;
std::string astResultOptimized;
+ std::string profileResult;
peg::parser peg;
auto is_grammar_valid = parse_grammar(grammarText, peg, grammarResult);
auto is_source_valid = false;
if (is_grammar_valid && peg) {
+ std::stringstream ss;
+ peg::enable_profiling(peg, ss);
+
std::shared_ptr ast;
is_source_valid = parse_code(codeText, peg, codeResult, ast);
+
+ profileResult = escape_json(ss.str());
+
if (ast) {
astResult = escape_json(peg::ast_to_s(ast));
astResultOptimized = escape_json(
@@ -83,6 +90,7 @@ std::string lint(const std::string &grammarText, const std::string &codeText, bo
json += ",\"code\":" + codeResult;
json += ",\"ast\":\"" + astResult + "\"";
json += ",\"astOptimized\":\"" + astResultOptimized + "\"";
+ json += ",\"profile\":\"" + profileResult + "\"";
}
json += "}";
diff --git a/docs/native.wasm b/docs/native.wasm
index 03951e2..b85a586 100755
Binary files a/docs/native.wasm and b/docs/native.wasm differ
diff --git a/lint/peglint.cc b/lint/peglint.cc
index 724458a..c78b9b2 100644
--- a/lint/peglint.cc
+++ b/lint/peglint.cc
@@ -130,11 +130,11 @@ int main(int argc, const char **argv) {
if (opt_packrat) { parser.enable_packrat_parsing(); }
if (opt_trace) {
- enable_tracing(parser);
+ enable_tracing(parser, std::cout);
}
if (opt_profile) {
- enable_profiling(parser);
+ enable_profiling(parser, std::cout);
}
parser.set_verbose_trace(opt_verbose);
diff --git a/peglib.h b/peglib.h
index d7895b0..facd906 100644
--- a/peglib.h
+++ b/peglib.h
@@ -4393,7 +4393,8 @@ public:
}
void enable_trace(TracerEnter tracer_enter, TracerLeave tracer_leave,
- TracerStartOrEnd tracer_start, TracerStartOrEnd tracer_end) {
+ TracerStartOrEnd tracer_start,
+ TracerStartOrEnd tracer_end) {
if (grammar_ != nullptr) {
auto &rule = (*grammar_)[start_];
rule.tracer_enter = tracer_enter;
@@ -4450,7 +4451,7 @@ private:
* enable_tracing
*---------------------------------------------------------------------------*/
-inline void enable_tracing(parser &parser) {
+inline void enable_tracing(parser &parser, std::ostream &os) {
size_t prev_pos = 0;
parser.enable_trace(
[&](auto &ope, auto s, auto, auto &, auto &c, auto &, auto &) {
@@ -4468,8 +4469,8 @@ inline void enable_tracing(parser &parser) {
auto lit = dynamic_cast(&ope);
if (lit) { name += " '" + peg::escape_characters(lit->lit_) + "'"; }
}
- std::cout << "E " << pos << backtrack << "\t" << indent << "┌" << name
- << " #" << c.trace_ids.back() << std::endl;
+ os << "E " << pos << backtrack << "\t" << indent << "┌" << name << " #"
+ << c.trace_ids.back() << std::endl;
prev_pos = static_cast(pos);
},
[&](auto &ope, auto s, auto, auto &sv, auto &c, auto &, auto len,
@@ -4498,9 +4499,9 @@ inline void enable_tracing(parser &parser) {
peg::TokenChecker::is_token(const_cast(ope))) {
matched = ", match '" + peg::escape_characters(s, len) + "'";
}
- std::cout << "L " << pos << "\t" << indent << ret << name << " #"
- << c.trace_ids.back() << choice.str() << token << matched
- << std::endl;
+ os << "L " << pos << "\t" << indent << ret << name << " #"
+ << c.trace_ids.back() << choice.str() << token << matched
+ << std::endl;
},
[&](auto &) {}, [&](auto &) {});
}
@@ -4509,7 +4510,7 @@ inline void enable_tracing(parser &parser) {
* enable_profiling
*---------------------------------------------------------------------------*/
-inline void enable_profiling(parser &parser) {
+inline void enable_profiling(parser &parser, std::ostream &os) {
struct Stats {
struct Item {
std::string name;
@@ -4522,8 +4523,7 @@ inline void enable_profiling(parser &parser) {
};
parser.enable_trace(
- [&](auto &ope, auto, auto, auto &, auto &, auto &,
- std::any &trace_data) {
+ [&](auto &ope, auto, auto, auto &, auto &, auto &, std::any &trace_data) {
if (auto holder = dynamic_cast(&ope)) {
auto &stats = *std::any_cast(trace_data);
@@ -4550,9 +4550,9 @@ inline void enable_profiling(parser &parser) {
}
if (index == 0) {
size_t id = 0;
- std::cout << " id total % success fail "
- "definition"
- << std::endl;
+ os << " id total % success fail "
+ "definition"
+ << std::endl;
size_t total_total, total_success = 0, total_fail = 0;
char buff[BUFSIZ];
for (auto &[name, success, fail] : stats.items) {
@@ -4562,18 +4562,18 @@ inline void enable_profiling(parser &parser) {
auto ratio = total * 100.0 / stats.total;
sprintf(buff, "%4zu %10lu %5.2f %10lu %10lu %s", id, total,
ratio, success, fail, name.c_str());
- std::cout << buff << std::endl;
+ os << buff << std::endl;
id++;
}
- std::cout << std::endl;
+ os << std::endl;
total_total = total_success + total_fail;
sprintf(buff, "%4s %10lu %5s %10lu %10lu %s", "", total_total,
"", total_success, total_fail, "Total counters");
- std::cout << buff << std::endl;
+ os << buff << std::endl;
sprintf(buff, "%4s %10s %5s %10.2f %10.2f %s", "", "", "",
total_success * 100.0 / total_total,
total_fail * 100.0 / total_total, "% success/fail");
- std::cout << buff << std::endl;
+ os << buff << std::endl;
}
}
},