diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 74704bb..0443aba 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -17,3 +17,6 @@ target_link_libraries(calc4 ${add_link_deps}) add_executable(calc5 calc5.cc) target_link_libraries(calc5 ${add_link_deps}) + +add_executable(indent indent.cc) +target_link_libraries(indent ${add_link_deps}) diff --git a/example/indent.cc b/example/indent.cc new file mode 100644 index 0000000..aec502f --- /dev/null +++ b/example/indent.cc @@ -0,0 +1,67 @@ +// +// indent.cc +// +// Copyright (c) 2022 Yuji Hirose. All rights reserved. +// MIT License +// + +// Based on https://gist.github.com/dmajda/04002578dd41ae8190fc + +#include +#include +#include + +using namespace peg; + +int main(void) { + parser parser(R"(Start <- Statements {} +Statements <- Statement* +Statement <- Samedent (S / I) + +S <- 'S' EOS { no_ast_opt } +I <- 'I' EOL Block / 'I' EOS { no_ast_opt } + +Block <- Statements {} + +~Samedent <- ' '* {} + +~EOS <- EOL / EOF +~EOL <- '\n' +~EOF <- !. + )"); + + size_t indent = 0; + + parser["Block"].enter = [&](const char * /*s*/, size_t /*n*/, + std::any & /*dt*/) { indent += 2; }; + + parser["Block"].leave = [&](const char * /*s*/, size_t /*n*/, + size_t /*matchlen*/, std::any & /*value*/, + std::any & /*dt*/) { indent -= 2; }; + + parser["Samedent"] = [&](const SemanticValues &vs, std::any & /*dt*/) { + if (indent != vs.sv().size()) { throw parse_error("different indent..."); } + }; + + parser.enable_ast(); + + const auto source = R"(I + S + I + I + S + S + S + S +)"; + + std::shared_ptr ast; + if (parser.parse(source, ast)) { + ast = parser.optimize_ast(ast); + std::cout << ast_to_s(ast); + return 0; + } + + std::cout << "syntax error..." << std::endl; + return -1; +}