#include "httplib.h" #include "peglib.h" #include #include using namespace httplib; using namespace std; string indexHTML = R"( PEG Playground
  • Grammar:
  • Valid
{{syntax}}
  • Code:
  • Valid
{{source}}

        

        
)"; function makeJSONFormatter(string& json) { auto init = make_shared(true); return [&json, init](size_t ln, size_t col, const string& msg) mutable { if (!init) { json += ","; } json += "{"; json += R"("ln":)" + to_string(ln) + ","; json += R"("col":)" + to_string(col) + ","; json += R"("msg":")" + msg + R"(")"; json += "}"; *init = false; }; } bool parse_grammar(const string& text, peg::parser& peg, string& json) { peg.log = makeJSONFormatter(json); json += "["; auto ret = peg.load_grammar(text.data(), text.size()); json += "]"; return ret; } bool parse_code(const string& text, peg::parser& peg, string& json, shared_ptr& ast) { peg.enable_ast(); peg.log = makeJSONFormatter(json); json += "["; auto ret = peg.parse_n(text.data(), text.size(), ast); json += "]"; return ret; } std::string replace_text(std::string &s, const std::string &toReplace, const std::string &replaceWith) { return(s.replace(s.find(toReplace), toReplace.length(), replaceWith)); } int run_server(int port, const vector& syntax, const vector& source) { Server svr; svr.get("/", [&](const Request& req, Response& res) { replace_text(indexHTML, "{{syntax}}", string(syntax.data(), syntax.size())); replace_text(indexHTML, "{{source}}", string(source.data(), source.size())); res.set_content(indexHTML, "text/html"); }); svr.post("/parse", [](const Request& req, Response& res) { const auto& grammarText = req.params.at("grammar"); string grammarResult; string codeResult; string astResult; string astResultOptimized; peg::parser peg; auto ret = parse_grammar(grammarText, peg, grammarResult); if (ret && peg) { const auto& codeText = req.params.at("code"); shared_ptr ast; if (parse_code(codeText, peg, codeResult, ast)) { astResult = peg::ast_to_s(ast); astResultOptimized = peg::ast_to_s(peg::AstOptimizer(true).optimize(ast)); } } string json; json += "{"; json += "\"grammar\":" + grammarResult; if (!codeResult.empty()) { json += ",\"code\":" + codeResult; json += ",\"ast\":\"" + astResult + "\""; json += ",\"astOptimized\":\"" + astResultOptimized + "\""; } json += "}"; res.set_content(json, "application/json"); }); svr.set_error_handler([](const Request& req, Response& res) { const char* fmt = "

Error Status: %d

"; char buf[BUFSIZ]; snprintf(buf, sizeof(buf), fmt, res.status); res.set_content(buf, "text/html"); }); cerr << "Server running at http://localhost:" << port << "/" << endl; svr.listen("localhost", port); return 0; } // vim: et ts=4 sw=4 cin cino={1s ff=unix