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}}
    +
    + +
    +
    AST
    
         
    Optimized AST     mode: 
    
    -    
    +
    Profile
    +
    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; } } },