From b26e2477ffe34deb37b92e9fc609a3a16cd55ec1 Mon Sep 17 00:00:00 2001 From: yhirose Date: Thu, 1 Oct 2020 21:26:04 -0400 Subject: [PATCH] C++17 support --- .github/workflows/cmake.yml | 49 ++ .travis.yml | 33 +- CMakeLists.txt | 34 +- README.md | 277 ++++--- appveyor.yml | 3 - docs/build.sh | 2 +- docs/native.js | 2 +- docs/native.wasm | Bin 353795 -> 349328 bytes example/CMakeLists.txt | 8 +- example/calc.cc | 70 +- example/calc2.cc | 74 +- example/calc3.cc | 75 +- example/calc4.cc | 42 +- example/calc5.cc | 75 +- lint/CMakeLists.txt | 12 +- lint/peglint.cc | 9 +- peglib.h | 1356 +++++++++++++++-------------------- pl0/CMakeLists.txt | 11 +- pl0/pl0.cc | 56 +- test/CMakeLists.txt | 13 +- test/test1.cc | 1095 +++++++++++++--------------- test/test2.cc | 941 ++++++++++++------------ 22 files changed, 1942 insertions(+), 2295 deletions(-) create mode 100644 .github/workflows/cmake.yml diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml new file mode 100644 index 0000000..2b11e35 --- /dev/null +++ b/.github/workflows/cmake.yml @@ -0,0 +1,49 @@ +name: CMake + +on: [push, pull_request] + +env: + # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) + BUILD_TYPE: Release + +jobs: + build: + # The CMake configure and build commands are platform agnostic and should work equally + # well on Windows or Mac. You can convert this to a matrix build if you need + # cross-platform coverage. + # See: https://docs.github.com/en/actions/configuring-and-managing-workflows/configuring-a-workflow#configuring-a-build-matrix + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-20.04, macos-latest, windows-latest] + + steps: + - uses: actions/checkout@v2 + + - name: Create Build Environment + # Some projects don't allow in-source building, so create a separate build directory + # We'll use this as our working directory for all subsequent commands + run: cmake -E make_directory ${{runner.workspace}}/build + + - name: Configure CMake + # Use a bash shell so we can use the same syntax for environment variable + # access regardless of the host operating system + shell: bash + working-directory: ${{runner.workspace}}/build + # Note the current convention is to use the -S and -B options here to specify source + # and build directories, but this is only available with CMake 3.13 and higher. + # The CMake binaries on the Github Actions machines are (as of this writing) 3.12 + run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE + + - name: Build + working-directory: ${{runner.workspace}}/build + shell: bash + # Execute the build. You can specify a specific target with "--target " + run: cmake --build . --config $BUILD_TYPE + + - name: Test + working-directory: ${{runner.workspace}}/build + shell: bash + # Execute tests defined by the CMake configuration. + # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail + run: ctest -C $BUILD_TYPE diff --git a/.travis.yml b/.travis.yml index 0b5fbad..2529dc6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,39 +1,20 @@ language: cpp -sudo: false matrix: include: - - compiler: gcc + - os: linux addons: apt: sources: - ubuntu-toolchain-r-test - - george-edison55-precise-backports packages: - - cmake - - cmake-data - - gcc-4.9 - - g++-4.9 - env: COMPILER=g++-4.9 -# - compiler: clang -# addons: -# apt: -# sources: -# - kubuntu-backports -# - ubuntu-toolchain-r-test -# - llvm-toolchain-precise-3.7 -# packages: -# - cmake -# - clang-3.7 -# env: COMPILER=clang++-3.7 + - g++-8 + env: + - MATRIX_EVAL="CC=gcc-8 && CXX=g++-8" -branches: - only: - - master - -before_script: - - export CXX=$COMPILER +before_install: + - eval "${MATRIX_EVAL}" script: - mkdir build && cd build - - cmake .. && make && ctest -V + - cmake .. && make && ./test/test-main diff --git a/CMakeLists.txt b/CMakeLists.txt index c83c5e0..3d5f99a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,33 +1,11 @@ cmake_minimum_required(VERSION 3.1.0) project("cpp-peglib") -# Check if a supported compiler is used to setup the C++ standard to use: -get_property(known_features GLOBAL PROPERTY CMAKE_CXX_KNOWN_FEATURES) -list(FIND known_features "cxx_std_17" found) -if(NOT ${found} EQUAL -1) - # C++17 standard is supported - set(CMAKE_CXX_STANDARD 17) -else() - # Check for C++11 standard support - list(FIND known_features "cxx_std_11" found) - if(NOT ${found} EQUAL -1) - # C++11 standard is supported - set(CMAKE_CXX_STANDARD 11) - endif() -endif() - -if(${found} EQUAL -1) - message(FATAL_ERROR "Your compiler is not supported.") -endif() - +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_EXTENSIONS OFF) -if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Weverything -Wno-c++98-compat -Wno-padded -Wno-weak-vtables -Wno-exit-time-destructors -Wno-c++2a-compat -Wno-switch-enum -Wno-c++98-compat-pedantic") -elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wpedantic -Wextra -Woverloaded-virtual") -elseif(MSVC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /wd4503 /wd4512 /utf-8") +if(MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zc:__cplusplus /utf-8") endif() set(THREADS_PREFER_PTHREAD_FLAG ON) @@ -37,10 +15,10 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux") set(add_link_deps Threads::Threads) endif() -enable_testing() - -add_subdirectory(test) add_subdirectory(example) add_subdirectory(lint) +add_subdirectory(test) +enable_testing() + install(FILES peglib.h DESTINATION include) diff --git a/README.md b/README.md index d16a325..9b9b9e1 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,13 @@ cpp-peglib ========== +[![](https://github.com/yhirose/cpp-peglib/workflows/CMake/badge.svg)](https://github.com/yhirose/cpp-peglib/actions) [![Build Status](https://travis-ci.org/yhirose/cpp-peglib.svg?branch=master)](https://travis-ci.org/yhirose/cpp-peglib) [![Bulid Status](https://ci.appveyor.com/api/projects/status/github/yhirose/cpp-peglib?branch=master&svg=true)](https://ci.appveyor.com/project/yhirose/cpp-peglib) -C++11 header-only [PEG](http://en.wikipedia.org/wiki/Parsing_expression_grammar) (Parsing Expression Grammars) library. You can start using it right away just by including `peglib.h` in your project. +C++17 header-only [PEG](http://en.wikipedia.org/wiki/Parsing_expression_grammar) (Parsing Expression Grammars) library. You can start using it right away just by including `peglib.h` in your project. + +Since this library only supports C++17 compilers, please make sure that compiler the option `-std=c++17` is enabled. (`/std:c++17 /Zc:__cplusplus` for MSVC) You can also try the online version, PEG Playground at https://yhirose.github.io/cpp-peglib. @@ -44,8 +47,8 @@ using namespace peg; using namespace std; int main(void) { - // (2) Make a parser - parser parser(R"( + // (2) Make a parser + parser parser(R"( # Grammar for Calculator... Additive <- Multitive '+' Additive / Multitive Multitive <- Primary '*' Multitive / Primary @@ -54,38 +57,38 @@ int main(void) { %whitespace <- [ \t]* )"); - assert((bool)parser == true); + assert(static_cast(parser) == true); - // (3) Setup actions - parser["Additive"] = [](const SemanticValues& sv) { - switch (sv.choice()) { - case 0: // "Multitive '+' Additive" - return any_cast(sv[0]) + any_cast(sv[1]); - default: // "Multitive" - return any_cast(sv[0]); - } - }; - - parser["Multitive"] = [](const SemanticValues& sv) { - switch (sv.choice()) { - case 0: // "Primary '*' Multitive" - return any_cast(sv[0]) * any_cast(sv[1]); - default: // "Primary" - return any_cast(sv[0]); - } - }; + // (3) Setup actions + parser["Additive"] = [](const SemanticValues &vs) { + switch (vs.choice()) { + case 0: // "Multitive '+' Additive" + return any_cast(vs[0]) + any_cast(vs[1]); + default: // "Multitive" + return any_cast(vs[0]); + } + }; + + parser["Multitive"] = [](const SemanticValues &vs) { + switch (vs.choice()) { + case 0: // "Primary '*' Multitive" + return any_cast(vs[0]) * any_cast(vs[1]); + default: // "Primary" + return any_cast(vs[0]); + } + }; - parser["Number"] = [](const SemanticValues& sv) { - return stoi(sv.token(), nullptr, 10); - }; + parser["Number"] = [](const SemanticValues &vs) { + return vs.token_to_number(); + }; - // (4) Parse - parser.enable_packrat_parsing(); // Enable packrat parsing. + // (4) Parse + parser.enable_packrat_parsing(); // Enable packrat parsing. - int val; - parser.parse(" (1 + 2) * 3 ", val); + int val; + parser.parse(" (1 + 2) * 3 ", val); - assert(val == 9); + assert(val == 9); } ``` @@ -104,7 +107,7 @@ auto grammar = R"( parser parser; parser.log = [](size_t line, size_t col, const string& msg) { - cerr << line << ":" << col << ": " << msg << "\n"; + cerr << line << ":" << col << ": " << msg << "\n"; }; auto ok = parser.load_grammar(grammar); @@ -114,10 +117,10 @@ assert(ok); There are four semantic actions available: ```cpp -[](const SemanticValues& sv, any& dt) -[](const SemanticValues& sv) -[](SemanticValues& sv, any& dt) -[](SemanticValues& sv) +[](const SemanticValues& vs, any& dt) +[](const SemanticValues& vs) +[](SemanticValues& vs, any& dt) +[](SemanticValues& vs) ``` `SemanticValues` value contains the following information: @@ -129,48 +132,36 @@ There are four semantic actions available: `any& dt` is a 'read-write' context data which can be used for whatever purposes. The initial context data is set in `peg::parser::parse` method. -`peg::any` is a simpler implementatin of std::any. If the compiler in use supports C++17, by default `peg::any` is defined as an alias to `std::any`. - -To force using the simpler `any` implementation that comes with `cpp-peglib`, define `PEGLIB_USE_STD_ANY` as 0 before including `peglib.h`: -```cpp -#define PEGLIB_USE_STD_ANY 0 -#include -[...] -``` - -A semantic action can return a value of arbitrary data type, which will be wrapped by `peg::any`. If a user returns nothing in a semantic action, the first semantic value in the `const SemanticValues& sv` argument will be returned. (Yacc parser has the same behavior.) +A semantic action can return a value of arbitrary data type, which will be wrapped by `peg::any`. If a user returns nothing in a semantic action, the first semantic value in the `const SemanticValues& vs` argument will be returned. (Yacc parser has the same behavior.) Here shows the `SemanticValues` structure: ```cpp struct SemanticValues : protected std::vector { - // Input text - const char* path; - const char* ss; + // Input text + const char* path; + const char* ss; - // Matched string - std::string str() const; // Matched string - const char* c_str() const; // Matched string start - size_t length() const; // Matched string length + // Matched string + std::string_view sv() const { return sv_; } - // Line number and column at which the matched string is - std::pair line_info() const; + // Line number and column at which the matched string is + std::pair line_info() const; - // Tokens - std::vector< - std::pair< - const char*, // Token start - size_t>> // Token length - tokens; + // Tokens + std::vector tokens; + std::string_view token(size_t id = 0) const; - std::string token(size_t id = 0) const; + // Token conversion + std::string token_to_string(size_t id = 0) const; + template T token_to_number() const; - // Choice number (0 based index) - size_t choice() const; + // Choice number (0 based index) + size_t choice() const; - // Transform the semantic value vector to another vector - template vector transform(size_t beg = 0, size_t end = -1) const; + // Transform the semantic value vector to another vector + template vector transform(size_t beg = 0, size_t end = -1) const; } ``` @@ -178,14 +169,14 @@ The following example uses `<` ... ` >` operator, which is *token boundary* oper ```cpp peg::parser parser(R"( - ROOT <- _ TOKEN (',' _ TOKEN)* - TOKEN <- < [a-z0-9]+ > _ - _ <- [ \t\r\n]* + ROOT <- _ TOKEN (',' _ TOKEN)* + TOKEN <- < [a-z0-9]+ > _ + _ <- [ \t\r\n]* )"); -parser["TOKEN"] = [](const SemanticValues& sv) { - // 'token' doesn't include trailing whitespaces - auto token = sv.token(); +parser["TOKEN"] = [](const SemanticValues& vs) { + // 'token' doesn't include trailing whitespaces + auto token = vs.token(); }; auto ret = parser.parse(" token1, token2 "); @@ -195,13 +186,13 @@ We can ignore unnecessary semantic values from the list by using `~` operator. ```cpp peg::parser parser(R"( - ROOT <- _ ITEM (',' _ ITEM _)* - ITEM <- ([a-z])+ - ~_ <- [ \t]* + ROOT <- _ ITEM (',' _ ITEM _)* + ITEM <- ([a-z])+ + ~_ <- [ \t]* )"); -parser["ROOT"] = [&](const SemanticValues& sv) { - assert(sv.size() == 2); // should be 2 instead of 5. +parser["ROOT"] = [&](const SemanticValues& vs) { + assert(vs.size() == 2); // should be 2 instead of 5. }; auto ret = parser.parse(" item1, item2 "); @@ -211,9 +202,9 @@ The following grammar is same as the above. ```cpp peg::parser parser(R"( - ROOT <- ~_ ITEM (',' ~_ ITEM ~_)* - ITEM <- ([a-z])+ - _ <- [ \t]* + ROOT <- ~_ ITEM (',' ~_ ITEM ~_)* + ITEM <- ([a-z])+ + _ <- [ \t]* )"); ``` @@ -222,12 +213,12 @@ peg::parser parser(R"( ```cpp peg::parser parser("NUMBER <- [0-9]+"); -parser["NUMBER"] = [](const SemanticValues& sv) { - auto val = stol(sv.str(), nullptr, 10); - if (val != 100) { - throw peg::parse_error("value error!!"); - } - return val; +parser["NUMBER"] = [](const SemanticValues& vs) { + auto val = vs.token_to_number(); + if (val != 100) { + throw peg::parse_error("value error!!"); + } + return val; }; long val; @@ -243,15 +234,15 @@ assert(ret == false); ```cpp parser["RULE"].enter = [](const char* s, size_t n, any& dt) { - std::cout << "enter" << std::endl; + std::cout << "enter" << std::endl; }; -parser["RULE"] = [](const SemanticValues& sv, any& dt) { - std::cout << "action!" << std::endl; +parser["RULE"] = [](const SemanticValues& vs, any& dt) { + std::cout << "action!" << std::endl; }; parser["RULE"].leave = [](const char* s, size_t n, size_t matchlen, any& value, any& dt) { - std::cout << "leave" << std::endl; + std::cout << "leave" << std::endl; }; ``` @@ -291,9 +282,9 @@ Word expression ```cpp peg::parser parser(R"( - ROOT <- 'hello' 'world' - %whitespace <- [ \t\r\n]* - %word <- [a-z]+ + ROOT <- 'hello' 'world' + %whitespace <- [ \t\r\n]* + %word <- [a-z]+ )"); parser.parse("hello world"); // OK @@ -305,14 +296,14 @@ Capture/Backreference ```cpp peg::parser parser(R"( - ROOT <- CONTENT - CONTENT <- (ELEMENT / TEXT)* - ELEMENT <- $(STAG CONTENT ETAG) - STAG <- '<' $tag< TAG_NAME > '>' - ETAG <- '' - TAG_NAME <- 'b' / 'u' - TEXT <- TEXT_DATA - TEXT_DATA <- ![<] . + ROOT <- CONTENT + CONTENT <- (ELEMENT / TEXT)* + ELEMENT <- $(STAG CONTENT ETAG) + STAG <- '<' $tag< TAG_NAME > '>' + ETAG <- '' + TAG_NAME <- 'b' / 'u' + TEXT <- TEXT_DATA + TEXT_DATA <- ![<] . )"); parser.parse("This is a test text."); // OK @@ -359,36 +350,36 @@ Regarding the *precedence climbing algorithm*, please see [this article](https:/ ```cpp parser parser(R"( - EXPRESSION <- INFIX_EXPRESSION(ATOM, OPERATOR) - ATOM <- NUMBER / '(' EXPRESSION ')' - OPERATOR <- < [-+/*] > - NUMBER <- < '-'? [0-9]+ > - %whitespace <- [ \t]* - - # Declare order of precedence - INFIX_EXPRESSION(A, O) <- A (O A)* { - precedence - L + - - L * / - } + EXPRESSION <- INFIX_EXPRESSION(ATOM, OPERATOR) + ATOM <- NUMBER / '(' EXPRESSION ')' + OPERATOR <- < [-+/*] > + NUMBER <- < '-'? [0-9]+ > + %whitespace <- [ \t]* + + # Declare order of precedence + INFIX_EXPRESSION(A, O) <- A (O A)* { + precedence + L + - + L * / + } )"); -parser["INFIX_EXPRESSION"] = [](const SemanticValues& sv) -> long { - auto result = any_cast(sv[0]); - if (sv.size() > 1) { - auto ope = any_cast(sv[1]); - auto num = any_cast(sv[2]); - switch (ope) { - case '+': result += num; break; - case '-': result -= num; break; - case '*': result *= num; break; - case '/': result /= num; break; - } +parser["INFIX_EXPRESSION"] = [](const SemanticValues& vs) -> long { + auto result = any_cast(vs[0]); + if (vs.size() > 1) { + auto ope = any_cast(vs[1]); + auto num = any_cast(vs[2]); + switch (ope) { + case '+': result += num; break; + case '-': result -= num; break; + case '*': result *= num; break; + case '/': result /= num; break; } - return result; + } + return result; }; -parser["OPERATOR"] = [](const SemanticValues& sv) { return *sv.c_str(); }; -parser["NUMBER"] = [](const SemanticValues& sv) { return atol(sv.c_str()); }; +parser["OPERATOR"] = [](const SemanticValues& vs) { return *vs.sv(); }; +parser["NUMBER"] = [](const SemanticValues& vs) { return vs.token_to_number(); }; long val; parser.parse(" -1 + (1 + 2) * 3 - -1", val); @@ -446,8 +437,8 @@ vector tags; Definition ROOT, TAG_NAME, _; ROOT <= seq(_, zom(seq(chr('['), TAG_NAME, chr(']'), _))); -TAG_NAME <= oom(seq(npd(chr(']')), dot())), [&](const SemanticValues& sv) { - tags.push_back(sv.str()); +TAG_NAME <= oom(seq(npd(chr(']')), dot())), [&](const SemanticValues& vs) { + tags.push_back(vs.str()); }; _ <= zom(cls(" \t")); @@ -487,24 +478,24 @@ It's possible to add/override definitions. ```cpp auto syntax = R"( - ROOT <- _ 'Hello' _ NAME '!' _ + ROOT <- _ 'Hello' _ NAME '!' _ )"; Rules additional_rules = { - { - "NAME", usr([](const char* s, size_t n, SemanticValues& sv, any& dt) -> size_t { - static vector names = { "PEG", "BNF" }; - for (const auto& name: names) { - if (name.size() <= n && !name.compare(0, name.size(), s, name.size())) { - return name.size(); // processed length - } - } - return -1; // parse error - }) - }, - { - "~_", zom(cls(" \t\r\n")) - } + { + "NAME", usr([](const char* s, size_t n, SemanticValues& vs, any& dt) -> size_t { + static vector names = { "PEG", "BNF" }; + for (const auto& name: names) { + if (name.size() <= n && !name.compare(0, name.size(), s, name.size())) { + return name.size(); // processed length + } + } + return -1; // parse error + }) + }, + { + "~_", zom(cls(" \t\r\n")) + } }; auto g = parser(syntax, additional_rules); diff --git a/appveyor.yml b/appveyor.yml index 942555e..3b39dc2 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,9 +2,6 @@ clone_depth: 5 environment: matrix: - - JOB: Visual Studio 2015 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - CMAKE_GENERATOR: "Visual Studio 14 2015" - JOB: Visual Studio 2017 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 CMAKE_GENERATOR: "Visual Studio 15 2017" diff --git a/docs/build.sh b/docs/build.sh index 91b6cbb..8099d75 100644 --- a/docs/build.sh +++ b/docs/build.sh @@ -1,2 +1,2 @@ source ~/Projects/emsdk/emsdk_env.sh -emcc -std=c++11 -O3 --bind -o native.js native.cpp +emcc -std=c++17 -O3 --bind -o native.js native.cpp diff --git a/docs/native.js b/docs/native.js index 32745cc..fe318f9 100644 --- a/docs/native.js +++ b/docs/native.js @@ -1 +1 @@ -var Module=typeof Module!=="undefined"?Module:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=require("path").dirname(scriptDirectory)+"/"}else{scriptDirectory=__dirname+"/"}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);if(typeof module!=="undefined"){module["exports"]=Module}process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status)};Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)}}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs}else if(typeof arguments!="undefined"){arguments_=arguments}if(typeof quit==="function"){quit_=function(status){quit(status)}}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}setWindowTitle=function(title){document.title=title}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){err("no native wasm support detected")}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":839,"maximum":839+0,"element":"anyfunc"});var ABORT=false;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}var UTF8Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf8"):undefined;function UTF8ArrayToString(heap,idx,maxBytesToRead){var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heap[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heap.subarray&&UTF8Decoder){return UTF8Decoder.decode(heap.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4}return len}var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;function UTF16ToString(ptr,maxBytesToRead){var endPtr=ptr;var idx=endPtr>>1;var maxIdx=idx+maxBytesToRead/2;while(!(idx>=maxIdx)&&HEAPU16[idx])++idx;endPtr=idx<<1;if(endPtr-ptr>32&&UTF16Decoder){return UTF16Decoder.decode(HEAPU8.subarray(ptr,endPtr))}else{var i=0;var str="";while(1){var codeUnit=HEAP16[ptr+i*2>>1];if(codeUnit==0||i==maxBytesToRead/2)return str;++i;str+=String.fromCharCode(codeUnit)}}}function stringToUTF16(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr}function lengthBytesUTF16(str){return str.length*2}function UTF32ToString(ptr,maxBytesToRead){var i=0;var str="";while(!(i>=maxBytesToRead/4)){var utf32=HEAP32[ptr+i*4>>2];if(utf32==0)break;++i;if(utf32>=65536){var ch=utf32-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}else{str+=String.fromCharCode(utf32)}}return str}function stringToUTF32(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i=55296&&codeUnit<=57343){var trailSurrogate=str.charCodeAt(++i);codeUnit=65536+((codeUnit&1023)<<10)|trailSurrogate&1023}HEAP32[outPtr>>2]=codeUnit;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr}function lengthBytesUTF32(str){var len=0;for(var i=0;i=55296&&codeUnit<=57343)++i;len+=4}return len}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}var WASM_PAGE_SIZE=65536;var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var DYNAMIC_BASE=5278160,DYNAMICTOP_PTR=35120;var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"]}else{wasmMemory=new WebAssembly.Memory({"initial":INITIAL_INITIAL_MEMORY/WASM_PAGE_SIZE,"maximum":INITIAL_INITIAL_MEMORY/WASM_PAGE_SIZE})}if(wasmMemory){buffer=wasmMemory.buffer}INITIAL_INITIAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func)}else{Module["dynCall_vi"](func,callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;if(!Module["noFSInit"]&&!FS.init.initialized)FS.init();TTY.init();callRuntimeCallbacks(__ATINIT__)}function preMain(){FS.ignorePermissions=false;callRuntimeCallbacks(__ATMAIN__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var Math_abs=Math.abs;var Math_ceil=Math.ceil;var Math_floor=Math.floor;var Math_min=Math.min;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function getUniqueRunDependency(id){return id}function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+="";out(what);err(what);ABORT=true;EXITSTATUS=1;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";throw new WebAssembly.RuntimeError(what)}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="native.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw"both async and sync fetching of the wasm failed"}}catch(err){abort(err)}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw"failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary())})}function createWasm(){var info={"a":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;removeRunDependency("wasm-instantiate")}addRunDependency("wasm-instantiate");function receiveInstantiatedSource(output){receiveInstance(output["instance"])}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason)})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource)})})}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return{}}var tempDouble;var tempI64;__ATINIT__.push({func:function(){___wasm_call_ctors()}});function demangle(func){return func}function demangleAll(text){var regex=/\b_Z[\w\d_]+/g;return text.replace(regex,function(x){var y=demangle(x);return x===y?x:y+" ["+x+"]"})}function jsStackTrace(){var err=new Error;if(!err.stack){try{throw new Error}catch(e){err=e}if(!err.stack){return"(no stack trace available)"}}return err.stack.toString()}function stackTrace(){var js=jsStackTrace();if(Module["extraStackTrace"])js+="\n"+Module["extraStackTrace"]();return demangleAll(js)}function ___assert_fail(condition,filename,line,func){abort("Assertion failed: "+UTF8ToString(condition)+", at: "+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])}function ___cxa_allocate_exception(size){return _malloc(size)}var ___exception_infos={};var ___exception_last=0;function __ZSt18uncaught_exceptionv(){return __ZSt18uncaught_exceptionv.uncaught_exceptions>0}function ___cxa_throw(ptr,type,destructor){___exception_infos[ptr]={ptr:ptr,adjusted:[ptr],type:type,destructor:destructor,refcount:0,caught:false,rethrown:false};___exception_last=ptr;if(!("uncaught_exception"in __ZSt18uncaught_exceptionv)){__ZSt18uncaught_exceptionv.uncaught_exceptions=1}else{__ZSt18uncaught_exceptionv.uncaught_exceptions++}throw ptr}function setErrNo(value){HEAP32[___errno_location()>>2]=value;return value}function ___map_file(pathname,size){setErrNo(63);return-1}var PATH={splitPath:function(filename){var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:function(parts,allowAboveRoot){var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:function(path){var isAbsolute=path.charAt(0)==="/",trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(function(p){return!!p}),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:function(path){var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:function(path){if(path==="/")return"/";var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},extname:function(path){return PATH.splitPath(path)[3]},join:function(){var paths=Array.prototype.slice.call(arguments,0);return PATH.normalize(paths.join("/"))},join2:function(l,r){return PATH.normalize(l+"/"+r)}};var PATH_FS={resolve:function(){var resolvedPath="",resolvedAbsolute=false;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?arguments[i]:FS.cwd();if(typeof path!=="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=path.charAt(0)==="/"}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter(function(p){return!!p}),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."},relative:function(from,to){from=PATH_FS.resolve(from).substr(1);to=PATH_FS.resolve(to).substr(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i0){result=buf.slice(0,bytesRead).toString("utf-8")}else{result=null}}else if(typeof window!="undefined"&&typeof window.prompt=="function"){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else if(typeof readline=="function"){result=readline();if(result!==null){result+="\n"}}if(!result){return null}tty.input=intArrayFromString(result,true)}return tty.input.shift()},put_char:function(tty,val){if(val===null||val===10){out(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},flush:function(tty){if(tty.output&&tty.output.length>0){out(UTF8ArrayToString(tty.output,0));tty.output=[]}}},default_tty1_ops:{put_char:function(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},flush:function(tty){if(tty.output&&tty.output.length>0){err(UTF8ArrayToString(tty.output,0));tty.output=[]}}}};var MEMFS={ops_table:null,mount:function(mount){return MEMFS.createNode(null,"/",16384|511,0)},createNode:function(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(63)}if(!MEMFS.ops_table){MEMFS.ops_table={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,allocate:MEMFS.stream_ops.allocate,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}}}var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=null}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.timestamp=Date.now();if(parent){parent.contents[name]=node}return node},getFileDataAsRegularArray:function(node){if(node.contents&&node.contents.subarray){var arr=[];for(var i=0;i=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity>>0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0);return},resizeFileStorage:function(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0;return}if(!node.contents||node.contents.subarray){var oldContents=node.contents;node.contents=new Uint8Array(newSize);if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize;return}if(!node.contents)node.contents=[];if(node.contents.length>newSize)node.contents.length=newSize;else while(node.contents.length=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i0||position+length8){throw new FS.ErrnoError(32)}var parts=PATH.normalizeArray(path.split("/").filter(function(p){return!!p}),false);var current=FS.root;var current_path="/";for(var i=0;i40){throw new FS.ErrnoError(32)}}}}return{path:current_path,node:current}},getPath:function(node){var path;while(true){if(FS.isRoot(node)){var mount=node.mount.mountpoint;if(!path)return mount;return mount[mount.length-1]!=="/"?mount+"/"+path:mount+path}path=path?node.name+"/"+path:node.name;node=node.parent}},hashName:function(parentid,name){var hash=0;for(var i=0;i>>0)%FS.nameTable.length},hashAddNode:function(node){var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode:function(node){var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode:function(parent,name){var errCode=FS.mayLookup(parent);if(errCode){throw new FS.ErrnoError(errCode,parent)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode:function(parent,name,mode,rdev){var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode:function(node){FS.hashRemoveNode(node)},isRoot:function(node){return node===node.parent},isMountpoint:function(node){return!!node.mounted},isFile:function(mode){return(mode&61440)===32768},isDir:function(mode){return(mode&61440)===16384},isLink:function(mode){return(mode&61440)===40960},isChrdev:function(mode){return(mode&61440)===8192},isBlkdev:function(mode){return(mode&61440)===24576},isFIFO:function(mode){return(mode&61440)===4096},isSocket:function(mode){return(mode&49152)===49152},flagModes:{"r":0,"rs":1052672,"r+":2,"w":577,"wx":705,"xw":705,"w+":578,"wx+":706,"xw+":706,"a":1089,"ax":1217,"xa":1217,"a+":1090,"ax+":1218,"xa+":1218},modeStringToFlags:function(str){var flags=FS.flagModes[str];if(typeof flags==="undefined"){throw new Error("Unknown file open mode: "+str)}return flags},flagsToPermissionString:function(flag){var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms},nodePermissions:function(node,perms){if(FS.ignorePermissions){return 0}if(perms.indexOf("r")!==-1&&!(node.mode&292)){return 2}else if(perms.indexOf("w")!==-1&&!(node.mode&146)){return 2}else if(perms.indexOf("x")!==-1&&!(node.mode&73)){return 2}return 0},mayLookup:function(dir){var errCode=FS.nodePermissions(dir,"x");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate:function(dir,name){try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,"wx")},mayDelete:function(dir,name,isdir){var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var errCode=FS.nodePermissions(dir,"wx");if(errCode){return errCode}if(isdir){if(!FS.isDir(node.mode)){return 54}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 10}}else{if(FS.isDir(node.mode)){return 31}}return 0},mayOpen:function(node,flags){if(!node){return 44}if(FS.isLink(node.mode)){return 32}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!=="r"||flags&512){return 31}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))},MAX_OPEN_FDS:4096,nextfd:function(fd_start,fd_end){fd_start=fd_start||0;fd_end=fd_end||FS.MAX_OPEN_FDS;for(var fd=fd_start;fd<=fd_end;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStream:function(fd){return FS.streams[fd]},createStream:function(stream,fd_start,fd_end){if(!FS.FSStream){FS.FSStream=function(){};FS.FSStream.prototype={object:{get:function(){return this.node},set:function(val){this.node=val}},isRead:{get:function(){return(this.flags&2097155)!==1}},isWrite:{get:function(){return(this.flags&2097155)!==0}},isAppend:{get:function(){return this.flags&1024}}}}var newStream=new FS.FSStream;for(var p in stream){newStream[p]=stream[p]}stream=newStream;var fd=FS.nextfd(fd_start,fd_end);stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream:function(fd){FS.streams[fd]=null},chrdev_stream_ops:{open:function(stream){var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;if(stream.stream_ops.open){stream.stream_ops.open(stream)}},llseek:function(){throw new FS.ErrnoError(70)}},major:function(dev){return dev>>8},minor:function(dev){return dev&255},makedev:function(ma,mi){return ma<<8|mi},registerDevice:function(dev,ops){FS.devices[dev]={stream_ops:ops}},getDevice:function(dev){return FS.devices[dev]},getMounts:function(mount){var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push.apply(check,m.mounts)}return mounts},syncfs:function(populate,callback){if(typeof populate==="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){err("warning: "+FS.syncFSRequests+" FS.syncfs operations in flight at once, probably just doing extra work")}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(errCode){FS.syncFSRequests--;return callback(errCode)}function done(errCode){if(errCode){if(!done.errored){done.errored=true;return doCallback(errCode)}return}if(++completed>=mounts.length){doCallback(null)}}mounts.forEach(function(mount){if(!mount.type.syncfs){return done(null)}mount.type.syncfs(mount,populate,done)})},mount:function(type,opts,mountpoint){var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(10)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}}var mount={type:type,opts:opts,mountpoint:mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount:function(mountpoint){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);Object.keys(FS.nameTable).forEach(function(hash){var current=FS.nameTable[hash];while(current){var next=current.name_next;if(mounts.indexOf(current.mount)!==-1){FS.destroyNode(current)}current=next}});node.mounted=null;var idx=node.mount.mounts.indexOf(mount);node.mount.mounts.splice(idx,1)},lookup:function(parent,name){return parent.node_ops.lookup(parent,name)},mknod:function(path,mode,dev){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name||name==="."||name===".."){throw new FS.ErrnoError(28)}var errCode=FS.mayCreate(parent,name);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(63)}return parent.node_ops.mknod(parent,name,mode,dev)},create:function(path,mode){mode=mode!==undefined?mode:438;mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir:function(path,mode){mode=mode!==undefined?mode:511;mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree:function(path,mode){var dirs=path.split("/");var d="";for(var i=0;ithis.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]};LazyUint8Array.prototype.setDataGetter=function LazyUint8Array_setDataGetter(getter){this.getter=getter};LazyUint8Array.prototype.cacheLength=function LazyUint8Array_cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=function(from,to){if(from>to)throw new Error("invalid range ("+from+", "+to+") or no bytes requested!");if(to>datalength-1)throw new Error("only "+datalength+" bytes available! programmer error!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);if(typeof Uint8Array!="undefined")xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}else{return intArrayFromString(xhr.responseText||"",true)}};var lazyArray=this;lazyArray.setDataGetter(function(chunkNum){var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]==="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]==="undefined")throw new Error("doXHR failed!");return lazyArray.chunks[chunkNum]});if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;out("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true};if(typeof XMLHttpRequest!=="undefined"){if(!ENVIRONMENT_IS_WORKER)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";var lazyArray=new LazyUint8Array;Object.defineProperties(lazyArray,{length:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._length}},chunkSize:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}});var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url:url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};var keys=Object.keys(node.stream_ops);keys.forEach(function(key){var fn=node.stream_ops[key];stream_ops[key]=function forceLoadLazyFile(){if(!FS.forceLoadFile(node)){throw new FS.ErrnoError(29)}return fn.apply(null,arguments)}});stream_ops.read=function stream_ops_read(stream,buffer,offset,length,position){if(!FS.forceLoadFile(node)){throw new FS.ErrnoError(29)}var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);if(contents.slice){for(var i=0;i>2]=stat.dev;HEAP32[buf+4>>2]=0;HEAP32[buf+8>>2]=stat.ino;HEAP32[buf+12>>2]=stat.mode;HEAP32[buf+16>>2]=stat.nlink;HEAP32[buf+20>>2]=stat.uid;HEAP32[buf+24>>2]=stat.gid;HEAP32[buf+28>>2]=stat.rdev;HEAP32[buf+32>>2]=0;tempI64=[stat.size>>>0,(tempDouble=stat.size,+Math_abs(tempDouble)>=1?tempDouble>0?(Math_min(+Math_floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+40>>2]=tempI64[0],HEAP32[buf+44>>2]=tempI64[1];HEAP32[buf+48>>2]=4096;HEAP32[buf+52>>2]=stat.blocks;HEAP32[buf+56>>2]=stat.atime.getTime()/1e3|0;HEAP32[buf+60>>2]=0;HEAP32[buf+64>>2]=stat.mtime.getTime()/1e3|0;HEAP32[buf+68>>2]=0;HEAP32[buf+72>>2]=stat.ctime.getTime()/1e3|0;HEAP32[buf+76>>2]=0;tempI64=[stat.ino>>>0,(tempDouble=stat.ino,+Math_abs(tempDouble)>=1?tempDouble>0?(Math_min(+Math_floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+80>>2]=tempI64[0],HEAP32[buf+84>>2]=tempI64[1];return 0},doMsync:function(addr,stream,len,flags,offset){var buffer=HEAPU8.slice(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},doMkdir:function(path,mode){path=PATH.normalize(path);if(path[path.length-1]==="/")path=path.substr(0,path.length-1);FS.mkdir(path,mode,0);return 0},doMknod:function(path,mode,dev){switch(mode&61440){case 32768:case 8192:case 24576:case 4096:case 49152:break;default:return-28}FS.mknod(path,mode,dev);return 0},doReadlink:function(path,buf,bufsize){if(bufsize<=0)return-28;var ret=FS.readlink(path);var len=Math.min(bufsize,lengthBytesUTF8(ret));var endChar=HEAP8[buf+len];stringToUTF8(ret,buf,bufsize+1);HEAP8[buf+len]=endChar;return len},doAccess:function(path,amode){if(amode&~7){return-28}var node;var lookup=FS.lookupPath(path,{follow:true});node=lookup.node;if(!node){return-44}var perms="";if(amode&4)perms+="r";if(amode&2)perms+="w";if(amode&1)perms+="x";if(perms&&FS.nodePermissions(node,perms)){return-2}return 0},doDup:function(path,flags,suggestFD){var suggest=FS.getStream(suggestFD);if(suggest)FS.close(suggest);return FS.open(path,flags,0,suggestFD,suggestFD).fd},doReadv:function(stream,iov,iovcnt,offset){var ret=0;for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2];var len=HEAP32[iov+(i*8+4)>>2];var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr}return ret},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},getStreamFromFD:function(fd){var stream=FS.getStream(fd);if(!stream)throw new FS.ErrnoError(8);return stream},get64:function(low,high){return low}};function syscallMunmap(addr,len){if((addr|0)===-1||len===0){return-28}var info=SYSCALLS.mappings[addr];if(!info)return 0;if(len===info.len){var stream=FS.getStream(info.fd);if(info.prot&2){SYSCALLS.doMsync(addr,stream,len,info.flags,info.offset)}FS.munmap(stream);SYSCALLS.mappings[addr]=null;if(info.allocated){_free(info.malloc)}}return 0}function ___sys_munmap(addr,len){try{return syscallMunmap(addr,len)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function getShiftFromSize(size){switch(size){case 1:return 0;case 2:return 1;case 4:return 2;case 8:return 3;default:throw new TypeError("Unknown type size: "+size)}}function embind_init_charCodes(){var codes=new Array(256);for(var i=0;i<256;++i){codes[i]=String.fromCharCode(i)}embind_charCodes=codes}var embind_charCodes=undefined;function readLatin1String(ptr){var ret="";var c=ptr;while(HEAPU8[c]){ret+=embind_charCodes[HEAPU8[c++]]}return ret}var awaitingDependencies={};var registeredTypes={};var typeDependencies={};var char_0=48;var char_9=57;function makeLegalFunctionName(name){if(undefined===name){return"_unknown"}name=name.replace(/[^a-zA-Z0-9_]/g,"$");var f=name.charCodeAt(0);if(f>=char_0&&f<=char_9){return"_"+name}else{return name}}function createNamedFunction(name,body){name=makeLegalFunctionName(name);return new Function("body","return function "+name+"() {\n"+' "use strict";'+" return body.apply(this, arguments);\n"+"};\n")(body)}function extendError(baseErrorType,errorName){var errorClass=createNamedFunction(errorName,function(message){this.name=errorName;this.message=message;var stack=new Error(message).stack;if(stack!==undefined){this.stack=this.toString()+"\n"+stack.replace(/^Error(:[^\n]*)?\n/,"")}});errorClass.prototype=Object.create(baseErrorType.prototype);errorClass.prototype.constructor=errorClass;errorClass.prototype.toString=function(){if(this.message===undefined){return this.name}else{return this.name+": "+this.message}};return errorClass}var BindingError=undefined;function throwBindingError(message){throw new BindingError(message)}var InternalError=undefined;function throwInternalError(message){throw new InternalError(message)}function whenDependentTypesAreResolved(myTypes,dependentTypes,getTypeConverters){myTypes.forEach(function(type){typeDependencies[type]=dependentTypes});function onComplete(typeConverters){var myTypeConverters=getTypeConverters(typeConverters);if(myTypeConverters.length!==myTypes.length){throwInternalError("Mismatched type converter count")}for(var i=0;i>shift])},destructorFunction:null})}var emval_free_list=[];var emval_handle_array=[{},{value:undefined},{value:null},{value:true},{value:false}];function __emval_decref(handle){if(handle>4&&0===--emval_handle_array[handle].refcount){emval_handle_array[handle]=undefined;emval_free_list.push(handle)}}function count_emval_handles(){var count=0;for(var i=5;i>2])}function __embind_register_emval(rawType,name){name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":function(handle){var rv=emval_handle_array[handle].value;__emval_decref(handle);return rv},"toWireType":function(destructors,value){return __emval_register(value)},"argPackAdvance":8,"readValueFromPointer":simpleReadValueFromPointer,destructorFunction:null})}function _embind_repr(v){if(v===null){return"null"}var t=typeof v;if(t==="object"||t==="array"||t==="function"){return v.toString()}else{return""+v}}function floatReadValueFromPointer(name,shift){switch(shift){case 2:return function(pointer){return this["fromWireType"](HEAPF32[pointer>>2])};case 3:return function(pointer){return this["fromWireType"](HEAPF64[pointer>>3])};default:throw new TypeError("Unknown float type: "+name)}}function __embind_register_float(rawType,name,size){var shift=getShiftFromSize(size);name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":function(value){return value},"toWireType":function(destructors,value){if(typeof value!=="number"&&typeof value!=="boolean"){throw new TypeError('Cannot convert "'+_embind_repr(value)+'" to '+this.name)}return value},"argPackAdvance":8,"readValueFromPointer":floatReadValueFromPointer(name,shift),destructorFunction:null})}function new_(constructor,argumentList){if(!(constructor instanceof Function)){throw new TypeError("new_ called with constructor type "+typeof constructor+" which is not a function")}var dummy=createNamedFunction(constructor.name||"unknownFunctionName",function(){});dummy.prototype=constructor.prototype;var obj=new dummy;var r=constructor.apply(obj,argumentList);return r instanceof Object?r:obj}function runDestructors(destructors){while(destructors.length){var ptr=destructors.pop();var del=destructors.pop();del(ptr)}}function craftInvokerFunction(humanName,argTypes,classType,cppInvokerFunc,cppTargetFunc){var argCount=argTypes.length;if(argCount<2){throwBindingError("argTypes array size mismatch! Must at least get return value and 'this' types!")}var isClassMethodFunc=argTypes[1]!==null&&classType!==null;var needsDestructorStack=false;for(var i=1;i0?", ":"")+argsListWired}invokerFnBody+=(returns?"var rv = ":"")+"invoker(fn"+(argsListWired.length>0?", ":"")+argsListWired+");\n";if(needsDestructorStack){invokerFnBody+="runDestructors(destructors);\n"}else{for(var i=isClassMethodFunc?1:2;i>2)+i])}return array}function replacePublicSymbol(name,value,numArguments){if(!Module.hasOwnProperty(name)){throwInternalError("Replacing nonexistant public symbol")}if(undefined!==Module[name].overloadTable&&undefined!==numArguments){Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}}function embind__requireFunction(signature,rawFunction){signature=readLatin1String(signature);function makeDynCaller(dynCall){var args=[];for(var i=1;i>1]}:function readU16FromPointer(pointer){return HEAPU16[pointer>>1]};case 2:return signed?function readS32FromPointer(pointer){return HEAP32[pointer>>2]}:function readU32FromPointer(pointer){return HEAPU32[pointer>>2]};default:throw new TypeError("Unknown integer type: "+name)}}function __embind_register_integer(primitiveType,name,size,minRange,maxRange){name=readLatin1String(name);if(maxRange===-1){maxRange=4294967295}var shift=getShiftFromSize(size);var fromWireType=function(value){return value};if(minRange===0){var bitshift=32-8*size;fromWireType=function(value){return value<>>bitshift}}var isUnsignedType=name.indexOf("unsigned")!=-1;registerType(primitiveType,{name:name,"fromWireType":fromWireType,"toWireType":function(destructors,value){if(typeof value!=="number"&&typeof value!=="boolean"){throw new TypeError('Cannot convert "'+_embind_repr(value)+'" to '+this.name)}if(valuemaxRange){throw new TypeError('Passing a number "'+_embind_repr(value)+'" from JS side to C/C++ side to an argument of type "'+name+'", which is outside the valid range ['+minRange+", "+maxRange+"]!")}return isUnsignedType?value>>>0:value|0},"argPackAdvance":8,"readValueFromPointer":integerReadValueFromPointer(name,shift,minRange!==0),destructorFunction:null})}function __embind_register_memory_view(rawType,dataTypeIndex,name){var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){handle=handle>>2;var heap=HEAPU32;var size=heap[handle];var data=heap[handle+1];return new TA(buffer,data,size)}name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":decodeMemoryView,"argPackAdvance":8,"readValueFromPointer":decodeMemoryView},{ignoreDuplicateRegistrations:true})}function __embind_register_std_string(rawType,name){name=readLatin1String(name);var stdStringIsUTF8=name==="std::string";registerType(rawType,{name:name,"fromWireType":function(value){var length=HEAPU32[value>>2];var str;if(stdStringIsUTF8){var decodeStartPtr=value+4;for(var i=0;i<=length;++i){var currentBytePtr=value+4+i;if(HEAPU8[currentBytePtr]==0||i==length){var maxRead=currentBytePtr-decodeStartPtr;var stringSegment=UTF8ToString(decodeStartPtr,maxRead);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+1}}}else{var a=new Array(length);for(var i=0;i>2]=length;if(stdStringIsUTF8&&valueIsOfTypeString){stringToUTF8(value,ptr+4,length+1)}else{if(valueIsOfTypeString){for(var i=0;i255){_free(ptr);throwBindingError("String has UTF-16 code units that do not fit in 8 bits")}HEAPU8[ptr+4+i]=charCode}}else{for(var i=0;i>2];var HEAP=getHeap();var str;var decodeStartPtr=value+4;for(var i=0;i<=length;++i){var currentBytePtr=value+4+i*charSize;if(HEAP[currentBytePtr>>shift]==0||i==length){var maxReadBytes=currentBytePtr-decodeStartPtr;var stringSegment=decodeString(decodeStartPtr,maxReadBytes);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+charSize}}_free(value);return str},"toWireType":function(destructors,value){if(!(typeof value==="string")){throwBindingError("Cannot pass non-string to C++ string type "+name)}var length=lengthBytesUTF(value);var ptr=_malloc(4+length+charSize);HEAPU32[ptr>>2]=length>>shift;encodeString(value,ptr+4,length+charSize);if(destructors!==null){destructors.push(_free,ptr)}return ptr},"argPackAdvance":8,"readValueFromPointer":simpleReadValueFromPointer,destructorFunction:function(ptr){_free(ptr)}})}function __embind_register_void(rawType,name){name=readLatin1String(name);registerType(rawType,{isVoid:true,name:name,"argPackAdvance":0,"fromWireType":function(){return undefined},"toWireType":function(destructors,o){return undefined}})}function _abort(){abort()}function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src,src+num)}function abortOnCannotGrowMemory(requestedSize){abort("OOM")}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;abortOnCannotGrowMemory(requestedSize)}var ENV={};function __getExecutableName(){return thisProgram||"./this.program"}function getEnvStrings(){if(!getEnvStrings.strings){var env={"USER":"web_user","LOGNAME":"web_user","PATH":"/","PWD":"/","HOME":"/home/web_user","LANG":(typeof navigator==="object"&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8","_":__getExecutableName()};for(var x in ENV){env[x]=ENV[x]}var strings=[];for(var x in env){strings.push(x+"="+env[x])}getEnvStrings.strings=strings}return getEnvStrings.strings}function _environ_get(__environ,environ_buf){var bufSize=0;getEnvStrings().forEach(function(string,i){var ptr=environ_buf+bufSize;HEAP32[__environ+i*4>>2]=ptr;writeAsciiToMemory(string,ptr);bufSize+=string.length+1});return 0}function _environ_sizes_get(penviron_count,penviron_buf_size){var strings=getEnvStrings();HEAP32[penviron_count>>2]=strings.length;var bufSize=0;strings.forEach(function(string){bufSize+=string.length+1});HEAP32[penviron_buf_size>>2]=bufSize;return 0}function __isLeapYear(year){return year%4===0&&(year%100!==0||year%400===0)}function __arraySum(array,index){var sum=0;for(var i=0;i<=index;sum+=array[i++]){}return sum}var __MONTH_DAYS_LEAP=[31,29,31,30,31,30,31,31,30,31,30,31];var __MONTH_DAYS_REGULAR=[31,28,31,30,31,30,31,31,30,31,30,31];function __addDays(date,days){var newDate=new Date(date.getTime());while(days>0){var leap=__isLeapYear(newDate.getFullYear());var currentMonth=newDate.getMonth();var daysInCurrentMonth=(leap?__MONTH_DAYS_LEAP:__MONTH_DAYS_REGULAR)[currentMonth];if(days>daysInCurrentMonth-newDate.getDate()){days-=daysInCurrentMonth-newDate.getDate()+1;newDate.setDate(1);if(currentMonth<11){newDate.setMonth(currentMonth+1)}else{newDate.setMonth(0);newDate.setFullYear(newDate.getFullYear()+1)}}else{newDate.setDate(newDate.getDate()+days);return newDate}}return newDate}function _strftime(s,maxsize,format,tm){var tm_zone=HEAP32[tm+40>>2];var date={tm_sec:HEAP32[tm>>2],tm_min:HEAP32[tm+4>>2],tm_hour:HEAP32[tm+8>>2],tm_mday:HEAP32[tm+12>>2],tm_mon:HEAP32[tm+16>>2],tm_year:HEAP32[tm+20>>2],tm_wday:HEAP32[tm+24>>2],tm_yday:HEAP32[tm+28>>2],tm_isdst:HEAP32[tm+32>>2],tm_gmtoff:HEAP32[tm+36>>2],tm_zone:tm_zone?UTF8ToString(tm_zone):""};var pattern=UTF8ToString(format);var EXPANSION_RULES_1={"%c":"%a %b %d %H:%M:%S %Y","%D":"%m/%d/%y","%F":"%Y-%m-%d","%h":"%b","%r":"%I:%M:%S %p","%R":"%H:%M","%T":"%H:%M:%S","%x":"%m/%d/%y","%X":"%H:%M:%S","%Ec":"%c","%EC":"%C","%Ex":"%m/%d/%y","%EX":"%H:%M:%S","%Ey":"%y","%EY":"%Y","%Od":"%d","%Oe":"%e","%OH":"%H","%OI":"%I","%Om":"%m","%OM":"%M","%OS":"%S","%Ou":"%u","%OU":"%U","%OV":"%V","%Ow":"%w","%OW":"%W","%Oy":"%y"};for(var rule in EXPANSION_RULES_1){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_1[rule])}var WEEKDAYS=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];var MONTHS=["January","February","March","April","May","June","July","August","September","October","November","December"];function leadingSomething(value,digits,character){var str=typeof value==="number"?value.toString():value||"";while(str.length0?1:0}var compare;if((compare=sgn(date1.getFullYear()-date2.getFullYear()))===0){if((compare=sgn(date1.getMonth()-date2.getMonth()))===0){compare=sgn(date1.getDate()-date2.getDate())}}return compare}function getFirstWeekStartDate(janFourth){switch(janFourth.getDay()){case 0:return new Date(janFourth.getFullYear()-1,11,29);case 1:return janFourth;case 2:return new Date(janFourth.getFullYear(),0,3);case 3:return new Date(janFourth.getFullYear(),0,2);case 4:return new Date(janFourth.getFullYear(),0,1);case 5:return new Date(janFourth.getFullYear()-1,11,31);case 6:return new Date(janFourth.getFullYear()-1,11,30)}}function getWeekBasedYear(date){var thisDate=__addDays(new Date(date.tm_year+1900,0,1),date.tm_yday);var janFourthThisYear=new Date(thisDate.getFullYear(),0,4);var janFourthNextYear=new Date(thisDate.getFullYear()+1,0,4);var firstWeekStartThisYear=getFirstWeekStartDate(janFourthThisYear);var firstWeekStartNextYear=getFirstWeekStartDate(janFourthNextYear);if(compareByDay(firstWeekStartThisYear,thisDate)<=0){if(compareByDay(firstWeekStartNextYear,thisDate)<=0){return thisDate.getFullYear()+1}else{return thisDate.getFullYear()}}else{return thisDate.getFullYear()-1}}var EXPANSION_RULES_2={"%a":function(date){return WEEKDAYS[date.tm_wday].substring(0,3)},"%A":function(date){return WEEKDAYS[date.tm_wday]},"%b":function(date){return MONTHS[date.tm_mon].substring(0,3)},"%B":function(date){return MONTHS[date.tm_mon]},"%C":function(date){var year=date.tm_year+1900;return leadingNulls(year/100|0,2)},"%d":function(date){return leadingNulls(date.tm_mday,2)},"%e":function(date){return leadingSomething(date.tm_mday,2," ")},"%g":function(date){return getWeekBasedYear(date).toString().substring(2)},"%G":function(date){return getWeekBasedYear(date)},"%H":function(date){return leadingNulls(date.tm_hour,2)},"%I":function(date){var twelveHour=date.tm_hour;if(twelveHour==0)twelveHour=12;else if(twelveHour>12)twelveHour-=12;return leadingNulls(twelveHour,2)},"%j":function(date){return leadingNulls(date.tm_mday+__arraySum(__isLeapYear(date.tm_year+1900)?__MONTH_DAYS_LEAP:__MONTH_DAYS_REGULAR,date.tm_mon-1),3)},"%m":function(date){return leadingNulls(date.tm_mon+1,2)},"%M":function(date){return leadingNulls(date.tm_min,2)},"%n":function(){return"\n"},"%p":function(date){if(date.tm_hour>=0&&date.tm_hour<12){return"AM"}else{return"PM"}},"%S":function(date){return leadingNulls(date.tm_sec,2)},"%t":function(){return"\t"},"%u":function(date){return date.tm_wday||7},"%U":function(date){var janFirst=new Date(date.tm_year+1900,0,1);var firstSunday=janFirst.getDay()===0?janFirst:__addDays(janFirst,7-janFirst.getDay());var endDate=new Date(date.tm_year+1900,date.tm_mon,date.tm_mday);if(compareByDay(firstSunday,endDate)<0){var februaryFirstUntilEndMonth=__arraySum(__isLeapYear(endDate.getFullYear())?__MONTH_DAYS_LEAP:__MONTH_DAYS_REGULAR,endDate.getMonth()-1)-31;var firstSundayUntilEndJanuary=31-firstSunday.getDate();var days=firstSundayUntilEndJanuary+februaryFirstUntilEndMonth+endDate.getDate();return leadingNulls(Math.ceil(days/7),2)}return compareByDay(firstSunday,janFirst)===0?"01":"00"},"%V":function(date){var janFourthThisYear=new Date(date.tm_year+1900,0,4);var janFourthNextYear=new Date(date.tm_year+1901,0,4);var firstWeekStartThisYear=getFirstWeekStartDate(janFourthThisYear);var firstWeekStartNextYear=getFirstWeekStartDate(janFourthNextYear);var endDate=__addDays(new Date(date.tm_year+1900,0,1),date.tm_yday);if(compareByDay(endDate,firstWeekStartThisYear)<0){return"53"}if(compareByDay(firstWeekStartNextYear,endDate)<=0){return"01"}var daysDifference;if(firstWeekStartThisYear.getFullYear()=0;off=Math.abs(off)/60;off=off/60*100+off%60;return(ahead?"+":"-")+String("0000"+off).slice(-4)},"%Z":function(date){return date.tm_zone},"%%":function(){return"%"}};for(var rule in EXPANSION_RULES_2){if(pattern.indexOf(rule)>=0){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_2[rule](date))}}var bytes=intArrayFromString(pattern,false);if(bytes.length>maxsize){return 0}writeArrayToMemory(bytes,s);return bytes.length-1}function _strftime_l(s,maxsize,format,tm){return _strftime(s,maxsize,format,tm)}var FSNode=function(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.mounted=null;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.node_ops={};this.stream_ops={};this.rdev=rdev};var readMode=292|73;var writeMode=146;Object.defineProperties(FSNode.prototype,{read:{get:function(){return(this.mode&readMode)===readMode},set:function(val){val?this.mode|=readMode:this.mode&=~readMode}},write:{get:function(){return(this.mode&writeMode)===writeMode},set:function(val){val?this.mode|=writeMode:this.mode&=~writeMode}},isFolder:{get:function(){return FS.isDir(this.mode)}},isDevice:{get:function(){return FS.isChrdev(this.mode)}}});FS.FSNode=FSNode;FS.staticInit();embind_init_charCodes();BindingError=Module["BindingError"]=extendError(Error,"BindingError");InternalError=Module["InternalError"]=extendError(Error,"InternalError");init_emval();UnboundTypeError=Module["UnboundTypeError"]=extendError(Error,"UnboundTypeError");function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}var asmLibraryArg={"a":___assert_fail,"d":___cxa_allocate_exception,"c":___cxa_throw,"q":___map_file,"p":___sys_munmap,"k":__embind_register_bool,"j":__embind_register_emval,"i":__embind_register_float,"t":__embind_register_function,"e":__embind_register_integer,"b":__embind_register_memory_view,"g":__embind_register_std_string,"f":__embind_register_std_wstring,"l":__embind_register_void,"h":_abort,"m":_emscripten_memcpy_big,"n":_emscripten_resize_heap,"r":_environ_get,"s":_environ_sizes_get,"memory":wasmMemory,"o":_strftime_l,"table":wasmTable};var asm=createWasm();Module["asm"]=asm;var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){return(___wasm_call_ctors=Module["___wasm_call_ctors"]=Module["asm"]["u"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return(_malloc=Module["_malloc"]=Module["asm"]["v"]).apply(null,arguments)};var ___getTypeName=Module["___getTypeName"]=function(){return(___getTypeName=Module["___getTypeName"]=Module["asm"]["w"]).apply(null,arguments)};var ___embind_register_native_and_builtin_types=Module["___embind_register_native_and_builtin_types"]=function(){return(___embind_register_native_and_builtin_types=Module["___embind_register_native_and_builtin_types"]=Module["asm"]["x"]).apply(null,arguments)};var ___errno_location=Module["___errno_location"]=function(){return(___errno_location=Module["___errno_location"]=Module["asm"]["y"]).apply(null,arguments)};var _free=Module["_free"]=function(){return(_free=Module["_free"]=Module["asm"]["z"]).apply(null,arguments)};var dynCall_viii=Module["dynCall_viii"]=function(){return(dynCall_viii=Module["dynCall_viii"]=Module["asm"]["A"]).apply(null,arguments)};var dynCall_viiii=Module["dynCall_viiii"]=function(){return(dynCall_viiii=Module["dynCall_viiii"]=Module["asm"]["B"]).apply(null,arguments)};var dynCall_vii=Module["dynCall_vii"]=function(){return(dynCall_vii=Module["dynCall_vii"]=Module["asm"]["C"]).apply(null,arguments)};var dynCall_viiiiii=Module["dynCall_viiiiii"]=function(){return(dynCall_viiiiii=Module["dynCall_viiiiii"]=Module["asm"]["D"]).apply(null,arguments)};var dynCall_viiiiiiii=Module["dynCall_viiiiiiii"]=function(){return(dynCall_viiiiiiii=Module["dynCall_viiiiiiii"]=Module["asm"]["E"]).apply(null,arguments)};var dynCall_viiiiiii=Module["dynCall_viiiiiii"]=function(){return(dynCall_viiiiiii=Module["dynCall_viiiiiii"]=Module["asm"]["F"]).apply(null,arguments)};var dynCall_vi=Module["dynCall_vi"]=function(){return(dynCall_vi=Module["dynCall_vi"]=Module["asm"]["G"]).apply(null,arguments)};var dynCall_iii=Module["dynCall_iii"]=function(){return(dynCall_iii=Module["dynCall_iii"]=Module["asm"]["H"]).apply(null,arguments)};var dynCall_ii=Module["dynCall_ii"]=function(){return(dynCall_ii=Module["dynCall_ii"]=Module["asm"]["I"]).apply(null,arguments)};var dynCall_iiiiii=Module["dynCall_iiiiii"]=function(){return(dynCall_iiiiii=Module["dynCall_iiiiii"]=Module["asm"]["J"]).apply(null,arguments)};var dynCall_viiiii=Module["dynCall_viiiii"]=function(){return(dynCall_viiiii=Module["dynCall_viiiii"]=Module["asm"]["K"]).apply(null,arguments)};var dynCall_iiii=Module["dynCall_iiii"]=function(){return(dynCall_iiii=Module["dynCall_iiii"]=Module["asm"]["L"]).apply(null,arguments)};var dynCall_viijii=Module["dynCall_viijii"]=function(){return(dynCall_viijii=Module["dynCall_viijii"]=Module["asm"]["M"]).apply(null,arguments)};var dynCall_iiiiiii=Module["dynCall_iiiiiii"]=function(){return(dynCall_iiiiiii=Module["dynCall_iiiiiii"]=Module["asm"]["N"]).apply(null,arguments)};var dynCall_iidiiii=Module["dynCall_iidiiii"]=function(){return(dynCall_iidiiii=Module["dynCall_iidiiii"]=Module["asm"]["O"]).apply(null,arguments)};var dynCall_iiiii=Module["dynCall_iiiii"]=function(){return(dynCall_iiiii=Module["dynCall_iiiii"]=Module["asm"]["P"]).apply(null,arguments)};var dynCall_iiiiiiiii=Module["dynCall_iiiiiiiii"]=function(){return(dynCall_iiiiiiiii=Module["dynCall_iiiiiiiii"]=Module["asm"]["Q"]).apply(null,arguments)};var dynCall_iiiiij=Module["dynCall_iiiiij"]=function(){return(dynCall_iiiiij=Module["dynCall_iiiiij"]=Module["asm"]["R"]).apply(null,arguments)};var dynCall_iiiiid=Module["dynCall_iiiiid"]=function(){return(dynCall_iiiiid=Module["dynCall_iiiiid"]=Module["asm"]["S"]).apply(null,arguments)};var dynCall_iiiiijj=Module["dynCall_iiiiijj"]=function(){return(dynCall_iiiiijj=Module["dynCall_iiiiijj"]=Module["asm"]["T"]).apply(null,arguments)};var dynCall_iiiiiiii=Module["dynCall_iiiiiiii"]=function(){return(dynCall_iiiiiiii=Module["dynCall_iiiiiiii"]=Module["asm"]["U"]).apply(null,arguments)};var dynCall_iiiiiijj=Module["dynCall_iiiiiijj"]=function(){return(dynCall_iiiiiijj=Module["dynCall_iiiiiijj"]=Module["asm"]["V"]).apply(null,arguments)};var dynCall_v=Module["dynCall_v"]=function(){return(dynCall_v=Module["dynCall_v"]=Module["asm"]["W"]).apply(null,arguments)};Module["asm"]=asm;var calledRun;function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(args){args=args||arguments_;if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}noExitRuntime=true;run(); +var Module=typeof Module!=="undefined"?Module:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=require("path").dirname(scriptDirectory)+"/"}else{scriptDirectory=__dirname+"/"}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);if(typeof module!=="undefined"){module["exports"]=Module}process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status)};Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)}}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs}else if(typeof arguments!="undefined"){arguments_=arguments}if(typeof quit==="function"){quit_=function(status){quit(status)}}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}setWindowTitle=function(title){document.title=title}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){err("no native wasm support detected")}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":776,"maximum":776+0,"element":"anyfunc"});var ABORT=false;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}var UTF8Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf8"):undefined;function UTF8ArrayToString(heap,idx,maxBytesToRead){var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heap[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heap.subarray&&UTF8Decoder){return UTF8Decoder.decode(heap.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4}return len}var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;function UTF16ToString(ptr,maxBytesToRead){var endPtr=ptr;var idx=endPtr>>1;var maxIdx=idx+maxBytesToRead/2;while(!(idx>=maxIdx)&&HEAPU16[idx])++idx;endPtr=idx<<1;if(endPtr-ptr>32&&UTF16Decoder){return UTF16Decoder.decode(HEAPU8.subarray(ptr,endPtr))}else{var i=0;var str="";while(1){var codeUnit=HEAP16[ptr+i*2>>1];if(codeUnit==0||i==maxBytesToRead/2)return str;++i;str+=String.fromCharCode(codeUnit)}}}function stringToUTF16(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr}function lengthBytesUTF16(str){return str.length*2}function UTF32ToString(ptr,maxBytesToRead){var i=0;var str="";while(!(i>=maxBytesToRead/4)){var utf32=HEAP32[ptr+i*4>>2];if(utf32==0)break;++i;if(utf32>=65536){var ch=utf32-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}else{str+=String.fromCharCode(utf32)}}return str}function stringToUTF32(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i=55296&&codeUnit<=57343){var trailSurrogate=str.charCodeAt(++i);codeUnit=65536+((codeUnit&1023)<<10)|trailSurrogate&1023}HEAP32[outPtr>>2]=codeUnit;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr}function lengthBytesUTF32(str){var len=0;for(var i=0;i=55296&&codeUnit<=57343)++i;len+=4}return len}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}var WASM_PAGE_SIZE=65536;var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var DYNAMIC_BASE=5279872,DYNAMICTOP_PTR=36832;var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"]}else{wasmMemory=new WebAssembly.Memory({"initial":INITIAL_INITIAL_MEMORY/WASM_PAGE_SIZE,"maximum":INITIAL_INITIAL_MEMORY/WASM_PAGE_SIZE})}if(wasmMemory){buffer=wasmMemory.buffer}INITIAL_INITIAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func)}else{Module["dynCall_vi"](func,callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;if(!Module["noFSInit"]&&!FS.init.initialized)FS.init();TTY.init();callRuntimeCallbacks(__ATINIT__)}function preMain(){FS.ignorePermissions=false;callRuntimeCallbacks(__ATMAIN__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var Math_abs=Math.abs;var Math_ceil=Math.ceil;var Math_floor=Math.floor;var Math_min=Math.min;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function getUniqueRunDependency(id){return id}function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+="";out(what);err(what);ABORT=true;EXITSTATUS=1;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";throw new WebAssembly.RuntimeError(what)}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="native.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw"both async and sync fetching of the wasm failed"}}catch(err){abort(err)}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw"failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary())})}function createWasm(){var info={"a":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;removeRunDependency("wasm-instantiate")}addRunDependency("wasm-instantiate");function receiveInstantiatedSource(output){receiveInstance(output["instance"])}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason)})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource)})})}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return{}}var tempDouble;var tempI64;__ATINIT__.push({func:function(){___wasm_call_ctors()}});function demangle(func){return func}function demangleAll(text){var regex=/\b_Z[\w\d_]+/g;return text.replace(regex,function(x){var y=demangle(x);return x===y?x:y+" ["+x+"]"})}function jsStackTrace(){var err=new Error;if(!err.stack){try{throw new Error}catch(e){err=e}if(!err.stack){return"(no stack trace available)"}}return err.stack.toString()}function stackTrace(){var js=jsStackTrace();if(Module["extraStackTrace"])js+="\n"+Module["extraStackTrace"]();return demangleAll(js)}function ___assert_fail(condition,filename,line,func){abort("Assertion failed: "+UTF8ToString(condition)+", at: "+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])}function ___cxa_allocate_exception(size){return _malloc(size)}var ___exception_infos={};var ___exception_last=0;function __ZSt18uncaught_exceptionv(){return __ZSt18uncaught_exceptionv.uncaught_exceptions>0}function ___cxa_throw(ptr,type,destructor){___exception_infos[ptr]={ptr:ptr,adjusted:[ptr],type:type,destructor:destructor,refcount:0,caught:false,rethrown:false};___exception_last=ptr;if(!("uncaught_exception"in __ZSt18uncaught_exceptionv)){__ZSt18uncaught_exceptionv.uncaught_exceptions=1}else{__ZSt18uncaught_exceptionv.uncaught_exceptions++}throw ptr}function setErrNo(value){HEAP32[___errno_location()>>2]=value;return value}function ___map_file(pathname,size){setErrNo(63);return-1}var PATH={splitPath:function(filename){var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:function(parts,allowAboveRoot){var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:function(path){var isAbsolute=path.charAt(0)==="/",trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(function(p){return!!p}),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:function(path){var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:function(path){if(path==="/")return"/";var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},extname:function(path){return PATH.splitPath(path)[3]},join:function(){var paths=Array.prototype.slice.call(arguments,0);return PATH.normalize(paths.join("/"))},join2:function(l,r){return PATH.normalize(l+"/"+r)}};var PATH_FS={resolve:function(){var resolvedPath="",resolvedAbsolute=false;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?arguments[i]:FS.cwd();if(typeof path!=="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=path.charAt(0)==="/"}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter(function(p){return!!p}),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."},relative:function(from,to){from=PATH_FS.resolve(from).substr(1);to=PATH_FS.resolve(to).substr(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i0){result=buf.slice(0,bytesRead).toString("utf-8")}else{result=null}}else if(typeof window!="undefined"&&typeof window.prompt=="function"){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else if(typeof readline=="function"){result=readline();if(result!==null){result+="\n"}}if(!result){return null}tty.input=intArrayFromString(result,true)}return tty.input.shift()},put_char:function(tty,val){if(val===null||val===10){out(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},flush:function(tty){if(tty.output&&tty.output.length>0){out(UTF8ArrayToString(tty.output,0));tty.output=[]}}},default_tty1_ops:{put_char:function(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},flush:function(tty){if(tty.output&&tty.output.length>0){err(UTF8ArrayToString(tty.output,0));tty.output=[]}}}};var MEMFS={ops_table:null,mount:function(mount){return MEMFS.createNode(null,"/",16384|511,0)},createNode:function(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(63)}if(!MEMFS.ops_table){MEMFS.ops_table={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,allocate:MEMFS.stream_ops.allocate,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}}}var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=null}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.timestamp=Date.now();if(parent){parent.contents[name]=node}return node},getFileDataAsRegularArray:function(node){if(node.contents&&node.contents.subarray){var arr=[];for(var i=0;i=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity>>0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0);return},resizeFileStorage:function(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0;return}if(!node.contents||node.contents.subarray){var oldContents=node.contents;node.contents=new Uint8Array(newSize);if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize;return}if(!node.contents)node.contents=[];if(node.contents.length>newSize)node.contents.length=newSize;else while(node.contents.length=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i0||position+length8){throw new FS.ErrnoError(32)}var parts=PATH.normalizeArray(path.split("/").filter(function(p){return!!p}),false);var current=FS.root;var current_path="/";for(var i=0;i40){throw new FS.ErrnoError(32)}}}}return{path:current_path,node:current}},getPath:function(node){var path;while(true){if(FS.isRoot(node)){var mount=node.mount.mountpoint;if(!path)return mount;return mount[mount.length-1]!=="/"?mount+"/"+path:mount+path}path=path?node.name+"/"+path:node.name;node=node.parent}},hashName:function(parentid,name){var hash=0;for(var i=0;i>>0)%FS.nameTable.length},hashAddNode:function(node){var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode:function(node){var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode:function(parent,name){var errCode=FS.mayLookup(parent);if(errCode){throw new FS.ErrnoError(errCode,parent)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode:function(parent,name,mode,rdev){var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode:function(node){FS.hashRemoveNode(node)},isRoot:function(node){return node===node.parent},isMountpoint:function(node){return!!node.mounted},isFile:function(mode){return(mode&61440)===32768},isDir:function(mode){return(mode&61440)===16384},isLink:function(mode){return(mode&61440)===40960},isChrdev:function(mode){return(mode&61440)===8192},isBlkdev:function(mode){return(mode&61440)===24576},isFIFO:function(mode){return(mode&61440)===4096},isSocket:function(mode){return(mode&49152)===49152},flagModes:{"r":0,"rs":1052672,"r+":2,"w":577,"wx":705,"xw":705,"w+":578,"wx+":706,"xw+":706,"a":1089,"ax":1217,"xa":1217,"a+":1090,"ax+":1218,"xa+":1218},modeStringToFlags:function(str){var flags=FS.flagModes[str];if(typeof flags==="undefined"){throw new Error("Unknown file open mode: "+str)}return flags},flagsToPermissionString:function(flag){var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms},nodePermissions:function(node,perms){if(FS.ignorePermissions){return 0}if(perms.indexOf("r")!==-1&&!(node.mode&292)){return 2}else if(perms.indexOf("w")!==-1&&!(node.mode&146)){return 2}else if(perms.indexOf("x")!==-1&&!(node.mode&73)){return 2}return 0},mayLookup:function(dir){var errCode=FS.nodePermissions(dir,"x");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate:function(dir,name){try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,"wx")},mayDelete:function(dir,name,isdir){var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var errCode=FS.nodePermissions(dir,"wx");if(errCode){return errCode}if(isdir){if(!FS.isDir(node.mode)){return 54}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 10}}else{if(FS.isDir(node.mode)){return 31}}return 0},mayOpen:function(node,flags){if(!node){return 44}if(FS.isLink(node.mode)){return 32}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!=="r"||flags&512){return 31}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))},MAX_OPEN_FDS:4096,nextfd:function(fd_start,fd_end){fd_start=fd_start||0;fd_end=fd_end||FS.MAX_OPEN_FDS;for(var fd=fd_start;fd<=fd_end;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStream:function(fd){return FS.streams[fd]},createStream:function(stream,fd_start,fd_end){if(!FS.FSStream){FS.FSStream=function(){};FS.FSStream.prototype={object:{get:function(){return this.node},set:function(val){this.node=val}},isRead:{get:function(){return(this.flags&2097155)!==1}},isWrite:{get:function(){return(this.flags&2097155)!==0}},isAppend:{get:function(){return this.flags&1024}}}}var newStream=new FS.FSStream;for(var p in stream){newStream[p]=stream[p]}stream=newStream;var fd=FS.nextfd(fd_start,fd_end);stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream:function(fd){FS.streams[fd]=null},chrdev_stream_ops:{open:function(stream){var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;if(stream.stream_ops.open){stream.stream_ops.open(stream)}},llseek:function(){throw new FS.ErrnoError(70)}},major:function(dev){return dev>>8},minor:function(dev){return dev&255},makedev:function(ma,mi){return ma<<8|mi},registerDevice:function(dev,ops){FS.devices[dev]={stream_ops:ops}},getDevice:function(dev){return FS.devices[dev]},getMounts:function(mount){var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push.apply(check,m.mounts)}return mounts},syncfs:function(populate,callback){if(typeof populate==="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){err("warning: "+FS.syncFSRequests+" FS.syncfs operations in flight at once, probably just doing extra work")}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(errCode){FS.syncFSRequests--;return callback(errCode)}function done(errCode){if(errCode){if(!done.errored){done.errored=true;return doCallback(errCode)}return}if(++completed>=mounts.length){doCallback(null)}}mounts.forEach(function(mount){if(!mount.type.syncfs){return done(null)}mount.type.syncfs(mount,populate,done)})},mount:function(type,opts,mountpoint){var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(10)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}}var mount={type:type,opts:opts,mountpoint:mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount:function(mountpoint){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);Object.keys(FS.nameTable).forEach(function(hash){var current=FS.nameTable[hash];while(current){var next=current.name_next;if(mounts.indexOf(current.mount)!==-1){FS.destroyNode(current)}current=next}});node.mounted=null;var idx=node.mount.mounts.indexOf(mount);node.mount.mounts.splice(idx,1)},lookup:function(parent,name){return parent.node_ops.lookup(parent,name)},mknod:function(path,mode,dev){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name||name==="."||name===".."){throw new FS.ErrnoError(28)}var errCode=FS.mayCreate(parent,name);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(63)}return parent.node_ops.mknod(parent,name,mode,dev)},create:function(path,mode){mode=mode!==undefined?mode:438;mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir:function(path,mode){mode=mode!==undefined?mode:511;mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree:function(path,mode){var dirs=path.split("/");var d="";for(var i=0;ithis.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]};LazyUint8Array.prototype.setDataGetter=function LazyUint8Array_setDataGetter(getter){this.getter=getter};LazyUint8Array.prototype.cacheLength=function LazyUint8Array_cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=function(from,to){if(from>to)throw new Error("invalid range ("+from+", "+to+") or no bytes requested!");if(to>datalength-1)throw new Error("only "+datalength+" bytes available! programmer error!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);if(typeof Uint8Array!="undefined")xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}else{return intArrayFromString(xhr.responseText||"",true)}};var lazyArray=this;lazyArray.setDataGetter(function(chunkNum){var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]==="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]==="undefined")throw new Error("doXHR failed!");return lazyArray.chunks[chunkNum]});if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;out("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true};if(typeof XMLHttpRequest!=="undefined"){if(!ENVIRONMENT_IS_WORKER)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";var lazyArray=new LazyUint8Array;Object.defineProperties(lazyArray,{length:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._length}},chunkSize:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}});var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url:url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};var keys=Object.keys(node.stream_ops);keys.forEach(function(key){var fn=node.stream_ops[key];stream_ops[key]=function forceLoadLazyFile(){if(!FS.forceLoadFile(node)){throw new FS.ErrnoError(29)}return fn.apply(null,arguments)}});stream_ops.read=function stream_ops_read(stream,buffer,offset,length,position){if(!FS.forceLoadFile(node)){throw new FS.ErrnoError(29)}var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);if(contents.slice){for(var i=0;i>2]=stat.dev;HEAP32[buf+4>>2]=0;HEAP32[buf+8>>2]=stat.ino;HEAP32[buf+12>>2]=stat.mode;HEAP32[buf+16>>2]=stat.nlink;HEAP32[buf+20>>2]=stat.uid;HEAP32[buf+24>>2]=stat.gid;HEAP32[buf+28>>2]=stat.rdev;HEAP32[buf+32>>2]=0;tempI64=[stat.size>>>0,(tempDouble=stat.size,+Math_abs(tempDouble)>=1?tempDouble>0?(Math_min(+Math_floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+40>>2]=tempI64[0],HEAP32[buf+44>>2]=tempI64[1];HEAP32[buf+48>>2]=4096;HEAP32[buf+52>>2]=stat.blocks;HEAP32[buf+56>>2]=stat.atime.getTime()/1e3|0;HEAP32[buf+60>>2]=0;HEAP32[buf+64>>2]=stat.mtime.getTime()/1e3|0;HEAP32[buf+68>>2]=0;HEAP32[buf+72>>2]=stat.ctime.getTime()/1e3|0;HEAP32[buf+76>>2]=0;tempI64=[stat.ino>>>0,(tempDouble=stat.ino,+Math_abs(tempDouble)>=1?tempDouble>0?(Math_min(+Math_floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+80>>2]=tempI64[0],HEAP32[buf+84>>2]=tempI64[1];return 0},doMsync:function(addr,stream,len,flags,offset){var buffer=HEAPU8.slice(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},doMkdir:function(path,mode){path=PATH.normalize(path);if(path[path.length-1]==="/")path=path.substr(0,path.length-1);FS.mkdir(path,mode,0);return 0},doMknod:function(path,mode,dev){switch(mode&61440){case 32768:case 8192:case 24576:case 4096:case 49152:break;default:return-28}FS.mknod(path,mode,dev);return 0},doReadlink:function(path,buf,bufsize){if(bufsize<=0)return-28;var ret=FS.readlink(path);var len=Math.min(bufsize,lengthBytesUTF8(ret));var endChar=HEAP8[buf+len];stringToUTF8(ret,buf,bufsize+1);HEAP8[buf+len]=endChar;return len},doAccess:function(path,amode){if(amode&~7){return-28}var node;var lookup=FS.lookupPath(path,{follow:true});node=lookup.node;if(!node){return-44}var perms="";if(amode&4)perms+="r";if(amode&2)perms+="w";if(amode&1)perms+="x";if(perms&&FS.nodePermissions(node,perms)){return-2}return 0},doDup:function(path,flags,suggestFD){var suggest=FS.getStream(suggestFD);if(suggest)FS.close(suggest);return FS.open(path,flags,0,suggestFD,suggestFD).fd},doReadv:function(stream,iov,iovcnt,offset){var ret=0;for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2];var len=HEAP32[iov+(i*8+4)>>2];var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr}return ret},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},getStreamFromFD:function(fd){var stream=FS.getStream(fd);if(!stream)throw new FS.ErrnoError(8);return stream},get64:function(low,high){return low}};function syscallMunmap(addr,len){if((addr|0)===-1||len===0){return-28}var info=SYSCALLS.mappings[addr];if(!info)return 0;if(len===info.len){var stream=FS.getStream(info.fd);if(info.prot&2){SYSCALLS.doMsync(addr,stream,len,info.flags,info.offset)}FS.munmap(stream);SYSCALLS.mappings[addr]=null;if(info.allocated){_free(info.malloc)}}return 0}function ___sys_munmap(addr,len){try{return syscallMunmap(addr,len)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function getShiftFromSize(size){switch(size){case 1:return 0;case 2:return 1;case 4:return 2;case 8:return 3;default:throw new TypeError("Unknown type size: "+size)}}function embind_init_charCodes(){var codes=new Array(256);for(var i=0;i<256;++i){codes[i]=String.fromCharCode(i)}embind_charCodes=codes}var embind_charCodes=undefined;function readLatin1String(ptr){var ret="";var c=ptr;while(HEAPU8[c]){ret+=embind_charCodes[HEAPU8[c++]]}return ret}var awaitingDependencies={};var registeredTypes={};var typeDependencies={};var char_0=48;var char_9=57;function makeLegalFunctionName(name){if(undefined===name){return"_unknown"}name=name.replace(/[^a-zA-Z0-9_]/g,"$");var f=name.charCodeAt(0);if(f>=char_0&&f<=char_9){return"_"+name}else{return name}}function createNamedFunction(name,body){name=makeLegalFunctionName(name);return new Function("body","return function "+name+"() {\n"+' "use strict";'+" return body.apply(this, arguments);\n"+"};\n")(body)}function extendError(baseErrorType,errorName){var errorClass=createNamedFunction(errorName,function(message){this.name=errorName;this.message=message;var stack=new Error(message).stack;if(stack!==undefined){this.stack=this.toString()+"\n"+stack.replace(/^Error(:[^\n]*)?\n/,"")}});errorClass.prototype=Object.create(baseErrorType.prototype);errorClass.prototype.constructor=errorClass;errorClass.prototype.toString=function(){if(this.message===undefined){return this.name}else{return this.name+": "+this.message}};return errorClass}var BindingError=undefined;function throwBindingError(message){throw new BindingError(message)}var InternalError=undefined;function throwInternalError(message){throw new InternalError(message)}function whenDependentTypesAreResolved(myTypes,dependentTypes,getTypeConverters){myTypes.forEach(function(type){typeDependencies[type]=dependentTypes});function onComplete(typeConverters){var myTypeConverters=getTypeConverters(typeConverters);if(myTypeConverters.length!==myTypes.length){throwInternalError("Mismatched type converter count")}for(var i=0;i>shift])},destructorFunction:null})}var emval_free_list=[];var emval_handle_array=[{},{value:undefined},{value:null},{value:true},{value:false}];function __emval_decref(handle){if(handle>4&&0===--emval_handle_array[handle].refcount){emval_handle_array[handle]=undefined;emval_free_list.push(handle)}}function count_emval_handles(){var count=0;for(var i=5;i>2])}function __embind_register_emval(rawType,name){name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":function(handle){var rv=emval_handle_array[handle].value;__emval_decref(handle);return rv},"toWireType":function(destructors,value){return __emval_register(value)},"argPackAdvance":8,"readValueFromPointer":simpleReadValueFromPointer,destructorFunction:null})}function _embind_repr(v){if(v===null){return"null"}var t=typeof v;if(t==="object"||t==="array"||t==="function"){return v.toString()}else{return""+v}}function floatReadValueFromPointer(name,shift){switch(shift){case 2:return function(pointer){return this["fromWireType"](HEAPF32[pointer>>2])};case 3:return function(pointer){return this["fromWireType"](HEAPF64[pointer>>3])};default:throw new TypeError("Unknown float type: "+name)}}function __embind_register_float(rawType,name,size){var shift=getShiftFromSize(size);name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":function(value){return value},"toWireType":function(destructors,value){if(typeof value!=="number"&&typeof value!=="boolean"){throw new TypeError('Cannot convert "'+_embind_repr(value)+'" to '+this.name)}return value},"argPackAdvance":8,"readValueFromPointer":floatReadValueFromPointer(name,shift),destructorFunction:null})}function new_(constructor,argumentList){if(!(constructor instanceof Function)){throw new TypeError("new_ called with constructor type "+typeof constructor+" which is not a function")}var dummy=createNamedFunction(constructor.name||"unknownFunctionName",function(){});dummy.prototype=constructor.prototype;var obj=new dummy;var r=constructor.apply(obj,argumentList);return r instanceof Object?r:obj}function runDestructors(destructors){while(destructors.length){var ptr=destructors.pop();var del=destructors.pop();del(ptr)}}function craftInvokerFunction(humanName,argTypes,classType,cppInvokerFunc,cppTargetFunc){var argCount=argTypes.length;if(argCount<2){throwBindingError("argTypes array size mismatch! Must at least get return value and 'this' types!")}var isClassMethodFunc=argTypes[1]!==null&&classType!==null;var needsDestructorStack=false;for(var i=1;i0?", ":"")+argsListWired}invokerFnBody+=(returns?"var rv = ":"")+"invoker(fn"+(argsListWired.length>0?", ":"")+argsListWired+");\n";if(needsDestructorStack){invokerFnBody+="runDestructors(destructors);\n"}else{for(var i=isClassMethodFunc?1:2;i>2)+i])}return array}function replacePublicSymbol(name,value,numArguments){if(!Module.hasOwnProperty(name)){throwInternalError("Replacing nonexistant public symbol")}if(undefined!==Module[name].overloadTable&&undefined!==numArguments){Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}}function embind__requireFunction(signature,rawFunction){signature=readLatin1String(signature);function makeDynCaller(dynCall){var args=[];for(var i=1;i>1]}:function readU16FromPointer(pointer){return HEAPU16[pointer>>1]};case 2:return signed?function readS32FromPointer(pointer){return HEAP32[pointer>>2]}:function readU32FromPointer(pointer){return HEAPU32[pointer>>2]};default:throw new TypeError("Unknown integer type: "+name)}}function __embind_register_integer(primitiveType,name,size,minRange,maxRange){name=readLatin1String(name);if(maxRange===-1){maxRange=4294967295}var shift=getShiftFromSize(size);var fromWireType=function(value){return value};if(minRange===0){var bitshift=32-8*size;fromWireType=function(value){return value<>>bitshift}}var isUnsignedType=name.indexOf("unsigned")!=-1;registerType(primitiveType,{name:name,"fromWireType":fromWireType,"toWireType":function(destructors,value){if(typeof value!=="number"&&typeof value!=="boolean"){throw new TypeError('Cannot convert "'+_embind_repr(value)+'" to '+this.name)}if(valuemaxRange){throw new TypeError('Passing a number "'+_embind_repr(value)+'" from JS side to C/C++ side to an argument of type "'+name+'", which is outside the valid range ['+minRange+", "+maxRange+"]!")}return isUnsignedType?value>>>0:value|0},"argPackAdvance":8,"readValueFromPointer":integerReadValueFromPointer(name,shift,minRange!==0),destructorFunction:null})}function __embind_register_memory_view(rawType,dataTypeIndex,name){var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){handle=handle>>2;var heap=HEAPU32;var size=heap[handle];var data=heap[handle+1];return new TA(buffer,data,size)}name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":decodeMemoryView,"argPackAdvance":8,"readValueFromPointer":decodeMemoryView},{ignoreDuplicateRegistrations:true})}function __embind_register_std_string(rawType,name){name=readLatin1String(name);var stdStringIsUTF8=name==="std::string";registerType(rawType,{name:name,"fromWireType":function(value){var length=HEAPU32[value>>2];var str;if(stdStringIsUTF8){var decodeStartPtr=value+4;for(var i=0;i<=length;++i){var currentBytePtr=value+4+i;if(HEAPU8[currentBytePtr]==0||i==length){var maxRead=currentBytePtr-decodeStartPtr;var stringSegment=UTF8ToString(decodeStartPtr,maxRead);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+1}}}else{var a=new Array(length);for(var i=0;i>2]=length;if(stdStringIsUTF8&&valueIsOfTypeString){stringToUTF8(value,ptr+4,length+1)}else{if(valueIsOfTypeString){for(var i=0;i255){_free(ptr);throwBindingError("String has UTF-16 code units that do not fit in 8 bits")}HEAPU8[ptr+4+i]=charCode}}else{for(var i=0;i>2];var HEAP=getHeap();var str;var decodeStartPtr=value+4;for(var i=0;i<=length;++i){var currentBytePtr=value+4+i*charSize;if(HEAP[currentBytePtr>>shift]==0||i==length){var maxReadBytes=currentBytePtr-decodeStartPtr;var stringSegment=decodeString(decodeStartPtr,maxReadBytes);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+charSize}}_free(value);return str},"toWireType":function(destructors,value){if(!(typeof value==="string")){throwBindingError("Cannot pass non-string to C++ string type "+name)}var length=lengthBytesUTF(value);var ptr=_malloc(4+length+charSize);HEAPU32[ptr>>2]=length>>shift;encodeString(value,ptr+4,length+charSize);if(destructors!==null){destructors.push(_free,ptr)}return ptr},"argPackAdvance":8,"readValueFromPointer":simpleReadValueFromPointer,destructorFunction:function(ptr){_free(ptr)}})}function __embind_register_void(rawType,name){name=readLatin1String(name);registerType(rawType,{isVoid:true,name:name,"argPackAdvance":0,"fromWireType":function(){return undefined},"toWireType":function(destructors,o){return undefined}})}function _abort(){abort()}function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src,src+num)}function abortOnCannotGrowMemory(requestedSize){abort("OOM")}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;abortOnCannotGrowMemory(requestedSize)}var ENV={};function __getExecutableName(){return thisProgram||"./this.program"}function getEnvStrings(){if(!getEnvStrings.strings){var env={"USER":"web_user","LOGNAME":"web_user","PATH":"/","PWD":"/","HOME":"/home/web_user","LANG":(typeof navigator==="object"&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8","_":__getExecutableName()};for(var x in ENV){env[x]=ENV[x]}var strings=[];for(var x in env){strings.push(x+"="+env[x])}getEnvStrings.strings=strings}return getEnvStrings.strings}function _environ_get(__environ,environ_buf){var bufSize=0;getEnvStrings().forEach(function(string,i){var ptr=environ_buf+bufSize;HEAP32[__environ+i*4>>2]=ptr;writeAsciiToMemory(string,ptr);bufSize+=string.length+1});return 0}function _environ_sizes_get(penviron_count,penviron_buf_size){var strings=getEnvStrings();HEAP32[penviron_count>>2]=strings.length;var bufSize=0;strings.forEach(function(string){bufSize+=string.length+1});HEAP32[penviron_buf_size>>2]=bufSize;return 0}function __isLeapYear(year){return year%4===0&&(year%100!==0||year%400===0)}function __arraySum(array,index){var sum=0;for(var i=0;i<=index;sum+=array[i++]){}return sum}var __MONTH_DAYS_LEAP=[31,29,31,30,31,30,31,31,30,31,30,31];var __MONTH_DAYS_REGULAR=[31,28,31,30,31,30,31,31,30,31,30,31];function __addDays(date,days){var newDate=new Date(date.getTime());while(days>0){var leap=__isLeapYear(newDate.getFullYear());var currentMonth=newDate.getMonth();var daysInCurrentMonth=(leap?__MONTH_DAYS_LEAP:__MONTH_DAYS_REGULAR)[currentMonth];if(days>daysInCurrentMonth-newDate.getDate()){days-=daysInCurrentMonth-newDate.getDate()+1;newDate.setDate(1);if(currentMonth<11){newDate.setMonth(currentMonth+1)}else{newDate.setMonth(0);newDate.setFullYear(newDate.getFullYear()+1)}}else{newDate.setDate(newDate.getDate()+days);return newDate}}return newDate}function _strftime(s,maxsize,format,tm){var tm_zone=HEAP32[tm+40>>2];var date={tm_sec:HEAP32[tm>>2],tm_min:HEAP32[tm+4>>2],tm_hour:HEAP32[tm+8>>2],tm_mday:HEAP32[tm+12>>2],tm_mon:HEAP32[tm+16>>2],tm_year:HEAP32[tm+20>>2],tm_wday:HEAP32[tm+24>>2],tm_yday:HEAP32[tm+28>>2],tm_isdst:HEAP32[tm+32>>2],tm_gmtoff:HEAP32[tm+36>>2],tm_zone:tm_zone?UTF8ToString(tm_zone):""};var pattern=UTF8ToString(format);var EXPANSION_RULES_1={"%c":"%a %b %d %H:%M:%S %Y","%D":"%m/%d/%y","%F":"%Y-%m-%d","%h":"%b","%r":"%I:%M:%S %p","%R":"%H:%M","%T":"%H:%M:%S","%x":"%m/%d/%y","%X":"%H:%M:%S","%Ec":"%c","%EC":"%C","%Ex":"%m/%d/%y","%EX":"%H:%M:%S","%Ey":"%y","%EY":"%Y","%Od":"%d","%Oe":"%e","%OH":"%H","%OI":"%I","%Om":"%m","%OM":"%M","%OS":"%S","%Ou":"%u","%OU":"%U","%OV":"%V","%Ow":"%w","%OW":"%W","%Oy":"%y"};for(var rule in EXPANSION_RULES_1){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_1[rule])}var WEEKDAYS=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];var MONTHS=["January","February","March","April","May","June","July","August","September","October","November","December"];function leadingSomething(value,digits,character){var str=typeof value==="number"?value.toString():value||"";while(str.length0?1:0}var compare;if((compare=sgn(date1.getFullYear()-date2.getFullYear()))===0){if((compare=sgn(date1.getMonth()-date2.getMonth()))===0){compare=sgn(date1.getDate()-date2.getDate())}}return compare}function getFirstWeekStartDate(janFourth){switch(janFourth.getDay()){case 0:return new Date(janFourth.getFullYear()-1,11,29);case 1:return janFourth;case 2:return new Date(janFourth.getFullYear(),0,3);case 3:return new Date(janFourth.getFullYear(),0,2);case 4:return new Date(janFourth.getFullYear(),0,1);case 5:return new Date(janFourth.getFullYear()-1,11,31);case 6:return new Date(janFourth.getFullYear()-1,11,30)}}function getWeekBasedYear(date){var thisDate=__addDays(new Date(date.tm_year+1900,0,1),date.tm_yday);var janFourthThisYear=new Date(thisDate.getFullYear(),0,4);var janFourthNextYear=new Date(thisDate.getFullYear()+1,0,4);var firstWeekStartThisYear=getFirstWeekStartDate(janFourthThisYear);var firstWeekStartNextYear=getFirstWeekStartDate(janFourthNextYear);if(compareByDay(firstWeekStartThisYear,thisDate)<=0){if(compareByDay(firstWeekStartNextYear,thisDate)<=0){return thisDate.getFullYear()+1}else{return thisDate.getFullYear()}}else{return thisDate.getFullYear()-1}}var EXPANSION_RULES_2={"%a":function(date){return WEEKDAYS[date.tm_wday].substring(0,3)},"%A":function(date){return WEEKDAYS[date.tm_wday]},"%b":function(date){return MONTHS[date.tm_mon].substring(0,3)},"%B":function(date){return MONTHS[date.tm_mon]},"%C":function(date){var year=date.tm_year+1900;return leadingNulls(year/100|0,2)},"%d":function(date){return leadingNulls(date.tm_mday,2)},"%e":function(date){return leadingSomething(date.tm_mday,2," ")},"%g":function(date){return getWeekBasedYear(date).toString().substring(2)},"%G":function(date){return getWeekBasedYear(date)},"%H":function(date){return leadingNulls(date.tm_hour,2)},"%I":function(date){var twelveHour=date.tm_hour;if(twelveHour==0)twelveHour=12;else if(twelveHour>12)twelveHour-=12;return leadingNulls(twelveHour,2)},"%j":function(date){return leadingNulls(date.tm_mday+__arraySum(__isLeapYear(date.tm_year+1900)?__MONTH_DAYS_LEAP:__MONTH_DAYS_REGULAR,date.tm_mon-1),3)},"%m":function(date){return leadingNulls(date.tm_mon+1,2)},"%M":function(date){return leadingNulls(date.tm_min,2)},"%n":function(){return"\n"},"%p":function(date){if(date.tm_hour>=0&&date.tm_hour<12){return"AM"}else{return"PM"}},"%S":function(date){return leadingNulls(date.tm_sec,2)},"%t":function(){return"\t"},"%u":function(date){return date.tm_wday||7},"%U":function(date){var janFirst=new Date(date.tm_year+1900,0,1);var firstSunday=janFirst.getDay()===0?janFirst:__addDays(janFirst,7-janFirst.getDay());var endDate=new Date(date.tm_year+1900,date.tm_mon,date.tm_mday);if(compareByDay(firstSunday,endDate)<0){var februaryFirstUntilEndMonth=__arraySum(__isLeapYear(endDate.getFullYear())?__MONTH_DAYS_LEAP:__MONTH_DAYS_REGULAR,endDate.getMonth()-1)-31;var firstSundayUntilEndJanuary=31-firstSunday.getDate();var days=firstSundayUntilEndJanuary+februaryFirstUntilEndMonth+endDate.getDate();return leadingNulls(Math.ceil(days/7),2)}return compareByDay(firstSunday,janFirst)===0?"01":"00"},"%V":function(date){var janFourthThisYear=new Date(date.tm_year+1900,0,4);var janFourthNextYear=new Date(date.tm_year+1901,0,4);var firstWeekStartThisYear=getFirstWeekStartDate(janFourthThisYear);var firstWeekStartNextYear=getFirstWeekStartDate(janFourthNextYear);var endDate=__addDays(new Date(date.tm_year+1900,0,1),date.tm_yday);if(compareByDay(endDate,firstWeekStartThisYear)<0){return"53"}if(compareByDay(firstWeekStartNextYear,endDate)<=0){return"01"}var daysDifference;if(firstWeekStartThisYear.getFullYear()=0;off=Math.abs(off)/60;off=off/60*100+off%60;return(ahead?"+":"-")+String("0000"+off).slice(-4)},"%Z":function(date){return date.tm_zone},"%%":function(){return"%"}};for(var rule in EXPANSION_RULES_2){if(pattern.indexOf(rule)>=0){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_2[rule](date))}}var bytes=intArrayFromString(pattern,false);if(bytes.length>maxsize){return 0}writeArrayToMemory(bytes,s);return bytes.length-1}function _strftime_l(s,maxsize,format,tm){return _strftime(s,maxsize,format,tm)}var FSNode=function(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.mounted=null;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.node_ops={};this.stream_ops={};this.rdev=rdev};var readMode=292|73;var writeMode=146;Object.defineProperties(FSNode.prototype,{read:{get:function(){return(this.mode&readMode)===readMode},set:function(val){val?this.mode|=readMode:this.mode&=~readMode}},write:{get:function(){return(this.mode&writeMode)===writeMode},set:function(val){val?this.mode|=writeMode:this.mode&=~writeMode}},isFolder:{get:function(){return FS.isDir(this.mode)}},isDevice:{get:function(){return FS.isChrdev(this.mode)}}});FS.FSNode=FSNode;FS.staticInit();embind_init_charCodes();BindingError=Module["BindingError"]=extendError(Error,"BindingError");InternalError=Module["InternalError"]=extendError(Error,"InternalError");init_emval();UnboundTypeError=Module["UnboundTypeError"]=extendError(Error,"UnboundTypeError");function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}var asmLibraryArg={"b":___assert_fail,"e":___cxa_allocate_exception,"d":___cxa_throw,"q":___map_file,"p":___sys_munmap,"k":__embind_register_bool,"j":__embind_register_emval,"i":__embind_register_float,"t":__embind_register_function,"c":__embind_register_integer,"a":__embind_register_memory_view,"g":__embind_register_std_string,"f":__embind_register_std_wstring,"l":__embind_register_void,"h":_abort,"m":_emscripten_memcpy_big,"n":_emscripten_resize_heap,"r":_environ_get,"s":_environ_sizes_get,"memory":wasmMemory,"o":_strftime_l,"table":wasmTable};var asm=createWasm();Module["asm"]=asm;var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){return(___wasm_call_ctors=Module["___wasm_call_ctors"]=Module["asm"]["u"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return(_malloc=Module["_malloc"]=Module["asm"]["v"]).apply(null,arguments)};var ___getTypeName=Module["___getTypeName"]=function(){return(___getTypeName=Module["___getTypeName"]=Module["asm"]["w"]).apply(null,arguments)};var ___embind_register_native_and_builtin_types=Module["___embind_register_native_and_builtin_types"]=function(){return(___embind_register_native_and_builtin_types=Module["___embind_register_native_and_builtin_types"]=Module["asm"]["x"]).apply(null,arguments)};var ___errno_location=Module["___errno_location"]=function(){return(___errno_location=Module["___errno_location"]=Module["asm"]["y"]).apply(null,arguments)};var _free=Module["_free"]=function(){return(_free=Module["_free"]=Module["asm"]["z"]).apply(null,arguments)};var dynCall_viiii=Module["dynCall_viiii"]=function(){return(dynCall_viiii=Module["dynCall_viiii"]=Module["asm"]["A"]).apply(null,arguments)};var dynCall_iiiiii=Module["dynCall_iiiiii"]=function(){return(dynCall_iiiiii=Module["dynCall_iiiiii"]=Module["asm"]["B"]).apply(null,arguments)};var dynCall_vii=Module["dynCall_vii"]=function(){return(dynCall_vii=Module["dynCall_vii"]=Module["asm"]["C"]).apply(null,arguments)};var dynCall_viiiiii=Module["dynCall_viiiiii"]=function(){return(dynCall_viiiiii=Module["dynCall_viiiiii"]=Module["asm"]["D"]).apply(null,arguments)};var dynCall_viiiiiiii=Module["dynCall_viiiiiiii"]=function(){return(dynCall_viiiiiiii=Module["dynCall_viiiiiiii"]=Module["asm"]["E"]).apply(null,arguments)};var dynCall_viiiiiii=Module["dynCall_viiiiiii"]=function(){return(dynCall_viiiiiii=Module["dynCall_viiiiiii"]=Module["asm"]["F"]).apply(null,arguments)};var dynCall_vi=Module["dynCall_vi"]=function(){return(dynCall_vi=Module["dynCall_vi"]=Module["asm"]["G"]).apply(null,arguments)};var dynCall_ii=Module["dynCall_ii"]=function(){return(dynCall_ii=Module["dynCall_ii"]=Module["asm"]["H"]).apply(null,arguments)};var dynCall_viiiii=Module["dynCall_viiiii"]=function(){return(dynCall_viiiii=Module["dynCall_viiiii"]=Module["asm"]["I"]).apply(null,arguments)};var dynCall_iiii=Module["dynCall_iiii"]=function(){return(dynCall_iiii=Module["dynCall_iiii"]=Module["asm"]["J"]).apply(null,arguments)};var dynCall_viijii=Module["dynCall_viijii"]=function(){return(dynCall_viijii=Module["dynCall_viijii"]=Module["asm"]["K"]).apply(null,arguments)};var dynCall_iii=Module["dynCall_iii"]=function(){return(dynCall_iii=Module["dynCall_iii"]=Module["asm"]["L"]).apply(null,arguments)};var dynCall_iiiiiii=Module["dynCall_iiiiiii"]=function(){return(dynCall_iiiiiii=Module["dynCall_iiiiiii"]=Module["asm"]["M"]).apply(null,arguments)};var dynCall_iidiiii=Module["dynCall_iidiiii"]=function(){return(dynCall_iidiiii=Module["dynCall_iidiiii"]=Module["asm"]["N"]).apply(null,arguments)};var dynCall_iiiii=Module["dynCall_iiiii"]=function(){return(dynCall_iiiii=Module["dynCall_iiiii"]=Module["asm"]["O"]).apply(null,arguments)};var dynCall_iiiiiiiii=Module["dynCall_iiiiiiiii"]=function(){return(dynCall_iiiiiiiii=Module["dynCall_iiiiiiiii"]=Module["asm"]["P"]).apply(null,arguments)};var dynCall_iiiiij=Module["dynCall_iiiiij"]=function(){return(dynCall_iiiiij=Module["dynCall_iiiiij"]=Module["asm"]["Q"]).apply(null,arguments)};var dynCall_iiiiid=Module["dynCall_iiiiid"]=function(){return(dynCall_iiiiid=Module["dynCall_iiiiid"]=Module["asm"]["R"]).apply(null,arguments)};var dynCall_iiiiijj=Module["dynCall_iiiiijj"]=function(){return(dynCall_iiiiijj=Module["dynCall_iiiiijj"]=Module["asm"]["S"]).apply(null,arguments)};var dynCall_iiiiiiii=Module["dynCall_iiiiiiii"]=function(){return(dynCall_iiiiiiii=Module["dynCall_iiiiiiii"]=Module["asm"]["T"]).apply(null,arguments)};var dynCall_iiiiiijj=Module["dynCall_iiiiiijj"]=function(){return(dynCall_iiiiiijj=Module["dynCall_iiiiiijj"]=Module["asm"]["U"]).apply(null,arguments)};var dynCall_v=Module["dynCall_v"]=function(){return(dynCall_v=Module["dynCall_v"]=Module["asm"]["V"]).apply(null,arguments)};Module["asm"]=asm;var calledRun;function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(args){args=args||arguments_;if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}noExitRuntime=true;run(); diff --git a/docs/native.wasm b/docs/native.wasm index 7af8445db984f81680b270253679980e4b784297..2f0b1c3b7c8809df757fd394f5c455b7907a4a4e 100644 GIT binary patch delta 91849 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 k9RE!6Suj%fpQ!o(^b diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 7669594..2c6aef2 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -1,13 +1,9 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 3.1) project(example) include_directories(..) -if(MSVC) - add_compile_options(${cxx11_options} /W3) -else() - add_compile_options(${cxx11_options}) -endif() +set(CMAKE_CXX_STANDARD 17) add_executable(calc calc.cc) target_link_libraries(calc ${add_link_deps}) diff --git a/example/calc.cc b/example/calc.cc index 6de3dd0..686aee7 100644 --- a/example/calc.cc +++ b/example/calc.cc @@ -1,13 +1,13 @@ -#include #include #include +#include using namespace peg; using namespace std; int main(void) { - // (2) Make a parser - parser parser(R"( + // (2) Make a parser + parser parser(R"( # Grammar for Calculator... Additive <- Multitive '+' Additive / Multitive Multitive <- Primary '*' Multitive / Primary @@ -16,36 +16,36 @@ int main(void) { %whitespace <- [ \t]* )"); - assert(static_cast(parser) == true); - - // (3) Setup actions - parser["Additive"] = [](const SemanticValues& sv) { - switch (sv.choice()) { - case 0: // "Multitive '+' Additive" - return any_cast(sv[0]) + any_cast(sv[1]); - default: // "Multitive" - return any_cast(sv[0]); - } - }; - - parser["Multitive"] = [](const SemanticValues& sv) { - switch (sv.choice()) { - case 0: // "Primary '*' Multitive" - return any_cast(sv[0]) * any_cast(sv[1]); - default: // "Primary" - return any_cast(sv[0]); - } - }; - - parser["Number"] = [](const SemanticValues& sv) { - return stoi(sv.token(), nullptr, 10); - }; - - // (4) Parse - parser.enable_packrat_parsing(); // Enable packrat parsing. - - int val; - parser.parse(" (1 + 2) * 3 ", val); - - assert(val == 9); + assert(static_cast(parser) == true); + + // (3) Setup actions + parser["Additive"] = [](const SemanticValues &vs) { + switch (vs.choice()) { + case 0: // "Multitive '+' Additive" + return any_cast(vs[0]) + any_cast(vs[1]); + default: // "Multitive" + return any_cast(vs[0]); + } + }; + + parser["Multitive"] = [](const SemanticValues &vs) { + switch (vs.choice()) { + case 0: // "Primary '*' Multitive" + return any_cast(vs[0]) * any_cast(vs[1]); + default: // "Primary" + return any_cast(vs[0]); + } + }; + + parser["Number"] = [](const SemanticValues &vs) { + return vs.token_to_number(); + }; + + // (4) Parse + parser.enable_packrat_parsing(); // Enable packrat parsing. + + int val; + parser.parse(" (1 + 2) * 3 ", val); + + assert(val == 9); } diff --git a/example/calc2.cc b/example/calc2.cc index 1ba00fa..c0121ab 100644 --- a/example/calc2.cc +++ b/example/calc2.cc @@ -5,9 +5,9 @@ // MIT License // -#include -#include #include +#include +#include using namespace peg; @@ -21,45 +21,47 @@ using namespace peg; // FACTOR_OPERATOR <- [/*] // NUMBER <- [0-9]+ // -int main(int argc, const char** argv) -{ - if (argc < 2 || std::string("--help") == argv[1]) { - std::cout << "usage: calc [formula]" << std::endl; - return 1; - } +int main(int argc, const char **argv) { + if (argc < 2 || std::string("--help") == argv[1]) { + std::cout << "usage: calc [formula]" << std::endl; + return 1; + } - auto reduce = [](const SemanticValues& sv) -> long { - auto result = any_cast(sv[0]); - for (auto i = 1u; i < sv.size(); i += 2) { - auto num = any_cast(sv[i + 1]); - auto ope = any_cast(sv[i]); - switch (ope) { - case '+': result += num; break; - case '-': result -= num; break; - case '*': result *= num; break; - case '/': result /= num; break; - } - } - return result; - }; + auto reduce = [](const SemanticValues &vs) { + auto result = std::any_cast(vs[0]); + for (auto i = 1u; i < vs.size(); i += 2) { + auto num = std::any_cast(vs[i + 1]); + auto ope = std::any_cast(vs[i]); + switch (ope) { + case '+': result += num; break; + case '-': result -= num; break; + case '*': result *= num; break; + case '/': result /= num; break; + } + } + return result; + }; - Definition EXPRESSION, TERM, FACTOR, TERM_OPERATOR, FACTOR_OPERATOR, NUMBER; + Definition EXPRESSION, TERM, FACTOR, TERM_OPERATOR, FACTOR_OPERATOR, NUMBER; - EXPRESSION <= seq(TERM, zom(seq(TERM_OPERATOR, TERM))), reduce; - TERM <= seq(FACTOR, zom(seq(FACTOR_OPERATOR, FACTOR))), reduce; - FACTOR <= cho(NUMBER, seq(chr('('), EXPRESSION, chr(')'))); - TERM_OPERATOR <= cls("+-"), [](const SemanticValues& sv) { return static_cast(*sv.c_str()); }; - FACTOR_OPERATOR <= cls("*/"), [](const SemanticValues& sv) { return static_cast(*sv.c_str()); }; - NUMBER <= oom(cls("0-9")), [](const SemanticValues& sv) { return atol(sv.c_str()); }; + EXPRESSION <= seq(TERM, zom(seq(TERM_OPERATOR, TERM))), reduce; + TERM <= seq(FACTOR, zom(seq(FACTOR_OPERATOR, FACTOR))), reduce; + FACTOR <= cho(NUMBER, seq(chr('('), EXPRESSION, chr(')'))); + TERM_OPERATOR <= cls("+-"), + [](const SemanticValues &vs) { return static_cast(*vs.sv().data()); }; + FACTOR_OPERATOR <= cls("*/"), + [](const SemanticValues &vs) { return static_cast(*vs.sv().data()); }; + NUMBER <= oom(cls("0-9")), + [](const SemanticValues &vs) { return vs.token_to_number(); }; - auto expr = argv[1]; - long val = 0; - if (EXPRESSION.parse_and_get_value(expr, val).ret) { - std::cout << expr << " = " << val << std::endl; - return 0; - } + auto expr = argv[1]; + long val = 0; + if (EXPRESSION.parse_and_get_value(expr, val).ret) { + std::cout << expr << " = " << val << std::endl; + return 0; + } - return -1; + return -1; } // vim: et ts=4 sw=4 cin cino={1s ff=unix diff --git a/example/calc3.cc b/example/calc3.cc index f8f85bb..1f5b633 100644 --- a/example/calc3.cc +++ b/example/calc3.cc @@ -5,40 +5,39 @@ // MIT License // -#include -#include #include +#include +#include using namespace peg; -int main(int argc, const char** argv) -{ - if (argc < 2 || std::string("--help") == argv[1]) { - std::cout << "usage: calc3 [formula]" << std::endl; - return 1; - } +int main(int argc, const char **argv) { + if (argc < 2 || std::string("--help") == argv[1]) { + std::cout << "usage: calc3 [formula]" << std::endl; + return 1; + } - std::function eval = [&](const Ast& ast) { - if (ast.name == "NUMBER") { - return stol(ast.token); - } else { - const auto& nodes = ast.nodes; - auto result = eval(*nodes[0]); - for (auto i = 1u; i < nodes.size(); i += 2) { - auto num = eval(*nodes[i + 1]); - auto ope = nodes[i]->token[0]; - switch (ope) { - case '+': result += num; break; - case '-': result -= num; break; - case '*': result *= num; break; - case '/': result /= num; break; - } - } - return result; + std::function eval = [&](const Ast &ast) { + if (ast.name == "NUMBER") { + return ast.token_to_number(); + } else { + const auto &nodes = ast.nodes; + auto result = eval(*nodes[0]); + for (auto i = 1u; i < nodes.size(); i += 2) { + auto num = eval(*nodes[i + 1]); + auto ope = nodes[i]->token[0]; + switch (ope) { + case '+': result += num; break; + case '-': result -= num; break; + case '*': result *= num; break; + case '/': result /= num; break; } - }; + } + return result; + } + }; - parser parser(R"( + parser parser(R"( EXPRESSION <- TERM (TERM_OPERATOR TERM)* TERM <- FACTOR (FACTOR_OPERATOR FACTOR)* FACTOR <- NUMBER / '(' EXPRESSION ')' @@ -50,20 +49,20 @@ int main(int argc, const char** argv) %whitespace <- [ \t\r\n]* )"); - parser.enable_ast(); + parser.enable_ast(); - auto expr = argv[1]; - std::shared_ptr ast; - if (parser.parse(expr, ast)) { - ast = AstOptimizer(true).optimize(ast); - std::cout << ast_to_s(ast); - std::cout << expr << " = " << eval(*ast) << std::endl; - return 0; - } + auto expr = argv[1]; + std::shared_ptr ast; + if (parser.parse(expr, ast)) { + ast = AstOptimizer(true).optimize(ast); + std::cout << ast_to_s(ast); + std::cout << expr << " = " << eval(*ast) << std::endl; + return 0; + } - std::cout << "syntax error..." << std::endl; + std::cout << "syntax error..." << std::endl; - return -1; + return -1; } // vim: et ts=4 sw=4 cin cino={1s ff=unix diff --git a/example/calc4.cc b/example/calc4.cc index 1404dfc..563f994 100644 --- a/example/calc4.cc +++ b/example/calc4.cc @@ -1,12 +1,12 @@ -#include #include #include +#include using namespace peg; using namespace std; int main(void) { - parser parser(R"( + parser parser(R"( EXPRESSION <- ATOM (OPERATOR ATOM)* { precedence L - + @@ -18,25 +18,25 @@ int main(void) { %whitespace <- [ \t\r\n]* )"); - parser["EXPRESSION"] = [](const SemanticValues& sv) -> long { - auto result = any_cast(sv[0]); - if (sv.size() > 1) { - auto ope = any_cast(sv[1]); - auto num = any_cast(sv[2]); - switch (ope) { - case '+': result += num; break; - case '-': result -= num; break; - case '*': result *= num; break; - case '/': result /= num; break; - } - } - return result; - }; - parser["OPERATOR"] = [](const SemanticValues& sv) { return *sv.c_str(); }; - parser["NUMBER"] = [](const SemanticValues& sv) { return atol(sv.c_str()); }; + parser["EXPRESSION"] = [](const SemanticValues &vs) { + auto result = any_cast(vs[0]); + if (vs.size() > 1) { + auto ope = any_cast(vs[1]); + auto num = any_cast(vs[2]); + switch (ope) { + case '+': result += num; break; + case '-': result -= num; break; + case '*': result *= num; break; + case '/': result /= num; break; + } + } + return result; + }; + parser["OPERATOR"] = [](const SemanticValues &vs) { return *vs.sv().data(); }; + parser["NUMBER"] = [](const SemanticValues &vs) { return atol(vs.sv().data()); }; - long val; - parser.parse(" -1 + (1 + 2) * 3 - -1", val); + long val; + parser.parse(" -1 + (1 + 2) * 3 - -1", val); - assert(val == 9); + assert(val == 9); } diff --git a/example/calc5.cc b/example/calc5.cc index 2b9a750..449a7d3 100644 --- a/example/calc5.cc +++ b/example/calc5.cc @@ -5,40 +5,39 @@ // MIT License // -#include -#include #include +#include +#include using namespace peg; -int main(int argc, const char** argv) -{ - if (argc < 2 || std::string("--help") == argv[1]) { - std::cout << "usage: calc5 [formula]" << std::endl; - return 1; - } +int main(int argc, const char **argv) { + if (argc < 2 || std::string("--help") == argv[1]) { + std::cout << "usage: calc5 [formula]" << std::endl; + return 1; + } - std::function eval = [&](const Ast& ast) { - if (ast.name == "NUMBER") { - return stol(ast.token); - } else { - const auto& nodes = ast.nodes; - auto result = eval(*nodes[0]); - if (nodes.size() > 1) { - auto ope = nodes[1]->token[0]; - auto num = eval(*nodes[2]); - switch (ope) { - case '+': result += num; break; - case '-': result -= num; break; - case '*': result *= num; break; - case '/': result /= num; break; - } - } - return result; + std::function eval = [&](const Ast &ast) { + if (ast.name == "NUMBER") { + return ast.token_to_number(); + } else { + const auto &nodes = ast.nodes; + auto result = eval(*nodes[0]); + if (nodes.size() > 1) { + auto ope = nodes[1]->token[0]; + auto num = eval(*nodes[2]); + switch (ope) { + case '+': result += num; break; + case '-': result -= num; break; + case '*': result *= num; break; + case '/': result /= num; break; } - }; + } + return result; + } + }; - parser parser(R"( + parser parser(R"( EXPRESSION <- ATOM (OPERATOR ATOM)* { precedence L - + @@ -50,20 +49,20 @@ int main(int argc, const char** argv) %whitespace <- [ \t\r\n]* )"); - parser.enable_ast(); + parser.enable_ast(); - auto expr = argv[1]; - std::shared_ptr ast; - if (parser.parse(expr, ast)) { - ast = AstOptimizer(true).optimize(ast); - std::cout << ast_to_s(ast); - std::cout << expr << " = " << eval(*ast) << std::endl; - return 0; - } + auto expr = argv[1]; + std::shared_ptr ast; + if (parser.parse(expr, ast)) { + ast = AstOptimizer(true).optimize(ast); + std::cout << ast_to_s(ast); + std::cout << expr << " = " << eval(*ast) << std::endl; + return 0; + } - std::cout << "syntax error..." << std::endl; + std::cout << "syntax error..." << std::endl; - return -1; + return -1; } // vim: et ts=4 sw=4 cin cino={1s ff=unix diff --git a/lint/CMakeLists.txt b/lint/CMakeLists.txt index 5561422..1c7e632 100644 --- a/lint/CMakeLists.txt +++ b/lint/CMakeLists.txt @@ -1,9 +1,9 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 3.1) project(peglint) + include_directories(..) -add_definitions("-std=c++11") -add_executable(peglint peglint.cc) -if(CMAKE_SYSTEM_NAME STREQUAL "Linux") - target_link_libraries(peglint ${add_link_deps}) -endif() +set(CMAKE_CXX_STANDARD 17) + +add_executable(peglint peglint.cc) +target_link_libraries(peglint ${add_link_deps}) diff --git a/lint/peglint.cc b/lint/peglint.cc index 930fd2e..7aeb2f4 100644 --- a/lint/peglint.cc +++ b/lint/peglint.cc @@ -131,7 +131,7 @@ int main(int argc, const char **argv) { parser.enable_trace( [&](const char *name, const char *s, size_t /*n*/, const peg::SemanticValues & /*sv*/, const peg::Context &c, - const peg::any & /*dt*/) { + const std::any & /*dt*/) { auto pos = static_cast(s - c.s); auto backtrack = (pos < prev_pos ? "*" : ""); string indent; @@ -145,7 +145,7 @@ int main(int argc, const char **argv) { }, [&](const char *name, const char *s, size_t /*n*/, const peg::SemanticValues &sv, const peg::Context &c, - const peg::any & /*dt*/, size_t len) { + const std::any & /*dt*/, size_t len) { auto pos = static_cast(s - c.s); if (len != static_cast(-1)) { pos += len; } string indent; @@ -160,8 +160,9 @@ int main(int argc, const char **argv) { } std::string token; if (!sv.tokens.empty()) { - const auto &tok = sv.tokens[0]; - token += " '" + std::string(tok.first, tok.second) + "'"; + token += " '"; + token += sv.tokens[0]; + token +=+ "'"; } std::cout << "L " << pos << "\t" << indent << ret << name << " #" << c.trace_ids.back() << choice.str() << token << std::endl; diff --git a/peglib.h b/peglib.h index 3cf24cd..e2e85ec 100644 --- a/peglib.h +++ b/peglib.h @@ -5,20 +5,13 @@ // MIT License // -#ifndef CPPPEGLIB_PEGLIB_H -#define CPPPEGLIB_PEGLIB_H - -#ifndef PEGLIB_USE_STD_ANY -#ifdef _MSVC_LANG -#define PEGLIB_USE_STD_ANY _MSVC_LANG >= 201703L -#elif defined(__cplusplus) -#define PEGLIB_USE_STD_ANY __cplusplus >= 201703L -#endif -#endif // PEGLIB_USE_STD_ANY +#pragma once #include +#include #include #include +#include #include #include #include @@ -29,110 +22,16 @@ #include #include #include -#include #include #include #include -#if PEGLIB_USE_STD_ANY -#include -#endif -// guard for older versions of VC++ -#ifdef _MSC_VER -#if defined(_MSC_VER) && _MSC_VER < 1900 // Less than Visual Studio 2015 -#error "Requires complete C+11 support" -#endif +#if !defined(__cplusplus) || __cplusplus < 201703L +#error "Requires complete C++17 support" #endif namespace peg { -/*----------------------------------------------------------------------------- - * any - *---------------------------------------------------------------------------*/ - -#if PEGLIB_USE_STD_ANY -using any = std::any; - -// Define a function alias to std::any_cast using perfect forwarding -template -auto any_cast(Args &&... args) - -> decltype(std::any_cast(std::forward(args)...)) { - return std::any_cast(std::forward(args)...); -} -#else -class any { -public: - any() = default; - - any(const any &rhs) : content_(rhs.clone()) {} - - any(any &&rhs) : content_(rhs.content_) { rhs.content_ = nullptr; } - - template any(const T &value) : content_(new holder(value)) {} - - any &operator=(const any &rhs) { - if (this != &rhs) { - if (content_) { delete content_; } - content_ = rhs.clone(); - } - return *this; - } - - any &operator=(any &&rhs) { - if (this != &rhs) { - if (content_) { delete content_; } - content_ = rhs.content_; - rhs.content_ = nullptr; - } - return *this; - } - - ~any() { delete content_; } - - bool has_value() const { return content_ != nullptr; } - - template friend T &any_cast(any &val); - - template friend const T &any_cast(const any &val); - -private: - struct placeholder { - virtual ~placeholder() {} - virtual placeholder *clone() const = 0; - }; - - template struct holder : placeholder { - holder(const T &value) : value_(value) {} - placeholder *clone() const override { return new holder(value_); } - T value_; - }; - - placeholder *clone() const { return content_ ? content_->clone() : nullptr; } - - placeholder *content_ = nullptr; -}; - -template T &any_cast(any &val) { - if (!val.content_) { throw std::bad_cast(); } - auto p = dynamic_cast *>(val.content_); - assert(p); - if (!p) { throw std::bad_cast(); } - return p->value_; -} - -template <> inline any &any_cast(any &val) { return val; } - -template const T &any_cast(const any &val) { - assert(val.content_); - auto p = dynamic_cast *>(val.content_); - assert(p); - if (!p) { throw std::bad_cast(); } - return p->value_; -} - -template <> inline const any &any_cast(const any &val) { return val; } -#endif - /*----------------------------------------------------------------------------- * scope_exit *---------------------------------------------------------------------------*/ @@ -165,12 +64,6 @@ private: bool execute_on_destruction; }; -template -auto make_scope_exit(EF &&exit_function) -> scope_exit { - return scope_exit::type>( - std::forward(exit_function)); -} - /*----------------------------------------------------------------------------- * UTF8 functions *---------------------------------------------------------------------------*/ @@ -324,7 +217,7 @@ inline std::pair parse_hex_number(const char *s, size_t n, ret = static_cast(ret * 16 + val); i++; } - return std::make_pair(ret, i); + return std::pair(ret, i); } inline std::pair parse_octal_number(const char *s, size_t n, @@ -335,7 +228,7 @@ inline std::pair parse_octal_number(const char *s, size_t n, ret = static_cast(ret * 8 + val); i++; } - return std::make_pair(ret, i); + return std::pair(ret, i); } inline std::string resolve_escape_sequence(const char *s, size_t n) { @@ -416,10 +309,10 @@ public: for (const auto &item : items) { for (size_t len = 1; len <= item.size(); len++) { auto last = len == item.size(); - std::string s(item.c_str(), len); - auto it = dic_.find(s); + std::string_view sv(item.data(), len); + auto it = dic_.find(sv); if (it == dic_.end()) { - dic_.emplace(s, Info{last, last}); + dic_.emplace(sv, Info{last, last}); } else if (last) { it->second.match = true; } else { @@ -431,20 +324,18 @@ public: size_t match(const char *text, size_t text_len) const { size_t match_len = 0; - { - auto done = false; - size_t len = 1; - while (!done && len <= text_len) { - std::string s(text, len); - auto it = dic_.find(s); - if (it == dic_.end()) { - done = true; - } else { - if (it->second.match) { match_len = len; } - if (it->second.done) { done = true; } - } - len += 1; + auto done = false; + size_t len = 1; + while (!done && len <= text_len) { + std::string_view sv(text, len); + auto it = dic_.find(sv); + if (it == dic_.end()) { + done = true; + } else { + if (it->second.match) { match_len = len; } + if (it->second.done) { done = true; } } + len += 1; } return match_len; } @@ -454,7 +345,10 @@ private: bool done; bool match; }; - std::unordered_map dic_; + + // TODO: Use unordered_map when heterogeneous lookup is supported in C++20 + // std::unordered_map dic_; + std::map> dic_; }; /*----------------------------------------------------------------------------- @@ -479,22 +373,27 @@ inline std::pair line_info(const char *start, const char *cur) { auto col = p - col_ptr + 1; - return std::make_pair(no, col); + return std::pair(no, col); } /* * String tag */ -inline constexpr unsigned int str2tag(const char *str, unsigned int h = 0) { - return (*str == '\0') - ? h - : str2tag(str + 1, (h * 33) ^ static_cast(*str)); +inline constexpr unsigned int str2tag_core(const char *s, size_t l, + unsigned int h) { + return (l == 0) ? h + : str2tag_core(s + 1, l - 1, + (h * 33) ^ static_cast(*s)); +} + +inline constexpr unsigned int str2tag(std::string_view sv) { + return str2tag_core(sv.data(), sv.size(), 0); } namespace udl { -inline constexpr unsigned int operator"" _(const char *s, size_t) { - return str2tag(s); +inline constexpr unsigned int operator"" _(const char *s, size_t l) { + return str2tag_core(s, l, 0); } } // namespace udl @@ -502,17 +401,14 @@ inline constexpr unsigned int operator"" _(const char *s, size_t) { /* * Semantic values */ -struct SemanticValues : protected std::vector { +struct SemanticValues : protected std::vector { // Input text const char *path = nullptr; const char *ss = nullptr; const std::vector *source_line_index = nullptr; // Matched string - const char *c_str() const { return s_; } - size_t length() const { return n_; } - - std::string str() const { return std::string(s_, n_); } + std::string_view sv() const { return sv_; } // Definition name const std::string &name() const { return name_; } @@ -523,14 +419,14 @@ struct SemanticValues : protected std::vector { std::pair line_info() const { const auto &idx = *source_line_index; - auto cur = static_cast(std::distance(ss, s_)); + auto cur = static_cast(std::distance(ss, sv_.data())); auto it = std::lower_bound( idx.begin(), idx.end(), cur, [](size_t element, size_t value) { return element < value; }); auto id = static_cast(std::distance(idx.begin(), it)); auto off = cur - (id == 0 ? 0 : idx[id - 1] + 1); - return std::make_pair(id + 1, off + 1); + return std::pair(id + 1, off + 1); } // Choice count @@ -540,15 +436,24 @@ struct SemanticValues : protected std::vector { size_t choice() const { return choice_; } // Tokens - std::vector> tokens; + std::vector tokens; - std::string token(size_t id = 0) const { - if (!tokens.empty()) { - assert(id < tokens.size()); - const auto &tok = tokens[id]; - return std::string(tok.first, tok.second); - } - return std::string(s_, n_); + std::string_view token(size_t id = 0) const { + if (tokens.empty()) { return sv_; } + assert(id < tokens.size()); + return tokens[id]; + } + + // Token conversion + std::string token_to_string(size_t id = 0) const { + return std::string(token(id)); + } + + template T token_to_number() const { + auto sv = token(); + T n = 0; + std::from_chars(sv.data(), sv.data() + sv.size(), n); + return n; } // Transform the semantic value vector to another vector @@ -558,33 +463,33 @@ struct SemanticValues : protected std::vector { std::vector r; end = (std::min)(end, size()); for (size_t i = beg; i < end; i++) { - r.emplace_back(any_cast((*this)[i])); + r.emplace_back(std::any_cast((*this)[i])); } return r; } - using std::vector::iterator; - using std::vector::const_iterator; - using std::vector::size; - using std::vector::empty; - using std::vector::assign; - using std::vector::begin; - using std::vector::end; - using std::vector::rbegin; - using std::vector::rend; - using std::vector::operator[]; - using std::vector::at; - using std::vector::resize; - using std::vector::front; - using std::vector::back; - using std::vector::push_back; - using std::vector::pop_back; - using std::vector::insert; - using std::vector::erase; - using std::vector::clear; - using std::vector::swap; - using std::vector::emplace; - using std::vector::emplace_back; + using std::vector::iterator; + using std::vector::const_iterator; + using std::vector::size; + using std::vector::empty; + using std::vector::assign; + using std::vector::begin; + using std::vector::end; + using std::vector::rbegin; + using std::vector::rend; + using std::vector::operator[]; + using std::vector::at; + using std::vector::resize; + using std::vector::front; + using std::vector::back; + using std::vector::push_back; + using std::vector::pop_back; + using std::vector::insert; + using std::vector::erase; + using std::vector::clear; + using std::vector::swap; + using std::vector::emplace; + using std::vector::emplace_back; private: friend class Context; @@ -593,8 +498,7 @@ private: friend class Holder; friend class PrecedenceClimbing; - const char *s_ = nullptr; - size_t n_ = 0; + std::string_view sv_; size_t choice_count_ = 0; size_t choice_ = 0; std::string name_; @@ -603,170 +507,54 @@ private: /* * Semantic action */ -template ::value, - std::nullptr_t>::type = nullptr, - typename... Args> -any call(F fn, Args &&... args) { - fn(std::forward(args)...); - return any(); -} - -template ::type, any>::value, - std::nullptr_t>::type = nullptr, - typename... Args> -any call(F fn, Args &&... args) { - return fn(std::forward(args)...); -} - -template ::value && - !std::is_same::type, any>::value, - std::nullptr_t>::type = nullptr, - typename... Args> -any call(F fn, Args &&... args) { - return any(fn(std::forward(args)...)); +template std::any call(F fn, Args &&... args) { + using R = decltype(fn(std::forward(args)...)); + if constexpr (std::is_void::value) { + fn(std::forward(args)...); + return std::any(); + } else if constexpr (std::is_same::type, + std::any>::value) { + return fn(std::forward(args)...); + } else { + return std::any(fn(std::forward(args)...)); + } } +template +struct argument_count : argument_count {}; +template +struct argument_count + : std::integral_constant {}; +template +struct argument_count + : std::integral_constant {}; +template +struct argument_count + : std::integral_constant {}; + class Action { public: Action() = default; - Action(const Action &rhs) = default; - - template ::value && - !std::is_same::value, - std::nullptr_t>::type = nullptr> - Action(F fn) : fn_(make_adaptor(fn, &F::operator())) {} - - template ::value, - std::nullptr_t>::type = nullptr> - Action(F fn) : fn_(make_adaptor(fn, fn)) {} - - template ::value, - std::nullptr_t>::type = nullptr> - Action(F /*fn*/) {} - - template ::value && - !std::is_same::value, - std::nullptr_t>::type = nullptr> - void operator=(F fn) { - fn_ = make_adaptor(fn, &F::operator()); - } - - template ::value, - std::nullptr_t>::type = nullptr> - void operator=(F fn) { - fn_ = make_adaptor(fn, fn); - } - - template ::value, - std::nullptr_t>::type = nullptr> - void operator=(F /*fn*/) {} - + Action(Action &&rhs) = default; + template Action(F fn) : fn_(make_adaptor(fn)) {} + template void operator=(F fn) { fn_ = make_adaptor(fn); } Action &operator=(const Action &rhs) = default; operator bool() const { return bool(fn_); } - any operator()(SemanticValues &sv, any &dt) const { return fn_(sv, dt); } + std::any operator()(SemanticValues &vs, std::any &dt) const { + return fn_(vs, dt); + } private: - template struct TypeAdaptor_sv { - TypeAdaptor_sv(std::function fn) : fn_(fn) {} - any operator()(SemanticValues &sv, any & /*dt*/) { - return call(fn_, sv); - } - std::function fn_; - }; + using Fty = std::function; - template struct TypeAdaptor_csv { - TypeAdaptor_csv(std::function fn) : fn_(fn) {} - any operator()(SemanticValues &sv, any & /*dt*/) { - return call(fn_, sv); + template Fty make_adaptor(F fn) { + if constexpr (argument_count::value == 1) { + return [fn](auto &vs, auto & /*dt*/) { return call(fn, vs); }; + } else { + return [fn](auto &vs, auto &dt) { return call(fn, vs, dt); }; } - std::function fn_; - }; - - template struct TypeAdaptor_sv_dt { - TypeAdaptor_sv_dt(std::function fn) - : fn_(fn) {} - any operator()(SemanticValues &sv, any &dt) { return call(fn_, sv, dt); } - std::function fn_; - }; - - template struct TypeAdaptor_csv_dt { - TypeAdaptor_csv_dt(std::function fn) - : fn_(fn) {} - any operator()(SemanticValues &sv, any &dt) { return call(fn_, sv, dt); } - std::function fn_; - }; - - typedef std::function Fty; - - template - Fty make_adaptor(F fn, R (F::*)(SemanticValues &sv) const) { - return TypeAdaptor_sv(fn); - } - - template - Fty make_adaptor(F fn, R (F::*)(const SemanticValues &sv) const) { - return TypeAdaptor_csv(fn); - } - - template - Fty make_adaptor(F fn, R (F::*)(SemanticValues &sv)) { - return TypeAdaptor_sv(fn); - } - - template - Fty make_adaptor(F fn, R (F::*)(const SemanticValues &sv)) { - return TypeAdaptor_csv(fn); - } - - template - Fty make_adaptor(F fn, R (*)(SemanticValues &sv)) { - return TypeAdaptor_sv(fn); - } - - template - Fty make_adaptor(F fn, R (*)(const SemanticValues &sv)) { - return TypeAdaptor_csv(fn); - } - - template - Fty make_adaptor(F fn, R (F::*)(SemanticValues &sv, any &dt) const) { - return TypeAdaptor_sv_dt(fn); - } - - template - Fty make_adaptor(F fn, R (F::*)(const SemanticValues &sv, any &dt) const) { - return TypeAdaptor_csv_dt(fn); - } - - template - Fty make_adaptor(F fn, R (F::*)(SemanticValues &sv, any &dt)) { - return TypeAdaptor_sv_dt(fn); - } - - template - Fty make_adaptor(F fn, R (F::*)(const SemanticValues &sv, any &dt)) { - return TypeAdaptor_csv_dt(fn); - } - - template - Fty make_adaptor(F fn, R (*)(SemanticValues &sv, any &dt)) { - return TypeAdaptor_sv_dt(fn); - } - - template - Fty make_adaptor(F fn, R (*)(const SemanticValues &sv, any &dt)) { - return TypeAdaptor_csv_dt(fn); } Fty fn_; @@ -780,7 +568,7 @@ private: struct parse_error { parse_error() = default; parse_error(const char *s) : s_(s) {} - const char *what() const { return s_.empty() ? nullptr : s_.c_str(); } + const char *what() const { return s_.empty() ? nullptr : s_.data(); } private: std::string s_; @@ -800,15 +588,13 @@ class Context; class Ope; class Definition; -typedef std::function - TracerEnter; +using TracerEnter = std::function; -typedef std::function - TracerLeave; +using TracerLeave = std::function; class Context { public: @@ -834,7 +620,7 @@ public: std::shared_ptr wordOpe; - std::vector> capture_scope_stack; + std::vector> capture_scope_stack; size_t capture_scope_stack_size = 0; const size_t def_count; @@ -842,7 +628,8 @@ public: std::vector cache_registered; std::vector cache_success; - std::map, std::tuple> cache_values; + std::map, std::tuple> + cache_values; TracerEnter tracer_enter; TracerLeave tracer_leave; @@ -875,7 +662,8 @@ public: Context operator=(const Context &) = delete; template - void packrat(const char *a_s, size_t def_id, size_t &len, any &val, T fn) { + void packrat(const char *a_s, size_t def_id, size_t &len, std::any &val, + T fn) { if (!enablePackratParsing) { fn(val); return; @@ -886,7 +674,7 @@ public: if (cache_registered[idx]) { if (cache_success[idx]) { - auto key = std::make_pair(col, def_id); + auto key = std::pair(col, def_id); std::tie(len, val) = cache_values[key]; return; } else { @@ -898,8 +686,8 @@ public: cache_registered[idx] = true; cache_success[idx] = success(len); if (success(len)) { - auto key = std::make_pair(col, def_id); - cache_values[key] = std::make_pair(len, val); + auto key = std::pair(col, def_id); + cache_values[key] = std::pair(len, val); } return; } @@ -910,23 +698,22 @@ public: if (value_stack_size == value_stack.size()) { value_stack.emplace_back(std::make_shared()); } else { - auto &sv = *value_stack[value_stack_size]; - if (!sv.empty()) { - sv.clear(); - if (!sv.tags.empty()) { sv.tags.clear(); } + auto &vs = *value_stack[value_stack_size]; + if (!vs.empty()) { + vs.clear(); + if (!vs.tags.empty()) { vs.tags.clear(); } } - sv.s_ = nullptr; - sv.n_ = 0; - sv.choice_count_ = 0; - sv.choice_ = 0; - if (!sv.tokens.empty()) { sv.tokens.clear(); } + vs.sv_ = std::string_view(); + vs.choice_count_ = 0; + vs.choice_ = 0; + if (!vs.tokens.empty()) { vs.tokens.clear(); } } - auto &sv = *value_stack[value_stack_size++]; - sv.path = path; - sv.ss = s; - sv.source_line_index = &source_line_index; - return sv; + auto &vs = *value_stack[value_stack_size++]; + vs.path = path; + vs.ss = s; + vs.source_line_index = &source_line_index; + return vs; } void pop() { value_stack_size--; } @@ -944,7 +731,8 @@ public: void push_capture_scope() { assert(capture_scope_stack_size <= capture_scope_stack.size()); if (capture_scope_stack_size == capture_scope_stack.size()) { - capture_scope_stack.emplace_back(std::map()); + capture_scope_stack.emplace_back( + std::map()); } else { auto &cs = capture_scope_stack[capture_scope_stack_size]; if (!cs.empty()) { cs.clear(); } @@ -968,9 +756,9 @@ public: } void trace_enter(const char *name, const char *a_s, size_t n, - SemanticValues &sv, any &dt) const; + SemanticValues &vs, std::any &dt) const; void trace_leave(const char *name, const char *a_s, size_t n, - SemanticValues &sv, any &dt, size_t len) const; + SemanticValues &vs, std::any &dt, size_t len) const; bool is_traceable(const Ope &ope) const; mutable size_t next_trace_id = 0; @@ -985,10 +773,10 @@ public: struct Visitor; virtual ~Ope() {} - size_t parse(const char *s, size_t n, SemanticValues &sv, Context &c, - any &dt) const; - virtual size_t parse_core(const char *s, size_t n, SemanticValues &sv, - Context &c, any &dt) const = 0; + size_t parse(const char *s, size_t n, SemanticValues &vs, Context &c, + std::any &dt) const; + virtual size_t parse_core(const char *s, size_t n, SemanticValues &vs, + Context &c, std::any &dt) const = 0; virtual void accept(Visitor &v) = 0; }; @@ -1000,10 +788,10 @@ public: Sequence(const std::vector> &opes) : opes_(opes) {} Sequence(std::vector> &&opes) : opes_(opes) {} - size_t parse_core(const char *s, size_t n, SemanticValues &sv, Context &c, - any &dt) const override { + size_t parse_core(const char *s, size_t n, SemanticValues &vs, Context &c, + std::any &dt) const override { auto &chldsv = c.push(); - auto pop_se = make_scope_exit([&]() { c.pop(); }); + auto pop_se = scope_exit([&]() { c.pop(); }); size_t i = 0; for (const auto &ope : opes_) { const auto &rule = *ope; @@ -1013,19 +801,18 @@ public: } if (!chldsv.empty()) { for (size_t j = 0; j < chldsv.size(); j++) { - sv.emplace_back(std::move(chldsv[j])); + vs.emplace_back(std::move(chldsv[j])); } } if (!chldsv.tags.empty()) { for (size_t j = 0; j < chldsv.tags.size(); j++) { - sv.tags.emplace_back(std::move(chldsv.tags[j])); + vs.tags.emplace_back(std::move(chldsv.tags[j])); } } - sv.s_ = chldsv.c_str(); - sv.n_ = chldsv.length(); + vs.sv_ = chldsv.sv_; if (!chldsv.tokens.empty()) { for (size_t j = 0; j < chldsv.tokens.size(); j++) { - sv.tokens.emplace_back(std::move(chldsv.tokens[j])); + vs.tokens.emplace_back(std::move(chldsv.tokens[j])); } } return i; @@ -1045,13 +832,13 @@ public: : opes_(opes) {} PrioritizedChoice(std::vector> &&opes) : opes_(opes) {} - size_t parse_core(const char *s, size_t n, SemanticValues &sv, Context &c, - any &dt) const override { + size_t parse_core(const char *s, size_t n, SemanticValues &vs, Context &c, + std::any &dt) const override { size_t id = 0; for (const auto &ope : opes_) { auto &chldsv = c.push(); c.push_capture_scope(); - auto se = make_scope_exit([&]() { + auto se = scope_exit([&]() { c.pop(); c.pop_capture_scope(); }); @@ -1059,21 +846,20 @@ public: if (success(len)) { if (!chldsv.empty()) { for (size_t i = 0; i < chldsv.size(); i++) { - sv.emplace_back(std::move(chldsv[i])); + vs.emplace_back(std::move(chldsv[i])); } } if (!chldsv.tags.empty()) { for (size_t i = 0; i < chldsv.tags.size(); i++) { - sv.tags.emplace_back(std::move(chldsv.tags[i])); + vs.tags.emplace_back(std::move(chldsv.tags[i])); } } - sv.s_ = chldsv.c_str(); - sv.n_ = chldsv.length(); - sv.choice_count_ = opes_.size(); - sv.choice_ = id; + vs.sv_ = chldsv.sv_; + vs.choice_count_ = opes_.size(); + vs.choice_ = id; if (!chldsv.tokens.empty()) { for (size_t i = 0; i < chldsv.tokens.size(); i++) { - sv.tokens.emplace_back(std::move(chldsv.tokens[i])); + vs.tokens.emplace_back(std::move(chldsv.tokens[i])); } } @@ -1097,15 +883,15 @@ public: Repetition(const std::shared_ptr &ope, size_t min, size_t max) : ope_(ope), min_(min), max_(max) {} - size_t parse_core(const char *s, size_t n, SemanticValues &sv, Context &c, - any &dt) const override { + size_t parse_core(const char *s, size_t n, SemanticValues &vs, Context &c, + std::any &dt) const override { size_t count = 0; size_t i = 0; while (count < min_) { c.push_capture_scope(); - auto se = make_scope_exit([&]() { c.pop_capture_scope(); }); + auto se = scope_exit([&]() { c.pop_capture_scope(); }); const auto &rule = *ope_; - auto len = rule.parse(s + i, n - i, sv, c, dt); + auto len = rule.parse(s + i, n - i, vs, c, dt); if (success(len)) { c.shift_capture_values(); } else { @@ -1118,21 +904,21 @@ public: auto save_error_pos = c.error_pos; while (n - i > 0 && count < max_) { c.push_capture_scope(); - auto se = make_scope_exit([&]() { c.pop_capture_scope(); }); - auto save_sv_size = sv.size(); - auto save_tok_size = sv.tokens.size(); + auto se = scope_exit([&]() { c.pop_capture_scope(); }); + auto save_sv_size = vs.size(); + auto save_tok_size = vs.tokens.size(); const auto &rule = *ope_; - auto len = rule.parse(s + i, n - i, sv, c, dt); + auto len = rule.parse(s + i, n - i, vs, c, dt); if (success(len)) { c.shift_capture_values(); } else { - if (sv.size() != save_sv_size) { - sv.erase(sv.begin() + static_cast(save_sv_size)); - sv.tags.erase(sv.tags.begin() + + if (vs.size() != save_sv_size) { + vs.erase(vs.begin() + static_cast(save_sv_size)); + vs.tags.erase(vs.tags.begin() + static_cast(save_sv_size)); } - if (sv.tokens.size() != save_tok_size) { - sv.tokens.erase(sv.tokens.begin() + + if (vs.tokens.size() != save_tok_size) { + vs.tokens.erase(vs.tokens.begin() + static_cast(save_tok_size)); } c.error_pos = save_error_pos; @@ -1173,11 +959,11 @@ class AndPredicate : public Ope { public: AndPredicate(const std::shared_ptr &ope) : ope_(ope) {} - size_t parse_core(const char *s, size_t n, SemanticValues & /*sv*/, - Context &c, any &dt) const override { + size_t parse_core(const char *s, size_t n, SemanticValues & /*vs*/, + Context &c, std::any &dt) const override { auto &chldsv = c.push(); c.push_capture_scope(); - auto se = make_scope_exit([&]() { + auto se = scope_exit([&]() { c.pop(); c.pop_capture_scope(); }); @@ -1199,12 +985,12 @@ class NotPredicate : public Ope { public: NotPredicate(const std::shared_ptr &ope) : ope_(ope) {} - size_t parse_core(const char *s, size_t n, SemanticValues & /*sv*/, - Context &c, any &dt) const override { + size_t parse_core(const char *s, size_t n, SemanticValues & /*vs*/, + Context &c, std::any &dt) const override { auto save_error_pos = c.error_pos; auto &chldsv = c.push(); c.push_capture_scope(); - auto se = make_scope_exit([&]() { + auto se = scope_exit([&]() { c.pop(); c.pop_capture_scope(); }); @@ -1227,8 +1013,8 @@ class Dictionary : public Ope, public std::enable_shared_from_this { public: Dictionary(const std::vector &v) : trie_(v) {} - size_t parse_core(const char *s, size_t n, SemanticValues &sv, Context &c, - any &dt) const override; + size_t parse_core(const char *s, size_t n, SemanticValues &vs, Context &c, + std::any &dt) const override; void accept(Visitor &v) override; @@ -1244,8 +1030,8 @@ public: LiteralString(const std::string &s, bool ignore_case) : lit_(s), ignore_case_(ignore_case), is_word_(false) {} - size_t parse_core(const char *s, size_t n, SemanticValues &sv, Context &c, - any &dt) const override; + size_t parse_core(const char *s, size_t n, SemanticValues &vs, Context &c, + std::any &dt) const override; void accept(Visitor &v) override; @@ -1259,17 +1045,17 @@ class CharacterClass : public Ope, public std::enable_shared_from_this { public: CharacterClass(const std::string &s, bool negated) : negated_(negated) { - auto chars = decode(s.c_str(), s.length()); + auto chars = decode(s.data(), s.length()); auto i = 0u; while (i < chars.size()) { if (i + 2 < chars.size() && chars[i + 1] == '-') { auto cp1 = chars[i]; auto cp2 = chars[i + 2]; - ranges_.emplace_back(std::make_pair(cp1, cp2)); + ranges_.emplace_back(std::pair(cp1, cp2)); i += 3; } else { auto cp = chars[i]; - ranges_.emplace_back(std::make_pair(cp, cp)); + ranges_.emplace_back(std::pair(cp, cp)); i += 1; } } @@ -1282,8 +1068,8 @@ public: assert(!ranges_.empty()); } - size_t parse_core(const char *s, size_t n, SemanticValues & /*sv*/, - Context &c, any & /*dt*/) const override { + size_t parse_core(const char *s, size_t n, SemanticValues & /*vs*/, + Context &c, std::any & /*dt*/) const override { if (n < 1) { c.set_error_pos(s); return static_cast(-1); @@ -1321,8 +1107,8 @@ class Character : public Ope, public std::enable_shared_from_this { public: Character(char ch) : ch_(ch) {} - size_t parse_core(const char *s, size_t n, SemanticValues & /*sv*/, - Context &c, any & /*dt*/) const override { + size_t parse_core(const char *s, size_t n, SemanticValues & /*vs*/, + Context &c, std::any & /*dt*/) const override { if (n < 1 || s[0] != ch_) { c.set_error_pos(s); return static_cast(-1); @@ -1338,8 +1124,8 @@ public: class AnyCharacter : public Ope, public std::enable_shared_from_this { public: - size_t parse_core(const char *s, size_t n, SemanticValues & /*sv*/, - Context &c, any & /*dt*/) const override { + size_t parse_core(const char *s, size_t n, SemanticValues & /*vs*/, + Context &c, std::any & /*dt*/) const override { auto len = codepoint_length(s, n); if (len < 1) { c.set_error_pos(s); @@ -1355,12 +1141,12 @@ class CaptureScope : public Ope { public: CaptureScope(const std::shared_ptr &ope) : ope_(ope) {} - size_t parse_core(const char *s, size_t n, SemanticValues &sv, Context &c, - any &dt) const override { + size_t parse_core(const char *s, size_t n, SemanticValues &vs, Context &c, + std::any &dt) const override { c.push_capture_scope(); - auto se = make_scope_exit([&]() { c.pop_capture_scope(); }); + auto se = scope_exit([&]() { c.pop_capture_scope(); }); const auto &rule = *ope_; - auto len = rule.parse(s, n, sv, c, dt); + auto len = rule.parse(s, n, vs, c, dt); return len; } @@ -1371,15 +1157,15 @@ public: class Capture : public Ope { public: - typedef std::function MatchAction; + using MatchAction = std::function; Capture(const std::shared_ptr &ope, MatchAction ma) : ope_(ope), match_action_(ma) {} - size_t parse_core(const char *s, size_t n, SemanticValues &sv, Context &c, - any &dt) const override { + size_t parse_core(const char *s, size_t n, SemanticValues &vs, Context &c, + std::any &dt) const override { const auto &rule = *ope_; - auto len = rule.parse(s, n, sv, c, dt); + auto len = rule.parse(s, n, vs, c, dt); if (success(len) && match_action_) { match_action_(s, len, c); } return len; } @@ -1394,8 +1180,8 @@ class TokenBoundary : public Ope { public: TokenBoundary(const std::shared_ptr &ope) : ope_(ope) {} - size_t parse_core(const char *s, size_t n, SemanticValues &sv, Context &c, - any &dt) const override; + size_t parse_core(const char *s, size_t n, SemanticValues &vs, Context &c, + std::any &dt) const override; void accept(Visitor &v) override; @@ -1406,11 +1192,11 @@ class Ignore : public Ope { public: Ignore(const std::shared_ptr &ope) : ope_(ope) {} - size_t parse_core(const char *s, size_t n, SemanticValues & /*sv*/, - Context &c, any &dt) const override { + size_t parse_core(const char *s, size_t n, SemanticValues & /*vs*/, + Context &c, std::any &dt) const override { const auto &rule = *ope_; auto &chldsv = c.push(); - auto se = make_scope_exit([&]() { c.pop(); }); + auto se = scope_exit([&]() { c.pop(); }); return rule.parse(s, n, chldsv, c, dt); } @@ -1419,20 +1205,20 @@ public: std::shared_ptr ope_; }; -typedef std::function - Parser; +using Parser = std::function; class User : public Ope { public: User(Parser fn) : fn_(fn) {} - size_t parse_core(const char *s, size_t n, SemanticValues &sv, - Context & /*c*/, any &dt) const override { + size_t parse_core(const char *s, size_t n, SemanticValues &vs, + Context & /*c*/, std::any &dt) const override { assert(fn_); - return fn_(s, n, sv, dt); + return fn_(s, n, vs, dt); } void accept(Visitor &v) override; - std::function + std::function fn_; }; @@ -1440,12 +1226,12 @@ class WeakHolder : public Ope { public: WeakHolder(const std::shared_ptr &ope) : weak_(ope) {} - size_t parse_core(const char *s, size_t n, SemanticValues &sv, Context &c, - any &dt) const override { + size_t parse_core(const char *s, size_t n, SemanticValues &vs, Context &c, + std::any &dt) const override { auto ope = weak_.lock(); assert(ope); const auto &rule = *ope; - return rule.parse(s, n, sv, c, dt); + return rule.parse(s, n, vs, c, dt); } void accept(Visitor &v) override; @@ -1457,12 +1243,12 @@ class Holder : public Ope { public: Holder(Definition *outer) : outer_(outer) {} - size_t parse_core(const char *s, size_t n, SemanticValues &sv, Context &c, - any &dt) const override; + size_t parse_core(const char *s, size_t n, SemanticValues &vs, Context &c, + std::any &dt) const override; void accept(Visitor &v) override; - any reduce(SemanticValues &sv, any &dt) const; + std::any reduce(SemanticValues &vs, std::any &dt) const; const char *trace_name() const; @@ -1473,7 +1259,7 @@ public: friend class Definition; }; -typedef std::unordered_map Grammar; +using Grammar = std::unordered_map; class Reference : public Ope, public std::enable_shared_from_this { public: @@ -1482,8 +1268,8 @@ public: : grammar_(grammar), name_(name), s_(s), is_macro_(is_macro), args_(args), rule_(nullptr), iarg_(0) {} - size_t parse_core(const char *s, size_t n, SemanticValues &sv, Context &c, - any &dt) const override; + size_t parse_core(const char *s, size_t n, SemanticValues &vs, Context &c, + std::any &dt) const override; void accept(Visitor &v) override; @@ -1504,13 +1290,13 @@ class Whitespace : public Ope { public: Whitespace(const std::shared_ptr &ope) : ope_(ope) {} - size_t parse_core(const char *s, size_t n, SemanticValues &sv, Context &c, - any &dt) const override { + size_t parse_core(const char *s, size_t n, SemanticValues &vs, Context &c, + std::any &dt) const override { if (c.in_whitespace) { return 0; } c.in_whitespace = true; - auto se = make_scope_exit([&]() { c.in_whitespace = false; }); + auto se = scope_exit([&]() { c.in_whitespace = false; }); const auto &rule = *ope_; - return rule.parse(s, n, sv, c, dt); + return rule.parse(s, n, vs, c, dt); } void accept(Visitor &v) override; @@ -1520,10 +1306,12 @@ public: class BackReference : public Ope { public: + BackReference(std::string &&name) : name_(name) {} + BackReference(const std::string &name) : name_(name) {} - size_t parse_core(const char *s, size_t n, SemanticValues &sv, Context &c, - any &dt) const override; + size_t parse_core(const char *s, size_t n, SemanticValues &vs, Context &c, + std::any &dt) const override; void accept(Visitor &v) override; @@ -1532,16 +1320,16 @@ public: class PrecedenceClimbing : public Ope { public: - using BinOpeInfo = std::map>; + using BinOpeInfo = std::map>; PrecedenceClimbing(const std::shared_ptr &atom, const std::shared_ptr &binop, const BinOpeInfo &info, const Definition &rule) : atom_(atom), binop_(binop), info_(info), rule_(rule) {} - size_t parse_core(const char *s, size_t n, SemanticValues &sv, Context &c, - any &dt) const override { - return parse_expression(s, n, sv, c, dt, 0); + size_t parse_core(const char *s, size_t n, SemanticValues &vs, Context &c, + std::any &dt) const override { + return parse_expression(s, n, vs, c, dt, 0); } void accept(Visitor &v) override; @@ -1552,8 +1340,8 @@ public: const Definition &rule_; private: - size_t parse_expression(const char *s, size_t n, SemanticValues &sv, - Context &c, any &dt, size_t min_prec) const; + size_t parse_expression(const char *s, size_t n, SemanticValues &vs, + Context &c, std::any &dt, size_t min_prec) const; Definition &get_reference_for_binop(Context &c) const; }; @@ -1649,7 +1437,8 @@ inline std::shared_ptr ign(const std::shared_ptr &ope) { } inline std::shared_ptr -usr(std::function +usr(std::function fn) { return std::make_shared(fn); } @@ -1664,7 +1453,7 @@ inline std::shared_ptr wsp(const std::shared_ptr &ope) { return std::make_shared(std::make_shared(ope)); } -inline std::shared_ptr bkr(const std::string &name) { +inline std::shared_ptr bkr(std::string &&name) { return std::make_shared(name); } @@ -1680,68 +1469,61 @@ inline std::shared_ptr pre(const std::shared_ptr &atom, */ struct Ope::Visitor { virtual ~Visitor() {} - virtual void visit(Sequence & /*ope*/) {} - virtual void visit(PrioritizedChoice & /*ope*/) {} - virtual void visit(Repetition & /*ope*/) {} - virtual void visit(AndPredicate & /*ope*/) {} - virtual void visit(NotPredicate & /*ope*/) {} - virtual void visit(Dictionary & /*ope*/) {} - virtual void visit(LiteralString & /*ope*/) {} - virtual void visit(CharacterClass & /*ope*/) {} - virtual void visit(Character & /*ope*/) {} - virtual void visit(AnyCharacter & /*ope*/) {} - virtual void visit(CaptureScope & /*ope*/) {} - virtual void visit(Capture & /*ope*/) {} - virtual void visit(TokenBoundary & /*ope*/) {} - virtual void visit(Ignore & /*ope*/) {} - virtual void visit(User & /*ope*/) {} - virtual void visit(WeakHolder & /*ope*/) {} - virtual void visit(Holder & /*ope*/) {} - virtual void visit(Reference & /*ope*/) {} - virtual void visit(Whitespace & /*ope*/) {} - virtual void visit(BackReference & /*ope*/) {} - virtual void visit(PrecedenceClimbing & /*ope*/) {} + virtual void visit(Sequence &) {} + virtual void visit(PrioritizedChoice &) {} + virtual void visit(Repetition &) {} + virtual void visit(AndPredicate &) {} + virtual void visit(NotPredicate &) {} + virtual void visit(Dictionary &) {} + virtual void visit(LiteralString &) {} + virtual void visit(CharacterClass &) {} + virtual void visit(Character &) {} + virtual void visit(AnyCharacter &) {} + virtual void visit(CaptureScope &) {} + virtual void visit(Capture &) {} + virtual void visit(TokenBoundary &) {} + virtual void visit(Ignore &) {} + virtual void visit(User &) {} + virtual void visit(WeakHolder &) {} + virtual void visit(Holder &) {} + virtual void visit(Reference &) {} + virtual void visit(Whitespace &) {} + virtual void visit(BackReference &) {} + virtual void visit(PrecedenceClimbing &) {} }; struct IsReference : public Ope::Visitor { - using Ope::Visitor::visit; - void visit(Reference & /*ope*/) override { is_reference = true; } + void visit(Reference &) override { is_reference = true; } bool is_reference = false; }; struct TraceOpeName : public Ope::Visitor { - void visit(Sequence & /*ope*/) override { name = "Sequence"; } - void visit(PrioritizedChoice & /*ope*/) override { - name = "PrioritizedChoice"; - } - void visit(Repetition & /*ope*/) override { name = "Repetition"; } - void visit(AndPredicate & /*ope*/) override { name = "AndPredicate"; } - void visit(NotPredicate & /*ope*/) override { name = "NotPredicate"; } - void visit(Dictionary & /*ope*/) override { name = "Dictionary"; } - void visit(LiteralString & /*ope*/) override { name = "LiteralString"; } - void visit(CharacterClass & /*ope*/) override { name = "CharacterClass"; } - void visit(Character & /*ope*/) override { name = "Character"; } - void visit(AnyCharacter & /*ope*/) override { name = "AnyCharacter"; } - void visit(CaptureScope & /*ope*/) override { name = "CaptureScope"; } - void visit(Capture & /*ope*/) override { name = "Capture"; } - void visit(TokenBoundary & /*ope*/) override { name = "TokenBoundary"; } - void visit(Ignore & /*ope*/) override { name = "Ignore"; } - void visit(User & /*ope*/) override { name = "User"; } - void visit(WeakHolder & /*ope*/) override { name = "WeakHolder"; } + void visit(Sequence &) override { name = "Sequence"; } + void visit(PrioritizedChoice &) override { name = "PrioritizedChoice"; } + void visit(Repetition &) override { name = "Repetition"; } + void visit(AndPredicate &) override { name = "AndPredicate"; } + void visit(NotPredicate &) override { name = "NotPredicate"; } + void visit(Dictionary &) override { name = "Dictionary"; } + void visit(LiteralString &) override { name = "LiteralString"; } + void visit(CharacterClass &) override { name = "CharacterClass"; } + void visit(Character &) override { name = "Character"; } + void visit(AnyCharacter &) override { name = "AnyCharacter"; } + void visit(CaptureScope &) override { name = "CaptureScope"; } + void visit(Capture &) override { name = "Capture"; } + void visit(TokenBoundary &) override { name = "TokenBoundary"; } + 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(Reference & /*ope*/) override { name = "Reference"; } - void visit(Whitespace & /*ope*/) override { name = "Whitespace"; } - void visit(BackReference & /*ope*/) override { name = "BackReference"; } - void visit(PrecedenceClimbing & /*ope*/) override { - name = "PrecedenceClimbing"; - } + void visit(Reference &) override { name = "Reference"; } + void visit(Whitespace &) override { name = "Whitespace"; } + void visit(BackReference &) override { name = "BackReference"; } + void visit(PrecedenceClimbing &) override { name = "PrecedenceClimbing"; } const char *name = nullptr; }; struct AssignIDToDefinition : public Ope::Visitor { - using Ope::Visitor::visit; - void visit(Sequence &ope) override { for (auto op : ope.opes_) { op->accept(*this); @@ -1769,8 +1551,6 @@ struct AssignIDToDefinition : public Ope::Visitor { }; struct IsLiteralToken : public Ope::Visitor { - using Ope::Visitor::visit; - void visit(PrioritizedChoice &ope) override { for (auto op : ope.opes_) { if (!IsLiteralToken::check(*op)) { return; } @@ -1778,8 +1558,8 @@ struct IsLiteralToken : public Ope::Visitor { result_ = true; } - void visit(Dictionary & /*ope*/) override { result_ = true; } - void visit(LiteralString & /*ope*/) override { result_ = true; } + void visit(Dictionary &) override { result_ = true; } + void visit(LiteralString &) override { result_ = true; } static bool check(Ope &ope) { IsLiteralToken vis; @@ -1792,8 +1572,6 @@ private: }; struct TokenChecker : public Ope::Visitor { - using Ope::Visitor::visit; - void visit(Sequence &ope) override { for (auto op : ope.opes_) { op->accept(*this); @@ -1807,7 +1585,7 @@ struct TokenChecker : public Ope::Visitor { void visit(Repetition &ope) override { ope.ope_->accept(*this); } void visit(CaptureScope &ope) override { ope.ope_->accept(*this); } void visit(Capture &ope) override { ope.ope_->accept(*this); } - void visit(TokenBoundary & /*ope*/) override { has_token_boundary_ = true; } + void visit(TokenBoundary &) override { has_token_boundary_ = true; } void visit(Ignore &ope) override { ope.ope_->accept(*this); } void visit(WeakHolder &ope) override; void visit(Reference &ope) override; @@ -1862,21 +1640,21 @@ struct DetectLeftRecursion : public Ope::Visitor { ope.ope_->accept(*this); done_ = false; } - void visit(Dictionary & /*ope*/) override { done_ = true; } + void visit(Dictionary &) override { done_ = true; } void visit(LiteralString &ope) override { done_ = !ope.lit_.empty(); } - void visit(CharacterClass & /*ope*/) override { done_ = true; } - void visit(Character & /*ope*/) override { done_ = true; } - void visit(AnyCharacter & /*ope*/) override { done_ = true; } + void visit(CharacterClass &) override { done_ = true; } + void visit(Character &) override { done_ = true; } + void visit(AnyCharacter &) override { done_ = true; } void visit(CaptureScope &ope) override { ope.ope_->accept(*this); } void visit(Capture &ope) override { ope.ope_->accept(*this); } void visit(TokenBoundary &ope) override { ope.ope_->accept(*this); } void visit(Ignore &ope) override { ope.ope_->accept(*this); } - void visit(User & /*ope*/) override { done_ = true; } + void visit(User &) override { done_ = true; } void visit(WeakHolder &ope) override { ope.weak_.lock()->accept(*this); } void visit(Holder &ope) override { ope.ope_->accept(*this); } void visit(Reference &ope) override; void visit(Whitespace &ope) override { ope.ope_->accept(*this); } - void visit(BackReference & /*ope*/) override { done_ = true; } + void visit(BackReference &) override { done_ = true; } void visit(PrecedenceClimbing &ope) override { ope.atom_->accept(*this); } const char *error_s = nullptr; @@ -1888,13 +1666,11 @@ private: }; struct HasEmptyElement : public Ope::Visitor { - using Ope::Visitor::visit; - HasEmptyElement(std::list> &refs) : refs_(refs) {} void visit(Sequence &ope) override { - bool save_is_empty = false; + auto save_is_empty = false; const char *save_error_s = nullptr; std::string save_error_name; for (auto op : ope.opes_) { @@ -1923,8 +1699,8 @@ struct HasEmptyElement : public Ope::Visitor { ope.ope_->accept(*this); } } - void visit(AndPredicate & /*ope*/) override { set_error(); } - void visit(NotPredicate & /*ope*/) override { set_error(); } + void visit(AndPredicate &) override { set_error(); } + void visit(NotPredicate &) override { set_error(); } void visit(LiteralString &ope) override { if (ope.lit_.empty()) { set_error(); } } @@ -1952,8 +1728,6 @@ private: }; struct DetectInfiniteLoop : public Ope::Visitor { - using Ope::Visitor::visit; - DetectInfiniteLoop(const char *s, const std::string &name) { refs_.emplace_back(s, name); } @@ -2004,8 +1778,6 @@ private: }; struct ReferenceChecker : public Ope::Visitor { - using Ope::Visitor::visit; - ReferenceChecker(const Grammar &grammar, const std::vector ¶ms) : grammar_(grammar), params_(params) {} @@ -2042,8 +1814,6 @@ private: }; struct LinkReferences : public Ope::Visitor { - using Ope::Visitor::visit; - LinkReferences(Grammar &grammar, const std::vector ¶ms) : grammar_(grammar), params_(params) {} @@ -2076,8 +1846,6 @@ private: }; struct FindReference : public Ope::Visitor { - using Ope::Visitor::visit; - FindReference(const std::vector> &args, const std::vector ¶ms) : args_(args), params_(params) {} @@ -2155,9 +1923,7 @@ private: }; struct IsPrioritizedChoice : public Ope::Visitor { - using Ope::Visitor::visit; - - void visit(PrioritizedChoice & /*ope*/) override { result_ = true; } + void visit(PrioritizedChoice &) override { result_ = true; } static bool check(Ope &ope) { IsPrioritizedChoice vis; @@ -2209,9 +1975,9 @@ public: } Result parse(const char *s, size_t n, const char *path = nullptr) const { - SemanticValues sv; - any dt; - return parse_core(s, n, sv, dt, path); + SemanticValues vs; + std::any dt; + return parse_core(s, n, vs, dt, path); } Result parse(const char *s, const char *path = nullptr) const { @@ -2219,13 +1985,13 @@ public: return parse(s, n, path); } - Result parse(const char *s, size_t n, any &dt, + Result parse(const char *s, size_t n, std::any &dt, const char *path = nullptr) const { - SemanticValues sv; - return parse_core(s, n, sv, dt, path); + SemanticValues vs; + return parse_core(s, n, vs, dt, path); } - Result parse(const char *s, any &dt, const char *path = nullptr) const { + Result parse(const char *s, std::any &dt, const char *path = nullptr) const { auto n = strlen(s); return parse(s, n, dt, path); } @@ -2233,11 +1999,11 @@ public: template Result parse_and_get_value(const char *s, size_t n, T &val, const char *path = nullptr) const { - SemanticValues sv; - any dt; - auto r = parse_core(s, n, sv, dt, path); - if (r.ret && !sv.empty() && sv.front().has_value()) { - val = any_cast(sv[0]); + SemanticValues vs; + std::any dt; + auto r = parse_core(s, n, vs, dt, path); + if (r.ret && !vs.empty() && vs.front().has_value()) { + val = std::any_cast(vs[0]); } return r; } @@ -2250,27 +2016,24 @@ public: } template - Result parse_and_get_value(const char *s, size_t n, any &dt, T &val, + Result parse_and_get_value(const char *s, size_t n, std::any &dt, T &val, const char *path = nullptr) const { - SemanticValues sv; - auto r = parse_core(s, n, sv, dt, path); - if (r.ret && !sv.empty() && sv.front().has_value()) { - val = any_cast(sv[0]); + SemanticValues vs; + auto r = parse_core(s, n, vs, dt, path); + if (r.ret && !vs.empty() && vs.front().has_value()) { + val = std::any_cast(vs[0]); } return r; } template - Result parse_and_get_value(const char *s, any &dt, T &val, + Result parse_and_get_value(const char *s, std::any &dt, T &val, const char *path = nullptr) const { auto n = strlen(s); return parse_and_get_value(s, n, dt, val, path); } - Action operator=(Action a) { - action = a; - return a; - } + void operator=(Action a) { action = a; } template Definition &operator,(T fn) { operator=(fn); @@ -2298,9 +2061,9 @@ public: size_t id = 0; Action action; - std::function enter; - std::function + std::function enter; + std::function leave; std::function error_message; bool ignoreSemanticValue = false; @@ -2330,7 +2093,7 @@ private: }); } - Result parse_core(const char *s, size_t n, SemanticValues &sv, any &dt, + Result parse_core(const char *s, size_t n, SemanticValues &vs, std::any &dt, const char *path) const { initialize_definition_ids(); @@ -2340,7 +2103,7 @@ private: Context cxt(path, s, n, definition_ids_.size(), whitespaceOpe, wordOpe, enablePackratParsing, tracer_enter, tracer_leave); - auto len = ope->parse(s, n, sv, cxt, dt); + auto len = ope->parse(s, n, vs, cxt, dt); return Result{success(len), len, cxt.error_pos, cxt.message_pos, cxt.message}; } @@ -2357,8 +2120,8 @@ private: * Implementations */ -inline size_t parse_literal(const char *s, size_t n, SemanticValues &sv, - Context &c, any &dt, const std::string &lit, +inline size_t parse_literal(const char *s, size_t n, SemanticValues &vs, + Context &c, std::any &dt, const std::string &lit, std::once_flag &init_is_word, bool &is_word, bool ignore_case) { size_t i = 0; @@ -2374,7 +2137,7 @@ inline size_t parse_literal(const char *s, size_t n, SemanticValues &sv, static Context dummy_c(nullptr, c.s, c.l, 0, nullptr, nullptr, false, nullptr, nullptr); static SemanticValues dummy_sv; - static any dummy_dt; + static std::any dummy_dt; std::call_once(init_is_word, [&]() { if (c.wordOpe) { @@ -2394,7 +2157,7 @@ inline size_t parse_literal(const char *s, size_t n, SemanticValues &sv, // Skip whiltespace if (!c.in_token_boundary_count) { if (c.whitespaceOpe) { - auto len = c.whitespaceOpe->parse(s + i, n - i, sv, c, dt); + auto len = c.whitespaceOpe->parse(s + i, n - i, vs, c, dt); if (fail(len)) { return static_cast(-1); } i += len; } @@ -2404,15 +2167,15 @@ inline size_t parse_literal(const char *s, size_t n, SemanticValues &sv, } inline void Context::trace_enter(const char *name, const char *a_s, size_t n, - SemanticValues &sv, any &dt) const { + SemanticValues &vs, std::any &dt) const { trace_ids.push_back(next_trace_id++); - tracer_enter(name, a_s, n, sv, *this, dt); + tracer_enter(name, a_s, n, vs, *this, dt); } inline void Context::trace_leave(const char *name, const char *a_s, size_t n, - SemanticValues &sv, any &dt, + SemanticValues &vs, std::any &dt, size_t len) const { - tracer_leave(name, a_s, n, sv, *this, dt, len); + tracer_leave(name, a_s, n, vs, *this, dt, len); trace_ids.pop_back(); } @@ -2425,22 +2188,22 @@ inline bool Context::is_traceable(const Ope &ope) const { return false; } -inline size_t Ope::parse(const char *s, size_t n, SemanticValues &sv, - Context &c, any &dt) const { +inline size_t Ope::parse(const char *s, size_t n, SemanticValues &vs, + Context &c, std::any &dt) const { if (c.is_traceable(*this)) { TraceOpeName vis; const_cast(*this).accept(vis); - c.trace_enter(vis.name, s, n, sv, dt); - auto len = parse_core(s, n, sv, c, dt); - c.trace_leave(vis.name, s, n, sv, dt, len); + c.trace_enter(vis.name, s, n, vs, dt); + auto len = parse_core(s, n, vs, c, dt); + c.trace_leave(vis.name, s, n, vs, dt, len); return len; } - return parse_core(s, n, sv, c, dt); + return parse_core(s, n, vs, c, dt); } inline size_t Dictionary::parse_core(const char *s, size_t n, - SemanticValues & /*sv*/, Context &c, - any & /*dt*/) const { + SemanticValues & /*vs*/, Context &c, + std::any & /*dt*/) const { auto len = trie_.match(s, n); if (len > 0) { return len; } c.set_error_pos(s); @@ -2448,28 +2211,28 @@ inline size_t Dictionary::parse_core(const char *s, size_t n, } inline size_t LiteralString::parse_core(const char *s, size_t n, - SemanticValues &sv, Context &c, - any &dt) const { - return parse_literal(s, n, sv, c, dt, lit_, init_is_word_, is_word_, + SemanticValues &vs, Context &c, + std::any &dt) const { + return parse_literal(s, n, vs, c, dt, lit_, init_is_word_, is_word_, ignore_case_); } inline size_t TokenBoundary::parse_core(const char *s, size_t n, - SemanticValues &sv, Context &c, - any &dt) const { + SemanticValues &vs, Context &c, + std::any &dt) const { size_t len; { c.in_token_boundary_count++; - auto se = make_scope_exit([&]() { c.in_token_boundary_count--; }); - len = ope_->parse(s, n, sv, c, dt); + auto se = scope_exit([&]() { c.in_token_boundary_count--; }); + len = ope_->parse(s, n, vs, c, dt); } if (success(len)) { - sv.tokens.emplace_back(std::make_pair(s, len)); + vs.tokens.emplace_back(std::string_view(s, len)); if (!c.in_token_boundary_count) { if (c.whitespaceOpe) { - auto l = c.whitespaceOpe->parse(s + len, n - len, sv, c, dt); + auto l = c.whitespaceOpe->parse(s + len, n - len, vs, c, dt); if (fail(l)) { return static_cast(-1); } len += l; } @@ -2478,8 +2241,8 @@ inline size_t TokenBoundary::parse_core(const char *s, size_t n, return len; } -inline size_t Holder::parse_core(const char *s, size_t n, SemanticValues &sv, - Context &c, any &dt) const { +inline size_t Holder::parse_core(const char *s, size_t n, SemanticValues &vs, + Context &c, std::any &dt) const { if (!ope_) { throw std::logic_error("Uninitialized definition ope was used..."); } @@ -2487,20 +2250,19 @@ inline size_t Holder::parse_core(const char *s, size_t n, SemanticValues &sv, // Macro reference if (outer_->is_macro) { c.rule_stack.push_back(outer_); - auto len = ope_->parse(s, n, sv, c, dt); + auto len = ope_->parse(s, n, vs, c, dt); c.rule_stack.pop_back(); return len; } size_t len; - any val; + std::any val; - c.packrat(s, outer_->id, len, val, [&](any &a_val) { + c.packrat(s, outer_->id, len, val, [&](std::any &a_val) { if (outer_->enter) { outer_->enter(s, n, dt); } - auto se2 = make_scope_exit([&]() { + auto se2 = scope_exit([&]() { c.pop(); - if (outer_->leave) { outer_->leave(s, n, len, a_val, dt); } }); @@ -2512,8 +2274,7 @@ inline size_t Holder::parse_core(const char *s, size_t n, SemanticValues &sv, // Invoke action if (success(len)) { - chldsv.s_ = s; - chldsv.n_ = len; + chldsv.sv_ = std::string_view(s, len); chldsv.name_ = outer_->name; if (!IsPrioritizedChoice::check(*ope_)) { @@ -2537,8 +2298,8 @@ inline size_t Holder::parse_core(const char *s, size_t n, SemanticValues &sv, if (success(len)) { if (!outer_->ignoreSemanticValue) { - sv.emplace_back(std::move(val)); - sv.tags.emplace_back(str2tag(outer_->name.c_str())); + vs.emplace_back(std::move(val)); + vs.tags.emplace_back(str2tag(outer_->name)); } } else { if (outer_->error_message) { @@ -2552,23 +2313,23 @@ inline size_t Holder::parse_core(const char *s, size_t n, SemanticValues &sv, return len; } -inline any Holder::reduce(SemanticValues &sv, any &dt) const { +inline std::any Holder::reduce(SemanticValues &vs, std::any &dt) const { if (outer_->action && !outer_->disable_action) { - return outer_->action(sv, dt); - } else if (sv.empty()) { - return any(); + return outer_->action(vs, dt); + } else if (vs.empty()) { + return std::any(); } else { - return std::move(sv.front()); + return std::move(vs.front()); } } inline const char *Holder::trace_name() const { if (trace_name_.empty()) { trace_name_ = "[" + outer_->name + "]"; } - return trace_name_.c_str(); + return trace_name_.data(); } -inline size_t Reference::parse_core(const char *s, size_t n, SemanticValues &sv, - Context &c, any &dt) const { +inline size_t Reference::parse_core(const char *s, size_t n, SemanticValues &vs, + Context &c, std::any &dt) const { if (rule_) { // Reference rule if (rule_->is_macro) { @@ -2583,20 +2344,20 @@ inline size_t Reference::parse_core(const char *s, size_t n, SemanticValues &sv, } c.push_args(std::move(args)); - auto se = make_scope_exit([&]() { c.pop_args(); }); + auto se = scope_exit([&]() { c.pop_args(); }); auto ope = get_core_operator(); - return ope->parse(s, n, sv, c, dt); + return ope->parse(s, n, vs, c, dt); } else { // Definition c.push_args(std::vector>()); - auto se = make_scope_exit([&]() { c.pop_args(); }); + auto se = scope_exit([&]() { c.pop_args(); }); auto ope = get_core_operator(); - return ope->parse(s, n, sv, c, dt); + return ope->parse(s, n, vs, c, dt); } } else { // Reference parameter in macro const auto &args = c.top_args(); - return args[iarg_]->parse(s, n, sv, c, dt); + return args[iarg_]->parse(s, n, vs, c, dt); } } @@ -2605,8 +2366,8 @@ inline std::shared_ptr Reference::get_core_operator() const { } inline size_t BackReference::parse_core(const char *s, size_t n, - SemanticValues &sv, Context &c, - any &dt) const { + SemanticValues &vs, Context &c, + std::any &dt) const { auto size = static_cast(c.capture_scope_stack_size); for (auto i = size - 1; i >= 0; i--) { auto index = static_cast(i); @@ -2615,7 +2376,7 @@ inline size_t BackReference::parse_core(const char *s, size_t n, const auto &lit = cs.at(name_); std::once_flag init_is_word; auto is_word = false; - return parse_literal(s, n, sv, c, dt, lit, init_is_word, is_word, false); + return parse_literal(s, n, vs, c, dt, lit, init_is_word, is_word, false); } } throw std::runtime_error("Invalid back reference..."); @@ -2635,33 +2396,33 @@ PrecedenceClimbing::get_reference_for_binop(Context &c) const { } inline size_t PrecedenceClimbing::parse_expression(const char *s, size_t n, - SemanticValues &sv, - Context &c, any &dt, + SemanticValues &vs, + Context &c, std::any &dt, size_t min_prec) const { - auto len = atom_->parse(s, n, sv, c, dt); + auto len = atom_->parse(s, n, vs, c, dt); if (fail(len)) { return len; } std::string tok; auto &rule = get_reference_for_binop(c); - auto action = rule.action; + auto action = std::move(rule.action); - rule.action = [&](SemanticValues &sv2, any &dt2) -> any { - tok = sv2.token(); + rule.action = [&](SemanticValues &vs2, std::any &dt2) { + tok = vs2.token(); if (action) { - return action(sv2, dt2); - } else if (!sv2.empty()) { - return sv2[0]; + return action(vs2, dt2); + } else if (!vs2.empty()) { + return vs2[0]; } - return any(); + return std::any(); }; - auto action_se = make_scope_exit([&]() { rule.action = action; }); + auto action_se = scope_exit([&]() { rule.action = std::move(action); }); auto save_error_pos = c.error_pos; auto i = len; while (i < n) { - std::vector save_values(sv.begin(), sv.end()); - auto save_tokens = sv.tokens; + std::vector save_values(vs.begin(), vs.end()); + auto save_tokens = vs.tokens; auto chv = c.push(); auto chl = binop_->parse(s + i, n - i, chv, c, dt); @@ -2680,7 +2441,7 @@ inline size_t PrecedenceClimbing::parse_expression(const char *s, size_t n, if (level < min_prec) { break; } - sv.emplace_back(std::move(chv[0])); + vs.emplace_back(std::move(chv[0])); i += chl; auto next_min_prec = level; @@ -2691,25 +2452,24 @@ inline size_t PrecedenceClimbing::parse_expression(const char *s, size_t n, c.pop(); if (fail(chl)) { - sv.assign(save_values.begin(), save_values.end()); - sv.tokens = save_tokens; + vs.assign(save_values.begin(), save_values.end()); + vs.tokens = save_tokens; c.error_pos = save_error_pos; break; } - sv.emplace_back(std::move(chv[0])); + vs.emplace_back(std::move(chv[0])); i += chl; - any val; + std::any val; if (rule_.action) { - sv.s_ = s; - sv.n_ = i; - val = rule_.action(sv, dt); - } else if (!sv.empty()) { - val = sv[0]; + vs.sv_ = std::string_view(s, i); + val = rule_.action(vs, dt); + } else if (!vs.empty()) { + val = vs[0]; } - sv.clear(); - sv.emplace_back(std::move(val)); + vs.clear(); + vs.emplace_back(std::move(val)); } return i; @@ -2760,7 +2520,7 @@ inline void AssignIDToDefinition::visit(PrecedenceClimbing &ope) { ope.binop_->accept(*this); } -inline void TokenChecker::visit(WeakHolder & /*ope*/) { has_rule_ = true; } +inline void TokenChecker::visit(WeakHolder &) { has_rule_ = true; } inline void TokenChecker::visit(Reference &ope) { if (ope.is_macro_) { @@ -2873,8 +2633,8 @@ inline void FindReference::visit(Reference &ope) { * PEG parser generator *---------------------------------------------------------------------------*/ -typedef std::unordered_map> Rules; -typedef std::function Log; +using Rules = std::unordered_map>; +using Log = std::function; class ParserGenerator { public: @@ -2906,7 +2666,7 @@ private: struct Instruction { std::string type; - any data; + std::any data; }; struct Data { @@ -3061,25 +2821,25 @@ private: } void setup_actions() { - g["Definition"] = [&](const SemanticValues &sv, any &dt) { - Data &data = *any_cast(dt); + g["Definition"] = [&](const SemanticValues &vs, std::any &dt) { + Data &data = *std::any_cast(dt); - auto is_macro = sv.choice() == 0; - auto ignore = any_cast(sv[0]); - auto name = any_cast(sv[1]); + auto is_macro = vs.choice() == 0; + auto ignore = std::any_cast(vs[0]); + auto name = std::any_cast(vs[1]); std::vector params; std::shared_ptr ope; if (is_macro) { - params = any_cast>(sv[2]); - ope = any_cast>(sv[4]); - if (sv.size() == 6) { - data.instructions[name] = any_cast(sv[5]); + params = std::any_cast>(vs[2]); + ope = std::any_cast>(vs[4]); + if (vs.size() == 6) { + data.instructions[name] = std::any_cast(vs[5]); } } else { - ope = any_cast>(sv[3]); - if (sv.size() == 5) { - data.instructions[name] = any_cast(sv[4]); + ope = std::any_cast>(vs[3]); + if (vs.size() == 5) { + data.instructions[name] = std::any_cast(vs[4]); } } @@ -3088,27 +2848,27 @@ private: auto &rule = grammar[name]; rule <= ope; rule.name = name; - rule.s_ = sv.c_str(); + rule.s_ = vs.sv().data(); rule.ignoreSemanticValue = ignore; rule.is_macro = is_macro; rule.params = params; if (data.start.empty()) { data.start = name; - data.start_pos = sv.c_str(); + data.start_pos = vs.sv().data(); } } else { - data.duplicates.emplace_back(name, sv.c_str()); + data.duplicates.emplace_back(name, vs.sv().data()); } }; - g["Expression"] = [&](const SemanticValues &sv) { - if (sv.size() == 1) { - return any_cast>(sv[0]); + g["Expression"] = [&](const SemanticValues &vs) { + if (vs.size() == 1) { + return std::any_cast>(vs[0]); } else { std::vector> opes; - for (auto i = 0u; i < sv.size(); i++) { - opes.emplace_back(any_cast>(sv[i])); + for (auto i = 0u; i < vs.size(); i++) { + opes.emplace_back(std::any_cast>(vs[i])); } const std::shared_ptr ope = std::make_shared(opes); @@ -3116,27 +2876,27 @@ private: } }; - g["Sequence"] = [&](const SemanticValues &sv) { - if (sv.size() == 1) { - return any_cast>(sv[0]); + g["Sequence"] = [&](const SemanticValues &vs) { + if (vs.size() == 1) { + return std::any_cast>(vs[0]); } else { std::vector> opes; - for (const auto &x : sv) { - opes.emplace_back(any_cast>(x)); + for (const auto &x : vs) { + opes.emplace_back(std::any_cast>(x)); } const std::shared_ptr ope = std::make_shared(opes); return ope; } }; - g["Prefix"] = [&](const SemanticValues &sv) { + g["Prefix"] = [&](const SemanticValues &vs) { std::shared_ptr ope; - if (sv.size() == 1) { - ope = any_cast>(sv[0]); + if (vs.size() == 1) { + ope = std::any_cast>(vs[0]); } else { - assert(sv.size() == 2); - auto tok = any_cast(sv[0]); - ope = any_cast>(sv[1]); + assert(vs.size() == 2); + auto tok = std::any_cast(vs[0]); + ope = std::any_cast>(vs[1]); if (tok == '&') { ope = apd(ope); } else { // '!' @@ -3152,13 +2912,13 @@ private: std::pair range; }; - g["Suffix"] = [&](const SemanticValues &sv) { - auto ope = any_cast>(sv[0]); - if (sv.size() == 1) { + g["Suffix"] = [&](const SemanticValues &vs) { + auto ope = std::any_cast>(vs[0]); + if (vs.size() == 1) { return ope; } else { - assert(sv.size() == 2); - auto loop = any_cast(sv[1]); + assert(vs.size() == 2); + auto loop = std::any_cast(vs[1]); switch (loop.type) { case Loop::Type::opt: return opt(ope); case Loop::Type::zom: return zom(ope); @@ -3169,8 +2929,8 @@ private: } }; - g["Loop"] = [&](const SemanticValues &sv) { - switch (sv.choice()) { + g["Loop"] = [&](const SemanticValues &vs) { + switch (vs.choice()) { case 0: // Option return Loop{Loop::Type::opt, std::pair()}; case 1: // Zero or More @@ -3179,53 +2939,50 @@ private: return Loop{Loop::Type::oom, std::pair()}; default: // Regex-like repetition return Loop{Loop::Type::rep, - any_cast>(sv[0])}; + std::any_cast>(vs[0])}; } }; - g["RepetitionRange"] = [&](const SemanticValues &sv) { - switch (sv.choice()) { + g["RepetitionRange"] = [&](const SemanticValues &vs) { + switch (vs.choice()) { case 0: { // Number COMMA Number - auto min = any_cast(sv[0]); - auto max = any_cast(sv[1]); - return std::make_pair(min, max); + auto min = std::any_cast(vs[0]); + auto max = std::any_cast(vs[1]); + return std::pair(min, max); } case 1: // Number COMMA - return std::make_pair(any_cast(sv[0]), - std::numeric_limits::max()); + return std::pair(std::any_cast(vs[0]), + std::numeric_limits::max()); case 2: { // Number - auto n = any_cast(sv[0]); - return std::make_pair(n, n); + auto n = std::any_cast(vs[0]); + return std::pair(n, n); } default: // COMMA Number - return std::make_pair(std::numeric_limits::min(), - any_cast(sv[0])); + return std::pair(std::numeric_limits::min(), + std::any_cast(vs[0])); } }; - g["Number"] = [&](const SemanticValues &sv) { - std::stringstream ss(sv.str()); - size_t n; - ss >> n; - return n; + g["Number"] = [&](const SemanticValues &vs) { + return vs.token_to_number(); }; - g["Primary"] = [&](const SemanticValues &sv, any &dt) { - Data &data = *any_cast(dt); + g["Primary"] = [&](const SemanticValues &vs, std::any &dt) { + Data &data = *std::any_cast(dt); - switch (sv.choice()) { + switch (vs.choice()) { case 0: // Macro Reference case 1: { // Reference - auto is_macro = sv.choice() == 0; - auto ignore = any_cast(sv[0]); - const auto &ident = any_cast(sv[1]); + auto is_macro = vs.choice() == 0; + auto ignore = std::any_cast(vs[0]); + const auto &ident = std::any_cast(vs[1]); std::vector> args; if (is_macro) { - args = any_cast>>(sv[2]); + args = std::any_cast>>(vs[2]); } std::shared_ptr ope = - ref(*data.grammar, ident, sv.c_str(), is_macro, args); + ref(*data.grammar, ident, vs.sv().data(), is_macro, args); if (ignore) { return ign(ope); @@ -3234,110 +2991,111 @@ private: } } case 2: { // (Expression) - return any_cast>(sv[0]); + return std::any_cast>(vs[0]); } case 3: { // TokenBoundary - return tok(any_cast>(sv[0])); + return tok(std::any_cast>(vs[0])); } case 4: { // CaptureScope - return csc(any_cast>(sv[0])); + return csc(std::any_cast>(vs[0])); } case 5: { // Capture - const auto &name = any_cast(sv[0]); - auto ope = any_cast>(sv[1]); + const auto &name = std::any_cast(vs[0]); + auto ope = std::any_cast>(vs[1]); return cap(ope, [name](const char *a_s, size_t a_n, Context &c) { auto &cs = c.capture_scope_stack[c.capture_scope_stack_size - 1]; cs[name] = std::string(a_s, a_n); }); } default: { - return any_cast>(sv[0]); + return std::any_cast>(vs[0]); } } }; - g["IdentCont"] = [](const SemanticValues &sv) { - return std::string(sv.c_str(), sv.length()); + g["IdentCont"] = [](const SemanticValues &vs) { + return std::string(vs.sv().data(), vs.sv().length()); }; - g["Dictionary"] = [](const SemanticValues &sv) { - auto items = sv.transform(); + g["Dictionary"] = [](const SemanticValues &vs) { + auto items = vs.transform(); return dic(items); }; - g["Literal"] = [](const SemanticValues &sv) { - const auto &tok = sv.tokens.front(); - return lit(resolve_escape_sequence(tok.first, tok.second)); + g["Literal"] = [](const SemanticValues &vs) { + const auto &tok = vs.tokens.front(); + return lit(resolve_escape_sequence(tok.data(), tok.size())); }; - g["LiteralI"] = [](const SemanticValues &sv) { - const auto &tok = sv.tokens.front(); - return liti(resolve_escape_sequence(tok.first, tok.second)); + g["LiteralI"] = [](const SemanticValues &vs) { + const auto &tok = vs.tokens.front(); + return liti(resolve_escape_sequence(tok.data(), tok.size())); }; - g["LiteralD"] = [](const SemanticValues &sv) { - auto &tok = sv.tokens.front(); - return resolve_escape_sequence(tok.first, tok.second); + g["LiteralD"] = [](const SemanticValues &vs) { + auto &tok = vs.tokens.front(); + return resolve_escape_sequence(tok.data(), tok.size()); }; - g["Class"] = [](const SemanticValues &sv) { - auto ranges = sv.transform>(); + g["Class"] = [](const SemanticValues &vs) { + auto ranges = vs.transform>(); return cls(ranges); }; - g["NegatedClass"] = [](const SemanticValues &sv) { - auto ranges = sv.transform>(); + g["NegatedClass"] = [](const SemanticValues &vs) { + auto ranges = vs.transform>(); return ncls(ranges); }; - g["Range"] = [](const SemanticValues &sv) { - switch (sv.choice()) { + g["Range"] = [](const SemanticValues &vs) { + switch (vs.choice()) { case 0: { - auto s1 = any_cast(sv[0]); - auto s2 = any_cast(sv[1]); - auto cp1 = decode_codepoint(s1.c_str(), s1.length()); - auto cp2 = decode_codepoint(s2.c_str(), s2.length()); - return std::make_pair(cp1, cp2); + auto s1 = std::any_cast(vs[0]); + auto s2 = std::any_cast(vs[1]); + auto cp1 = decode_codepoint(s1.data(), s1.length()); + auto cp2 = decode_codepoint(s2.data(), s2.length()); + return std::pair(cp1, cp2); } case 1: { - auto s = any_cast(sv[0]); - auto cp = decode_codepoint(s.c_str(), s.length()); - return std::make_pair(cp, cp); + auto s = std::any_cast(vs[0]); + auto cp = decode_codepoint(s.data(), s.length()); + return std::pair(cp, cp); } } - return std::make_pair(0, 0); + return std::pair(0, 0); }; - g["Char"] = [](const SemanticValues &sv) { - return resolve_escape_sequence(sv.c_str(), sv.length()); + g["Char"] = [](const SemanticValues &vs) { + return resolve_escape_sequence(vs.sv().data(), vs.sv().length()); }; - g["AND"] = [](const SemanticValues &sv) { return *sv.c_str(); }; - g["NOT"] = [](const SemanticValues &sv) { return *sv.c_str(); }; - g["QUESTION"] = [](const SemanticValues &sv) { return *sv.c_str(); }; - g["STAR"] = [](const SemanticValues &sv) { return *sv.c_str(); }; - g["PLUS"] = [](const SemanticValues &sv) { return *sv.c_str(); }; + g["AND"] = [](const SemanticValues &vs) { return *vs.sv().data(); }; + g["NOT"] = [](const SemanticValues &vs) { return *vs.sv().data(); }; + g["QUESTION"] = [](const SemanticValues &vs) { return *vs.sv().data(); }; + g["STAR"] = [](const SemanticValues &vs) { return *vs.sv().data(); }; + g["PLUS"] = [](const SemanticValues &vs) { return *vs.sv().data(); }; - g["DOT"] = [](const SemanticValues & /*sv*/) { return dot(); }; + g["DOT"] = [](const SemanticValues & /*vs*/) { return dot(); }; - g["BeginCap"] = [](const SemanticValues &sv) { return sv.token(); }; + g["BeginCap"] = [](const SemanticValues &vs) { return vs.token(); }; - g["BackRef"] = [&](const SemanticValues &sv) { return bkr(sv.token()); }; + g["BackRef"] = [&](const SemanticValues &vs) { + return bkr(vs.token_to_string()); + }; - g["Ignore"] = [](const SemanticValues &sv) { return sv.size() > 0; }; + g["Ignore"] = [](const SemanticValues &vs) { return vs.size() > 0; }; - g["Parameters"] = [](const SemanticValues &sv) { - return sv.transform(); + g["Parameters"] = [](const SemanticValues &vs) { + return vs.transform(); }; - g["Arguments"] = [](const SemanticValues &sv) { - return sv.transform>(); + g["Arguments"] = [](const SemanticValues &vs) { + return vs.transform>(); }; - g["PrecedenceClimbing"] = [](const SemanticValues &sv) { + g["PrecedenceClimbing"] = [](const SemanticValues &vs) { PrecedenceClimbing::BinOpeInfo binOpeInfo; size_t level = 1; - for (auto v : sv) { - auto tokens = any_cast>(v); + for (auto v : vs) { + auto tokens = std::any_cast>(v); auto assoc = tokens[0][0]; for (size_t i = 1; i < tokens.size(); i++) { - const auto &tok = tokens[i]; - binOpeInfo[tok] = std::make_pair(level, assoc); + binOpeInfo[tokens[i]] = std::pair(level, assoc); } level++; } @@ -3346,11 +3104,11 @@ private: instruction.data = binOpeInfo; return instruction; }; - g["PrecedenceInfo"] = [](const SemanticValues &sv) { - return sv.transform(); + g["PrecedenceInfo"] = [](const SemanticValues &vs) { + return vs.transform(); }; - g["PrecedenceOpe"] = [](const SemanticValues &sv) { return sv.token(); }; - g["PrecedenceAssoc"] = [](const SemanticValues &sv) { return sv.token(); }; + g["PrecedenceOpe"] = [](const SemanticValues &vs) { return vs.token(); }; + g["PrecedenceAssoc"] = [](const SemanticValues &vs) { return vs.token(); }; } bool apply_precedence_instruction(Definition &rule, @@ -3396,7 +3154,7 @@ private: const Rules &rules, std::string &start, Log log) { Data data; - any dt = &data; + std::any dt = &data; auto r = g["Grammar"].parse(s, n, dt); if (!r.ret) { @@ -3417,7 +3175,7 @@ private: // User provided rules for (const auto &x : rules) { auto name = x.first; - bool ignore = false; + auto ignore = false; if (!name.empty() && name[0] == '~') { ignore = true; name.erase(0, 1); @@ -3431,7 +3189,7 @@ private: } // Check duplicated definitions - bool ret = data.duplicates.empty(); + auto ret = data.duplicates.empty(); for (const auto &x : data.duplicates) { if (log) { @@ -3546,7 +3304,7 @@ private: if (instruction.type == "precedence") { const auto &info = - any_cast(instruction.data); + std::any_cast(instruction.data); if (!apply_precedence_instruction(rule, info, s, log)) { return nullptr; @@ -3581,8 +3339,9 @@ template struct AstBase : public Annotation { nodes(a_nodes) {} AstBase(const char *a_path, size_t a_line, size_t a_column, - const char *a_name, const std::string &a_token, size_t a_position = 0, - size_t a_length = 0, size_t a_choice_count = 0, size_t a_choice = 0) + const char *a_name, const std::string_view &a_token, + size_t a_position = 0, size_t a_length = 0, size_t a_choice_count = 0, + size_t a_choice = 0) : path(a_path ? a_path : ""), line(a_line), column(a_column), name(a_name), position(a_position), length(a_length), choice_count(a_choice_count), choice(a_choice), original_name(a_name), @@ -3617,10 +3376,22 @@ template struct AstBase : public Annotation { const unsigned int original_tag; const bool is_token; - const std::string token; + const std::string_view token; std::vector>> nodes; std::weak_ptr> parent; + + std::string token_to_string() const { + assert(is_token); + return std::string(token); + } + + template T token_to_number() const { + assert(is_token); + T n = 0; + std::from_chars(token.data(), token.data() + token.size(), n); + return n; + } }; template @@ -3636,7 +3407,9 @@ void ast_to_s_core(const std::shared_ptr &ptr, std::string &s, int level, } if (ast.name != ast.original_name) { name += "[" + ast.name + "]"; } if (ast.is_token) { - s += "- " + name + " (" + ast.token + ")\n"; + s += "- " + name + " ("; + s += ast.token; + s += ")\n"; } else { s += "+ " + name + "\n"; } @@ -3668,7 +3441,7 @@ struct AstOptimizer { if (opt && original->nodes.size() == 1) { auto child = optimize(original->nodes[0], parent); - return std::make_shared(*child, original->name.c_str(), + return std::make_shared(*child, original->name.data(), original->choice_count, original->position, original->length, original->choice); } @@ -3689,23 +3462,24 @@ private: }; struct EmptyType {}; -typedef AstBase Ast; +using Ast = AstBase; template void add_ast_action(Definition &rule) { - rule.action = [&](const SemanticValues &sv) { - auto line = sv.line_info(); + rule.action = [&](const SemanticValues &vs) { + auto line = vs.line_info(); if (rule.is_token()) { - return std::make_shared(sv.path, line.first, line.second, - rule.name.c_str(), sv.token(), - std::distance(sv.ss, sv.c_str()), sv.length(), - sv.choice_count(), sv.choice()); + return std::make_shared( + vs.path, line.first, line.second, rule.name.data(), vs.token(), + std::distance(vs.ss, vs.sv().data()), vs.sv().length(), + vs.choice_count(), vs.choice()); } - auto ast = std::make_shared( - sv.path, line.first, line.second, rule.name.c_str(), - sv.transform>(), std::distance(sv.ss, sv.c_str()), - sv.length(), sv.choice_count(), sv.choice()); + auto ast = + std::make_shared(vs.path, line.first, line.second, rule.name.data(), + vs.transform>(), + std::distance(vs.ss, vs.sv().data()), + vs.sv().length(), vs.choice_count(), vs.choice()); for (auto node : ast->nodes) { node->parent = ast; @@ -3899,7 +3673,7 @@ public: return parse_n(s, n, path); } - bool parse_n(const char *s, size_t n, any &dt, + bool parse_n(const char *s, size_t n, std::any &dt, const char *path = nullptr) const { if (grammar_ != nullptr) { const auto &rule = (*grammar_)[start_]; @@ -3910,7 +3684,7 @@ public: return false; } - bool parse(const char *s, any &dt, const char *path = nullptr) const { + bool parse(const char *s, std::any &dt, const char *path = nullptr) const { auto n = strlen(s); return parse_n(s, n, dt, path); } @@ -3934,7 +3708,7 @@ public: } template - bool parse_n(const char *s, size_t n, any &dt, T &val, + bool parse_n(const char *s, size_t n, std::any &dt, T &val, const char *path = nullptr) const { if (grammar_ != nullptr) { const auto &rule = (*grammar_)[start_]; @@ -3946,7 +3720,7 @@ public: } template - bool parse(const char *s, any &dt, T &val, + bool parse(const char *s, std::any &dt, T &val, const char * /*path*/ = nullptr) const { auto n = strlen(s); return parse_n(s, n, dt, val); @@ -4013,7 +3787,3 @@ private: }; } // namespace peg - -#endif - -// vim: et ts=2 sw=2 cin cino={1s ff=unix diff --git a/pl0/CMakeLists.txt b/pl0/CMakeLists.txt index 8485819..5d88b45 100644 --- a/pl0/CMakeLists.txt +++ b/pl0/CMakeLists.txt @@ -1,14 +1,11 @@ cmake_minimum_required(VERSION 3.1) -project(tcp) - -enable_language(CXX) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_EXTENSIONS OFF) +project(pl0) include_directories(..) -add_executable(pl0 pl0.cc) +set(CMAKE_CXX_STANDARD 17) + +add_executable(pl0 pl0.cc) find_package(LLVM REQUIRED CONFIG) set(add_link_deps ${add_link_deps} LLVM) target_include_directories(pl0 PUBLIC ${LLVM_INCLUDE_DIRS}) diff --git a/pl0/pl0.cc b/pl0/pl0.cc index 6598c36..6ce8544 100644 --- a/pl0/pl0.cc +++ b/pl0/pl0.cc @@ -182,11 +182,11 @@ struct SymbolTable { // _)? const auto& nodes = ast->nodes; for (auto i = 0u; i < nodes.size(); i += 2) { - const auto& ident = nodes[i + 0]->token; + const auto& ident = nodes[i + 0]->token_to_string(); if (scope->has_symbol(ident)) { throw_runtime_error(nodes[i], "'" + ident + "' is already defined..."); } - auto number = stoi(nodes[i + 1]->token); + auto number = nodes[i + 1]->token_to_number(); scope->constants.emplace(ident, number); } } @@ -196,7 +196,7 @@ struct SymbolTable { // var <- ('VAR' __ ident(',' _ ident)* ';' _) ? const auto& nodes = ast->nodes; for (auto i = 0u; i < nodes.size(); i += 1) { - const auto& ident = nodes[i]->token; + const auto& ident = nodes[i]->token_to_string(); if (scope->has_symbol(ident)) { throw_runtime_error(nodes[i], "'" + ident + "' is already defined..."); } @@ -209,7 +209,7 @@ struct SymbolTable { // procedure <- ('PROCEDURE' __ ident ';' _ block ';' _)* const auto& nodes = ast->nodes; for (auto i = 0u; i < nodes.size(); i += 2) { - const auto& ident = nodes[i + 0]->token; + const auto& ident = nodes[i + 0]->token_to_string(); auto block = nodes[i + 1]; scope->procedures[ident] = block; build_on_ast(block, scope); @@ -219,7 +219,7 @@ struct SymbolTable { static void assignment(const shared_ptr ast, shared_ptr scope) { // assignment <- ident ':=' _ expression - const auto& ident = ast->nodes[0]->token; + const auto& ident = ast->nodes[0]->token_to_string(); if (scope->has_constant(ident)) { throw_runtime_error(ast->nodes[0], "cannot modify constant value '" + ident + "'..."); @@ -238,7 +238,7 @@ struct SymbolTable { static void call(const shared_ptr ast, shared_ptr scope) { // call <- 'CALL' __ ident - const auto& ident = ast->nodes[0]->token; + const auto& ident = ast->nodes[0]->token_to_string(); if (!scope->has_procedure(ident)) { throw_runtime_error(ast->nodes[0], "undefined procedure '" + ident + "'..."); @@ -256,7 +256,7 @@ struct SymbolTable { static void ident(const shared_ptr ast, shared_ptr scope) { - const auto& ident = ast->token; + const auto& ident = ast->token_to_string(); if (!scope->has_symbol(ident)) { throw_runtime_error(ast, "undefined variable '" + ident + "'..."); } @@ -360,13 +360,13 @@ struct Interpreter { static void exec_assignment(const shared_ptr ast, shared_ptr env) { // assignment <- ident ':=' _ expression - env->set_variable(ast->nodes[0]->token, eval(ast->nodes[1], env)); + env->set_variable(ast->nodes[0]->token_to_string(), eval(ast->nodes[1], env)); } static void exec_call(const shared_ptr ast, shared_ptr env) { // call <- 'CALL' __ ident - exec_block(env->get_procedure(ast->nodes[0]->token), env); + exec_block(env->get_procedure(ast->nodes[0]->token_to_string()), env); } static void exec_statements(const shared_ptr ast, @@ -406,7 +406,7 @@ struct Interpreter { // in <- ('in' __ / 'read' __ / '?' _) ident int val; cin >> val; - env->set_variable(ast->nodes[0]->token, val); + env->set_variable(ast->nodes[0]->token_to_string(), val); } static bool eval_condition(const shared_ptr ast, @@ -434,7 +434,7 @@ struct Interpreter { // compare <- expression compare_op expression const auto& nodes = ast->nodes; auto lval = eval_expression(nodes[0], env); - auto op = peg::str2tag(nodes[1]->token.c_str()); + auto op = peg::str2tag(nodes[1]->token_to_string().c_str()); auto rval = eval_expression(nodes[2], env); switch (op) { case "="_: @@ -473,11 +473,11 @@ struct Interpreter { shared_ptr env) { // expression <- sign term (term_op term)* const auto& nodes = ast->nodes; - auto sign = nodes[0]->token; + auto sign = nodes[0]->token_to_string(); auto sign_val = (sign.empty() || sign == "+") ? 1 : -1; auto val = eval(nodes[1], env) * sign_val; for (auto i = 2u; i < nodes.size(); i += 2) { - auto ope = nodes[i + 0]->token[0]; + auto ope = nodes[i + 0]->token_to_string()[0]; auto rval = eval(nodes[i + 1], env); switch (ope) { case '+': @@ -497,7 +497,7 @@ struct Interpreter { const auto& nodes = ast->nodes; auto val = eval(nodes[0], env); for (auto i = 1u; i < nodes.size(); i += 2) { - auto ope = nodes[i + 0]->token[0]; + auto ope = nodes[i + 0]->token_to_string()[0]; auto rval = eval(nodes[i + 1], env); switch (ope) { case '*': @@ -516,12 +516,12 @@ struct Interpreter { static int eval_ident(const shared_ptr ast, shared_ptr env) { - return env->get_value(ast, ast->token); + return env->get_value(ast, ast->token_to_string()); } static int eval_number(const shared_ptr ast, shared_ptr env) { - return stol(ast->token); + return stol(ast->token_to_string()); } }; @@ -653,8 +653,8 @@ struct LLVM { void compile_const(const shared_ptr ast) { for (auto i = 0u; i < ast->nodes.size(); i += 2) { - auto ident = ast->nodes[i]->token; - auto number = stoi(ast->nodes[i + 1]->token); + auto ident = ast->nodes[i]->token_to_string(); + auto number = stoi(ast->nodes[i + 1]->token_to_string()); auto alloca = builder_.CreateAlloca(builder_.getInt32Ty(), nullptr, ident); @@ -664,14 +664,14 @@ struct LLVM { void compile_var(const shared_ptr ast) { for (const auto node : ast->nodes) { - auto ident = node->token; + auto ident = node->token_to_string(); builder_.CreateAlloca(builder_.getInt32Ty(), nullptr, ident); } } void compile_procedure(const shared_ptr ast) { for (auto i = 0u; i < ast->nodes.size(); i += 2) { - auto ident = ast->nodes[i]->token; + auto ident = ast->nodes[i]->token_to_string(); auto block = ast->nodes[i + 1]; std::vector pt(block->scope->free_variables.size(), @@ -712,7 +712,7 @@ struct LLVM { } void compile_assignment(const shared_ptr ast) { - auto ident = ast->nodes[0]->token; + auto ident = ast->nodes[0]->token_to_string(); auto fn = builder_.GetInsertBlock()->getParent(); auto tbl = fn->getValueSymbolTable(); @@ -726,7 +726,7 @@ struct LLVM { } void compile_call(const shared_ptr ast) { - auto ident = ast->nodes[0]->token; + auto ident = ast->nodes[0]->token_to_string(); auto scope = get_closest_scope(ast); auto block = scope->get_procedure(ident); @@ -805,7 +805,7 @@ struct LLVM { auto lhs = compile_expression(ast->nodes[0]); auto rhs = compile_expression(ast->nodes[2]); - const auto& ope = ast->nodes[1]->token; + const auto& ope = ast->nodes[1]->token_to_string(); switch (ope[0]) { case '=': return builder_.CreateICmpEQ(lhs, rhs, "icmpeq"); @@ -836,7 +836,7 @@ struct LLVM { Value* compile_expression(const shared_ptr ast) { const auto& nodes = ast->nodes; - auto sign = nodes[0]->token; + auto sign = nodes[0]->token_to_string(); auto negative = !(sign.empty() || sign == "+"); auto val = compile_term(nodes[1]); @@ -845,7 +845,7 @@ struct LLVM { } for (auto i = 2u; i < nodes.size(); i += 2) { - auto ope = nodes[i + 0]->token[0]; + auto ope = nodes[i + 0]->token_to_string()[0]; auto rval = compile_term(nodes[i + 1]); switch (ope) { case '+': @@ -863,7 +863,7 @@ struct LLVM { const auto& nodes = ast->nodes; auto val = compile_factor(nodes[0]); for (auto i = 1u; i < nodes.size(); i += 2) { - auto ope = nodes[i + 0]->token[0]; + auto ope = nodes[i + 0]->token_to_string()[0]; auto rval = compile_switch_value(nodes[i + 1]); switch (ope) { case '*': @@ -889,7 +889,7 @@ struct LLVM { } Value* compile_ident(const shared_ptr ast) { - auto ident = ast->token; + auto ident = ast->token_to_string(); auto fn = builder_.GetInsertBlock()->getParent(); auto tbl = fn->getValueSymbolTable(); @@ -903,7 +903,7 @@ struct LLVM { Value* compile_number(const shared_ptr ast) { return ConstantInt::getIntegerValue(builder_.getInt32Ty(), - APInt(32, ast->token, 10)); + APInt(32, ast->token_to_string(), 10)); } }; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9944772..1a1da03 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,13 +1,14 @@ cmake_minimum_required(VERSION 3.1) project(test) -enable_language(CXX) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_EXTENSIONS OFF) - include_directories(..) + +set(CMAKE_CXX_STANDARD 17) + add_executable(test-main test-main.cc test1.cc test2.cc test3.cc) target_link_libraries(test-main ${add_link_deps}) -add_test(TestMain test-main) +add_test( + NAME TestMain + COMMAND test-main + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/test/test1.cc b/test/test1.cc index a583e81..dcde402 100644 --- a/test/test1.cc +++ b/test/test1.cc @@ -4,198 +4,178 @@ using namespace peg; #if !defined(PEGLIB_NO_UNICODE_CHARS) -TEST_CASE("Simple syntax test (with unicode)", "[general]") -{ - parser parser( - u8" ROOT ← _ " - " _ <- ' ' " - ); - - bool ret = parser; - REQUIRE(ret == true); +TEST_CASE("Simple syntax test (with unicode)", "[general]") { + parser parser(u8" ROOT ← _ " + " _ <- ' ' "); + + bool ret = parser; + REQUIRE(ret == true); } #endif -TEST_CASE("Simple syntax test", "[general]") -{ - parser parser(R"( +TEST_CASE("Simple syntax test", "[general]") { + parser parser(R"( ROOT <- _ _ <- ' ' )"); - bool ret = parser; - REQUIRE(ret == true); + bool ret = parser; + REQUIRE(ret == true); } -TEST_CASE("Empty syntax test", "[general]") -{ - parser parser(""); - bool ret = parser; - REQUIRE(ret == false); +TEST_CASE("Empty syntax test", "[general]") { + parser parser(""); + bool ret = parser; + REQUIRE(ret == false); } -TEST_CASE("Start rule with ignore operator test", "[general]") -{ - parser parser(R"( +TEST_CASE("Start rule with ignore operator test", "[general]") { + parser parser(R"( ~ROOT <- _ _ <- ' ' )"); - bool ret = parser; - REQUIRE(ret == false); + bool ret = parser; + REQUIRE(ret == false); } -TEST_CASE("Invalid UTF-8 text test", "[general]") -{ - std::string s = "a <- '"; - s += static_cast(0xe8); // Make invalid utf8 text... +TEST_CASE("Invalid UTF-8 text test", "[general]") { + std::string s = "a <- '"; + s += static_cast(0xe8); // Make invalid utf8 text... - parser parser(s.c_str()); + parser parser(s.data()); - bool ret = parser; - REQUIRE(ret == false); + bool ret = parser; + REQUIRE(ret == false); } -TEST_CASE("Backslash escape sequence test", "[general]") -{ - parser parser(R"( +TEST_CASE("Backslash escape sequence test", "[general]") { + parser parser(R"( ROOT <- _ _ <- '\\' )"); - bool ret = parser; - REQUIRE(ret == true); + bool ret = parser; + REQUIRE(ret == true); } -TEST_CASE("Invalid escape sequence test", "[general]") -{ - parser parser(R"( +TEST_CASE("Invalid escape sequence test", "[general]") { + parser parser(R"( ROOT <- _ _ <- '\' )"); - bool ret = parser; - REQUIRE(ret == false); + bool ret = parser; + REQUIRE(ret == false); } -TEST_CASE("Action taking non const Semantic Values parameter", "[general]") -{ - parser parser(R"( +TEST_CASE("Action taking non const Semantic Values parameter", "[general]") { + parser parser(R"( ROOT <- TEXT TEXT <- [a-zA-Z]+ )"); - parser["ROOT"] = [&](SemanticValues& sv) { - auto s = any_cast(sv[0]); - s[0] = 'H'; // mutate - return std::string(std::move(s)); // move - }; + parser["ROOT"] = [&](SemanticValues &vs) { + auto s = std::string(std::any_cast(vs[0])); + s[0] = 'H'; // mutate + return s; // move + }; - parser["TEXT"] = [&](SemanticValues& sv) { - return sv.token(); - }; + parser["TEXT"] = [&](SemanticValues &vs) { return vs.token(); }; - std::string val; - auto ret = parser.parse("hello", val); - REQUIRE(ret == true); - REQUIRE(val == "Hello"); + std::string val; + auto ret = parser.parse("hello", val); + REQUIRE(ret == true); + REQUIRE(val == "Hello"); } -TEST_CASE("String capture test", "[general]") -{ - parser parser(R"( +TEST_CASE("String capture test", "[general]") { + parser parser(R"( ROOT <- _ ('[' TAG_NAME ']' _)* TAG_NAME <- (!']' .)+ _ <- [ \t]* )"); - std::vector tags; + std::vector tags; - parser["TAG_NAME"] = [&](const SemanticValues& sv) { - tags.push_back(sv.str()); - }; + parser["TAG_NAME"] = [&](const SemanticValues &vs) { + tags.push_back(vs.sv()); + }; - auto ret = parser.parse(" [tag1] [tag:2] [tag-3] "); + auto ret = parser.parse(" [tag1] [tag:2] [tag-3] "); - REQUIRE(ret == true); - REQUIRE(tags.size() == 3); - REQUIRE(tags[0] == "tag1"); - REQUIRE(tags[1] == "tag:2"); - REQUIRE(tags[2] == "tag-3"); + REQUIRE(ret == true); + REQUIRE(tags.size() == 3); + REQUIRE(tags[0] == "tag1"); + REQUIRE(tags[1] == "tag:2"); + REQUIRE(tags[2] == "tag-3"); } using namespace peg; -TEST_CASE("String capture test2", "[general]") -{ - std::vector tags; +TEST_CASE("String capture test2", "[general]") { + std::vector tags; - Definition ROOT, TAG, TAG_NAME, WS; - ROOT <= seq(WS, zom(TAG)); - TAG <= seq(chr('['), TAG_NAME, chr(']'), WS); - TAG_NAME <= oom(seq(npd(chr(']')), dot())), [&](const SemanticValues& sv) { tags.push_back(sv.str()); }; - WS <= zom(cls(" \t")); + Definition ROOT, TAG, TAG_NAME, WS; + ROOT <= seq(WS, zom(TAG)); + TAG <= seq(chr('['), TAG_NAME, chr(']'), WS); + TAG_NAME <= oom(seq(npd(chr(']')), dot())), + [&](const SemanticValues &vs) { tags.push_back(vs.sv()); }; + WS <= zom(cls(" \t")); - auto r = ROOT.parse(" [tag1] [tag:2] [tag-3] "); + auto r = ROOT.parse(" [tag1] [tag:2] [tag-3] "); - REQUIRE(r.ret == true); - REQUIRE(tags.size() == 3); - REQUIRE(tags[0] == "tag1"); - REQUIRE(tags[1] == "tag:2"); - REQUIRE(tags[2] == "tag-3"); + REQUIRE(r.ret == true); + REQUIRE(tags.size() == 3); + REQUIRE(tags[0] == "tag1"); + REQUIRE(tags[1] == "tag:2"); + REQUIRE(tags[2] == "tag-3"); } -TEST_CASE("String capture test3", "[general]") -{ - parser pg(R"( +TEST_CASE("String capture test3", "[general]") { + parser pg(R"( ROOT <- _ TOKEN* TOKEN <- '[' < (!']' .)+ > ']' _ _ <- [ \t\r\n]* )"); + std::vector tags; - std::vector tags; + pg["TOKEN"] = [&](const SemanticValues &vs) { tags.push_back(vs.token()); }; - pg["TOKEN"] = [&](const SemanticValues& sv) { - tags.push_back(sv.token()); - }; + auto ret = pg.parse(" [tag1] [tag:2] [tag-3] "); - auto ret = pg.parse(" [tag1] [tag:2] [tag-3] "); - - REQUIRE(ret == true); - REQUIRE(tags.size() == 3); - REQUIRE(tags[0] == "tag1"); - REQUIRE(tags[1] == "tag:2"); - REQUIRE(tags[2] == "tag-3"); + REQUIRE(ret == true); + REQUIRE(tags.size() == 3); + REQUIRE(tags[0] == "tag1"); + REQUIRE(tags[1] == "tag:2"); + REQUIRE(tags[2] == "tag-3"); } -TEST_CASE("Cyclic grammer test", "[general]") -{ - Definition PARENT; - Definition CHILD; +TEST_CASE("Cyclic grammer test", "[general]") { + Definition PARENT; + Definition CHILD; - PARENT <= seq(CHILD); - CHILD <= seq(PARENT); + PARENT <= seq(CHILD); + CHILD <= seq(PARENT); } -TEST_CASE("Visit test", "[general]") -{ - Definition ROOT, TAG, TAG_NAME, WS; +TEST_CASE("Visit test", "[general]") { + Definition ROOT, TAG, TAG_NAME, WS; - ROOT <= seq(WS, zom(TAG)); - TAG <= seq(chr('['), TAG_NAME, chr(']'), WS); - TAG_NAME <= oom(seq(npd(chr(']')), dot())); - WS <= zom(cls(" \t")); + ROOT <= seq(WS, zom(TAG)); + TAG <= seq(chr('['), TAG_NAME, chr(']'), WS); + TAG_NAME <= oom(seq(npd(chr(']')), dot())); + WS <= zom(cls(" \t")); - AssignIDToDefinition defIds; - ROOT.accept(defIds); + AssignIDToDefinition defIds; + ROOT.accept(defIds); - REQUIRE(defIds.ids.size() == 4); + REQUIRE(defIds.ids.size() == 4); } -TEST_CASE("Token check test", "[general]") -{ - parser parser(R"( +TEST_CASE("Token check test", "[general]") { + parser parser(R"( EXPRESSION <- _ TERM (TERM_OPERATOR TERM)* TERM <- FACTOR (FACTOR_OPERATOR FACTOR)* FACTOR <- NUMBER / '(' _ EXPRESSION ')' _ @@ -205,78 +185,74 @@ TEST_CASE("Token check test", "[general]") _ <- [ \t\r\n]* )"); - REQUIRE(parser["EXPRESSION"].is_token() == false); - REQUIRE(parser["FACTOR"].is_token() == false); - REQUIRE(parser["FACTOR_OPERATOR"].is_token() == true); - REQUIRE(parser["NUMBER"].is_token() == true); - REQUIRE(parser["_"].is_token() == true); + REQUIRE(parser["EXPRESSION"].is_token() == false); + REQUIRE(parser["FACTOR"].is_token() == false); + REQUIRE(parser["FACTOR_OPERATOR"].is_token() == true); + REQUIRE(parser["NUMBER"].is_token() == true); + REQUIRE(parser["_"].is_token() == true); } -TEST_CASE("Lambda action test", "[general]") -{ - parser parser(R"( +TEST_CASE("Lambda action test", "[general]") { + parser parser(R"( START <- (CHAR)* CHAR <- . )"); - std::string ss; - parser["CHAR"] = [&](const SemanticValues& sv) { - ss += *sv.c_str(); - }; + std::string ss; + parser["CHAR"] = [&](const SemanticValues &vs) { ss += *vs.sv().data(); }; - bool ret = parser.parse("hello"); - REQUIRE(ret == true); - REQUIRE(ss == "hello"); + bool ret = parser.parse("hello"); + REQUIRE(ret == true); + REQUIRE(ss == "hello"); } -TEST_CASE("enter/leave handlers test", "[general]") -{ - parser parser(R"( +TEST_CASE("enter/leave handlers test", "[general]") { + parser parser(R"( START <- LTOKEN '=' RTOKEN LTOKEN <- TOKEN RTOKEN <- TOKEN TOKEN <- [A-Za-z]+ )"); - parser["LTOKEN"].enter = [&](const char*, size_t, any& dt) { - auto& require_upper_case = *any_cast(dt); - require_upper_case = false; - }; - parser["LTOKEN"].leave = [&](const char*, size_t, size_t, any&, any& dt) { - auto& require_upper_case = *any_cast(dt); - require_upper_case = true; - }; + parser["LTOKEN"].enter = [&](const char *, size_t, std::any &dt) { + auto &require_upper_case = *std::any_cast(dt); + require_upper_case = false; + }; + parser["LTOKEN"].leave = [&](const char *, size_t, size_t, std::any &, + std::any &dt) { + auto &require_upper_case = *std::any_cast(dt); + require_upper_case = true; + }; - auto message = "should be upper case string..."; + auto message = "should be upper case string..."; - parser["TOKEN"] = [&](const SemanticValues& sv, any& dt) { - auto& require_upper_case = *any_cast(dt); - if (require_upper_case) { - const auto& s = sv.str(); - if (!std::all_of(s.begin(), s.end(), ::isupper)) { - throw parse_error(message); - } - } - }; + parser["TOKEN"] = [&](const SemanticValues &vs, std::any &dt) { + auto &require_upper_case = *std::any_cast(dt); + if (require_upper_case) { + const auto &s = vs.sv(); + if (!std::all_of(s.begin(), s.end(), ::isupper)) { + throw parse_error(message); + } + } + }; - bool require_upper_case = false; - any dt = &require_upper_case; - REQUIRE(parser.parse("hello=world", dt) == false); - REQUIRE(parser.parse("HELLO=world", dt) == false); - REQUIRE(parser.parse("hello=WORLD", dt) == true); - REQUIRE(parser.parse("HELLO=WORLD", dt) == true); - - parser.log = [&](size_t ln, size_t col, const std::string& msg) { - REQUIRE(ln == 1); - REQUIRE(col == 7); - REQUIRE(msg == message); - }; - parser.parse("hello=world", dt); + bool require_upper_case = false; + std::any dt = &require_upper_case; + REQUIRE(parser.parse("hello=world", dt) == false); + REQUIRE(parser.parse("HELLO=world", dt) == false); + REQUIRE(parser.parse("hello=WORLD", dt) == true); + REQUIRE(parser.parse("HELLO=WORLD", dt) == true); + + parser.log = [&](size_t ln, size_t col, const std::string &msg) { + REQUIRE(ln == 1); + REQUIRE(col == 7); + REQUIRE(msg == message); + }; + parser.parse("hello=world", dt); } -TEST_CASE("WHITESPACE test", "[general]") -{ - parser parser(R"( +TEST_CASE("WHITESPACE test", "[general]") { + parser parser(R"( # Rules ROOT <- ITEM (',' ITEM)* ITEM <- WORD / PHRASE @@ -288,14 +264,13 @@ TEST_CASE("WHITESPACE test", "[general]") %whitespace <- [ \t\r\n]* )"); - auto ret = parser.parse(R"( one, "two, three", four )"); + auto ret = parser.parse(R"( one, "two, three", four )"); - REQUIRE(ret == true); + REQUIRE(ret == true); } -TEST_CASE("WHITESPACE test2", "[general]") -{ - parser parser(R"( +TEST_CASE("WHITESPACE test2", "[general]") { + parser parser(R"( # Rules ROOT <- ITEM (',' ITEM)* ITEM <- '[' < [a-zA-Z0-9_]+ > ']' @@ -305,22 +280,22 @@ TEST_CASE("WHITESPACE test2", "[general]") TAB <- '\t' )"); - std::vector items; - parser["ITEM"] = [&](const SemanticValues& sv) { - items.push_back(sv.token()); - }; + std::vector items; + parser["ITEM"] = [&](const SemanticValues &vs) { + items.push_back(vs.token()); + }; - auto ret = parser.parse(R"([one], [two] ,[three] )"); + auto ret = parser.parse(R"([one], [two] ,[three] )"); - REQUIRE(ret == true); - REQUIRE(items.size() == 3); - REQUIRE(items[0] == "one"); - REQUIRE(items[1] == "two"); - REQUIRE(items[2] == "three"); + REQUIRE(ret == true); + REQUIRE(items.size() == 3); + REQUIRE(items[0] == "one"); + REQUIRE(items[1] == "two"); + REQUIRE(items[2] == "three"); } TEST_CASE("WHITESPACE test3", "[general]") { - parser parser(R"( + parser parser(R"( StrQuot <- < '"' < (StrEscape / StrChars)* > '"' > StrEscape <- '\\' any StrChars <- (!'"' !'\\' any)+ @@ -328,16 +303,16 @@ TEST_CASE("WHITESPACE test3", "[general]") { %whitespace <- [ \t]* )"); - parser["StrQuot"] = [](const SemanticValues& sv) { - REQUIRE(sv.token() == R"( aaa \" bbb )"); - }; + parser["StrQuot"] = [](const SemanticValues &vs) { + REQUIRE(vs.token() == R"( aaa \" bbb )"); + }; - auto ret = parser.parse(R"( " aaa \" bbb " )"); - REQUIRE(ret == true); + auto ret = parser.parse(R"( " aaa \" bbb " )"); + REQUIRE(ret == true); } TEST_CASE("WHITESPACE test4", "[general]") { - parser parser(R"( + parser parser(R"( ROOT <- HELLO OPE WORLD HELLO <- 'hello' OPE <- < [-+] > @@ -345,249 +320,221 @@ TEST_CASE("WHITESPACE test4", "[general]") { %whitespace <- [ \t\r\n]* )"); - parser["HELLO"] = [](const SemanticValues& sv) { - REQUIRE(sv.token() == "hello"); - }; + parser["HELLO"] = [](const SemanticValues &vs) { + REQUIRE(vs.token() == "hello"); + }; - parser["OPE"] = [](const SemanticValues& sv) { - REQUIRE(sv.token() == "+"); - }; + parser["OPE"] = [](const SemanticValues &vs) { REQUIRE(vs.token() == "+"); }; - parser["WORLD"] = [](const SemanticValues& sv) { - REQUIRE(sv.token() == "world"); - }; + parser["WORLD"] = [](const SemanticValues &vs) { + REQUIRE(vs.token() == "world"); + }; - auto ret = parser.parse(" hello + world "); - REQUIRE(ret == true); + auto ret = parser.parse(" hello + world "); + REQUIRE(ret == true); } TEST_CASE("Word expression test", "[general]") { - parser parser(R"( + parser parser(R"( ROOT <- 'hello' ','? 'world' %whitespace <- [ \t\r\n]* %word <- [a-z]+ )"); - REQUIRE(parser.parse("helloworld") == false); - REQUIRE(parser.parse("hello world") == true); - REQUIRE(parser.parse("hello,world") == true); - REQUIRE(parser.parse("hello, world") == true); - REQUIRE(parser.parse("hello , world") == true); + REQUIRE(parser.parse("helloworld") == false); + REQUIRE(parser.parse("hello world") == true); + REQUIRE(parser.parse("hello,world") == true); + REQUIRE(parser.parse("hello, world") == true); + REQUIRE(parser.parse("hello , world") == true); } -TEST_CASE("Skip token test", "[general]") -{ - parser parser( - " ROOT <- _ ITEM (',' _ ITEM _)* " - " ITEM <- ([a-z0-9])+ " - " ~_ <- [ \t]* " - ); +TEST_CASE("Skip token test", "[general]") { + parser parser(" ROOT <- _ ITEM (',' _ ITEM _)* " + " ITEM <- ([a-z0-9])+ " + " ~_ <- [ \t]* "); - parser["ROOT"] = [&](const SemanticValues& sv) { - REQUIRE(sv.size() == 2); - }; + parser["ROOT"] = [&](const SemanticValues &vs) { REQUIRE(vs.size() == 2); }; - auto ret = parser.parse(" item1, item2 "); + auto ret = parser.parse(" item1, item2 "); - REQUIRE(ret == true); + REQUIRE(ret == true); } -TEST_CASE("Skip token test2", "[general]") -{ - parser parser(R"( +TEST_CASE("Skip token test2", "[general]") { + parser parser(R"( ROOT <- ITEM (',' ITEM)* ITEM <- < ([a-z0-9])+ > %whitespace <- [ \t]* )"); - parser["ROOT"] = [&](const SemanticValues& sv) { - REQUIRE(sv.size() == 2); - }; + parser["ROOT"] = [&](const SemanticValues &vs) { REQUIRE(vs.size() == 2); }; - auto ret = parser.parse(" item1, item2 "); + auto ret = parser.parse(" item1, item2 "); - REQUIRE(ret == true); + REQUIRE(ret == true); } -TEST_CASE("Custom AST test", "[general]") -{ - struct CustomType {}; - using CustomAst = AstBase; - - parser parser(R"( +TEST_CASE("Custom AST test", "[general]") { + struct CustomType {}; + using CustomAst = AstBase; + + parser parser(R"( ROOT <- _ TEXT* TEXT <- [a-zA-Z]+ _ _ <- [ \t\r\n]* )"); - parser.enable_ast(); - std::shared_ptr ast; - bool ret = parser.parse("a b c", ast); - REQUIRE(ret == true); - REQUIRE(ast->nodes.size() == 4); + parser.enable_ast(); + std::shared_ptr ast; + bool ret = parser.parse("a b c", ast); + REQUIRE(ret == true); + REQUIRE(ast->nodes.size() == 4); } -TEST_CASE("Backtracking test", "[general]") -{ - parser parser(R"( +TEST_CASE("Backtracking test", "[general]") { + parser parser(R"( START <- PAT1 / PAT2 PAT1 <- HELLO ' One' PAT2 <- HELLO ' Two' HELLO <- 'Hello' )"); - size_t count = 0; - parser["HELLO"] = [&](const SemanticValues& /*sv*/) { - count++; - }; + size_t count = 0; + parser["HELLO"] = [&](const SemanticValues & /*vs*/) { count++; }; - parser.enable_packrat_parsing(); + parser.enable_packrat_parsing(); - bool ret = parser.parse("Hello Two"); - REQUIRE(ret == true); - REQUIRE(count == 1); // Skip second time + bool ret = parser.parse("Hello Two"); + REQUIRE(ret == true); + REQUIRE(count == 1); // Skip second time } -TEST_CASE("Backtracking with AST", "[general]") -{ - parser parser(R"( +TEST_CASE("Backtracking with AST", "[general]") { + parser parser(R"( S <- A? B (A B)* A A <- 'a' B <- 'b' )"); - parser.enable_ast(); - std::shared_ptr ast; - bool ret = parser.parse("ba", ast); - REQUIRE(ret == true); - REQUIRE(ast->nodes.size() == 2); + parser.enable_ast(); + std::shared_ptr ast; + bool ret = parser.parse("ba", ast); + REQUIRE(ret == true); + REQUIRE(ast->nodes.size() == 2); } -TEST_CASE("Octal/Hex/Unicode value test", "[general]") -{ - parser parser( - R"( ROOT <- '\132\x7a\u30f3' )" - ); +TEST_CASE("Octal/Hex/Unicode value test", "[general]") { + parser parser(R"( ROOT <- '\132\x7a\u30f3' )"); - auto ret = parser.parse("Zzン"); + auto ret = parser.parse("Zzン"); - REQUIRE(ret == true); + REQUIRE(ret == true); } TEST_CASE("Ignore case test", "[general]") { - parser parser(R"( + parser parser(R"( ROOT <- HELLO WORLD HELLO <- 'hello'i WORLD <- 'world'i %whitespace <- [ \t\r\n]* )"); - parser["HELLO"] = [](const SemanticValues& sv) { - REQUIRE(sv.token() == "Hello"); - }; + parser["HELLO"] = [](const SemanticValues &vs) { + REQUIRE(vs.token() == "Hello"); + }; - parser["WORLD"] = [](const SemanticValues& sv) { - REQUIRE(sv.token() == "World"); - }; + parser["WORLD"] = [](const SemanticValues &vs) { + REQUIRE(vs.token() == "World"); + }; - auto ret = parser.parse(" Hello World "); - REQUIRE(ret == true); + auto ret = parser.parse(" Hello World "); + REQUIRE(ret == true); } -TEST_CASE("mutable lambda test", "[general]") -{ - std::vector vec; +TEST_CASE("mutable lambda test", "[general]") { + std::vector vec; - parser pg("ROOT <- 'mutable lambda test'"); + parser pg("ROOT <- 'mutable lambda test'"); - // This test makes sure if the following code can be compiled. - pg["TOKEN"] = [=](const SemanticValues& sv) mutable { - vec.push_back(sv.str()); - }; + // This test makes sure if the following code can be compiled. + pg["TOKEN"] = [=](const SemanticValues &vs) mutable { + vec.push_back(vs.sv()); + }; } -TEST_CASE("Simple calculator test", "[general]") -{ - parser parser(R"( +TEST_CASE("Simple calculator test", "[general]") { + parser parser(R"( Additive <- Multitive '+' Additive / Multitive Multitive <- Primary '*' Multitive / Primary Primary <- '(' Additive ')' / Number Number <- [0-9]+ )"); - parser["Additive"] = [](const SemanticValues& sv) { - switch (sv.choice()) { - case 0: - return any_cast(sv[0]) + any_cast(sv[1]); - default: - return any_cast(sv[0]); - } - }; + parser["Additive"] = [](const SemanticValues &vs) { + switch (vs.choice()) { + case 0: return std::any_cast(vs[0]) + std::any_cast(vs[1]); + default: return std::any_cast(vs[0]); + } + }; - parser["Multitive"] = [](const SemanticValues& sv) { - switch (sv.choice()) { - case 0: - return any_cast(sv[0]) * any_cast(sv[1]); - default: - return any_cast(sv[0]); - } - }; + parser["Multitive"] = [](const SemanticValues &vs) { + switch (vs.choice()) { + case 0: return std::any_cast(vs[0]) * std::any_cast(vs[1]); + default: return std::any_cast(vs[0]); + } + }; - parser["Number"] = [](const SemanticValues& sv) { - return atoi(sv.c_str()); - }; + parser["Number"] = [](const SemanticValues &vs) { return vs.token_to_number(); }; - int val; - parser.parse("(1+2)*3", val); - - REQUIRE(val == 9); -} - -TEST_CASE("Calculator test", "[general]") -{ - // Construct grammer - Definition EXPRESSION, TERM, FACTOR, TERM_OPERATOR, FACTOR_OPERATOR, NUMBER; - - EXPRESSION <= seq(TERM, zom(seq(TERM_OPERATOR, TERM))); - TERM <= seq(FACTOR, zom(seq(FACTOR_OPERATOR, FACTOR))); - FACTOR <= cho(NUMBER, seq(chr('('), EXPRESSION, chr(')'))); - TERM_OPERATOR <= cls("+-"); - FACTOR_OPERATOR <= cls("*/"); - NUMBER <= oom(cls("0-9")); - - // Setup actions - auto reduce = [](const SemanticValues& sv) -> long { - long ret = any_cast(sv[0]); - for (auto i = 1u; i < sv.size(); i += 2) { - auto num = any_cast(sv[i + 1]); - switch (any_cast(sv[i])) { - case '+': ret += num; break; - case '-': ret -= num; break; - case '*': ret *= num; break; - case '/': ret /= num; break; - } - } - return ret; - }; + int val; + parser.parse("(1+2)*3", val); - EXPRESSION = reduce; - TERM = reduce; - TERM_OPERATOR = [](const SemanticValues& sv) { return *sv.c_str(); }; - FACTOR_OPERATOR = [](const SemanticValues& sv) { return *sv.c_str(); }; - NUMBER = [](const SemanticValues& sv) { return stol(sv.str(), nullptr, 10); }; + REQUIRE(val == 9); +} + +TEST_CASE("Calculator test", "[general]") { + // Construct grammer + Definition EXPRESSION, TERM, FACTOR, TERM_OPERATOR, FACTOR_OPERATOR, NUMBER; - // Parse - long val; - auto r = EXPRESSION.parse_and_get_value("1+2*3*(4-5+6)/7-8", val); + EXPRESSION <= seq(TERM, zom(seq(TERM_OPERATOR, TERM))); + TERM <= seq(FACTOR, zom(seq(FACTOR_OPERATOR, FACTOR))); + FACTOR <= cho(NUMBER, seq(chr('('), EXPRESSION, chr(')'))); + TERM_OPERATOR <= cls("+-"); + FACTOR_OPERATOR <= cls("*/"); + NUMBER <= oom(cls("0-9")); - REQUIRE(r.ret == true); - REQUIRE(val == -3); + // Setup actions + auto reduce = [](const SemanticValues &vs) -> long { + long ret = std::any_cast(vs[0]); + for (auto i = 1u; i < vs.size(); i += 2) { + auto num = std::any_cast(vs[i + 1]); + switch (std::any_cast(vs[i])) { + case '+': ret += num; break; + case '-': ret -= num; break; + case '*': ret *= num; break; + case '/': ret /= num; break; + } + } + return ret; + }; + + EXPRESSION = reduce; + TERM = reduce; + TERM_OPERATOR = [](const SemanticValues &vs) { return *vs.sv().data(); }; + FACTOR_OPERATOR = [](const SemanticValues &vs) { return *vs.sv().data(); }; + NUMBER = [](const SemanticValues &vs) { return vs.token_to_number(); }; + + // Parse + long val; + auto r = EXPRESSION.parse_and_get_value("1+2*3*(4-5+6)/7-8", val); + + REQUIRE(r.ret == true); + REQUIRE(val == -3); } -TEST_CASE("Calculator test2", "[general]") -{ - // Parse syntax - auto syntax = R"( +TEST_CASE("Calculator test2", "[general]") { + // Parse syntax + auto syntax = R"( # Grammar for Calculator... EXPRESSION <- TERM (TERM_OPERATOR TERM)* TERM <- FACTOR (FACTOR_OPERATOR FACTOR)* @@ -597,43 +544,42 @@ TEST_CASE("Calculator test2", "[general]") NUMBER <- [0-9]+ )"; - std::string start; - auto grammar = ParserGenerator::parse(syntax, strlen(syntax), start, nullptr); - auto& g = *grammar; - - // Setup actions - auto reduce = [](const SemanticValues& sv) -> long { - long ret = any_cast(sv[0]); - for (auto i = 1u; i < sv.size(); i += 2) { - auto num = any_cast(sv[i + 1]); - switch (any_cast(sv[i])) { - case '+': ret += num; break; - case '-': ret -= num; break; - case '*': ret *= num; break; - case '/': ret /= num; break; - } - } - return ret; - }; + std::string start; + auto grammar = ParserGenerator::parse(syntax, strlen(syntax), start, nullptr); + auto &g = *grammar; + + // Setup actions + auto reduce = [](const SemanticValues &vs) -> long { + long ret = std::any_cast(vs[0]); + for (auto i = 1u; i < vs.size(); i += 2) { + auto num = std::any_cast(vs[i + 1]); + switch (std::any_cast(vs[i])) { + case '+': ret += num; break; + case '-': ret -= num; break; + case '*': ret *= num; break; + case '/': ret /= num; break; + } + } + return ret; + }; - g["EXPRESSION"] = reduce; - g["TERM"] = reduce; - g["TERM_OPERATOR"] = [](const SemanticValues& sv) { return *sv.c_str(); }; - g["FACTOR_OPERATOR"] = [](const SemanticValues& sv) { return *sv.c_str(); }; - g["NUMBER"] = [](const SemanticValues& sv) { return stol(sv.str(), nullptr, 10); }; + g["EXPRESSION"] = reduce; + g["TERM"] = reduce; + g["TERM_OPERATOR"] = [](const SemanticValues &vs) { return *vs.sv().data(); }; + g["FACTOR_OPERATOR"] = [](const SemanticValues &vs) { return *vs.sv().data(); }; + g["NUMBER"] = [](const SemanticValues &vs) { return vs.token_to_number(); }; - // Parse - long val; - auto r = g[start].parse_and_get_value("1+2*3*(4-5+6)/7-8", val); + // Parse + long val; + auto r = g[start].parse_and_get_value("1+2*3*(4-5+6)/7-8", val); - REQUIRE(r.ret == true); - REQUIRE(val == -3); + REQUIRE(r.ret == true); + REQUIRE(val == -3); } -TEST_CASE("Calculator test3", "[general]") -{ - // Parse syntax - parser parser(R"( +TEST_CASE("Calculator test3", "[general]") { + // Parse syntax + parser parser(R"( # Grammar for Calculator... EXPRESSION <- TERM (TERM_OPERATOR TERM)* TERM <- FACTOR (FACTOR_OPERATOR FACTOR)* @@ -643,38 +589,41 @@ TEST_CASE("Calculator test3", "[general]") NUMBER <- [0-9]+ )"); - auto reduce = [](const SemanticValues& sv) -> long { - long ret = any_cast(sv[0]); - for (auto i = 1u; i < sv.size(); i += 2) { - auto num = any_cast(sv[i + 1]); - switch (any_cast(sv[i])) { - case '+': ret += num; break; - case '-': ret -= num; break; - case '*': ret *= num; break; - case '/': ret /= num; break; - } - } - return ret; - }; + auto reduce = [](const SemanticValues &vs) -> long { + long ret = std::any_cast(vs[0]); + for (auto i = 1u; i < vs.size(); i += 2) { + auto num = std::any_cast(vs[i + 1]); + switch (std::any_cast(vs[i])) { + case '+': ret += num; break; + case '-': ret -= num; break; + case '*': ret *= num; break; + case '/': ret /= num; break; + } + } + return ret; + }; - // Setup actions - parser["EXPRESSION"] = reduce; - parser["TERM"] = reduce; - parser["TERM_OPERATOR"] = [](const SemanticValues& sv) { return static_cast(*sv.c_str()); }; - parser["FACTOR_OPERATOR"] = [](const SemanticValues& sv) { return static_cast(*sv.c_str()); }; - parser["NUMBER"] = [](const SemanticValues& sv) { return stol(sv.str(), nullptr, 10); }; + // Setup actions + parser["EXPRESSION"] = reduce; + parser["TERM"] = reduce; + parser["TERM_OPERATOR"] = [](const SemanticValues &vs) { + return static_cast(*vs.sv().data()); + }; + parser["FACTOR_OPERATOR"] = [](const SemanticValues &vs) { + return static_cast(*vs.sv().data()); + }; + parser["NUMBER"] = [](const SemanticValues &vs) { return vs.token_to_number(); }; - // Parse - long val; - auto ret = parser.parse("1+2*3*(4-5+6)/7-8", val); + // Parse + long val; + auto ret = parser.parse("1+2*3*(4-5+6)/7-8", val); - REQUIRE(ret == true); - REQUIRE(val == -3); + REQUIRE(ret == true); + REQUIRE(val == -3); } -TEST_CASE("Calculator test with AST", "[general]") -{ - parser parser(R"( +TEST_CASE("Calculator test with AST", "[general]") { + parser parser(R"( EXPRESSION <- _ TERM (TERM_OPERATOR TERM)* TERM <- FACTOR (FACTOR_OPERATOR FACTOR)* FACTOR <- NUMBER / '(' _ EXPRESSION ')' _ @@ -684,40 +633,41 @@ TEST_CASE("Calculator test with AST", "[general]") ~_ <- [ \t\r\n]* )"); - parser.enable_ast(); - - std::function eval = [&](const Ast& ast) { - if (ast.name == "NUMBER") { - return stol(ast.token); - } else { - const auto& nodes = ast.nodes; - auto result = eval(*nodes[0]); - for (auto i = 1u; i < nodes.size(); i += 2) { - auto num = eval(*nodes[i + 1]); - auto ope = nodes[i]->token[0]; - switch (ope) { - case '+': result += num; break; - case '-': result -= num; break; - case '*': result *= num; break; - case '/': result /= num; break; - } - } - return result; + parser.enable_ast(); + + std::function eval = [&](const Ast &ast) { + if (ast.name == "NUMBER") { + return ast.token_to_number(); + } else { + const auto &nodes = ast.nodes; + auto result = eval(*nodes[0]); + for (auto i = 1u; i < nodes.size(); i += 2) { + auto num = eval(*nodes[i + 1]); + auto ope = nodes[i]->token[0]; + switch (ope) { + case '+': result += num; break; + case '-': result -= num; break; + case '*': result *= num; break; + case '/': result /= num; break; } - }; + } + return result; + } + }; - std::shared_ptr ast; - auto ret = parser.parse("1+2*3*(4-5+6)/7-8", ast); - ast = AstOptimizer(true).optimize(ast); - auto val = eval(*ast); + std::shared_ptr ast; + auto ret = parser.parse("1+2*3*(4-5+6)/7-8", ast); + ast = AstOptimizer(true).optimize(ast); + auto val = eval(*ast); - REQUIRE(ret == true); - REQUIRE(val == -3); + REQUIRE(ret == true); + REQUIRE(val == -3); } TEST_CASE("Calculator test with combinators and AST", "[general]") { // Construct grammer - AST_DEFINITIONS(EXPRESSION, TERM, FACTOR, TERM_OPERATOR, FACTOR_OPERATOR, NUMBER); + AST_DEFINITIONS(EXPRESSION, TERM, FACTOR, TERM_OPERATOR, FACTOR_OPERATOR, + NUMBER); EXPRESSION <= seq(TERM, zom(seq(TERM_OPERATOR, TERM))); TERM <= seq(FACTOR, zom(seq(FACTOR_OPERATOR, FACTOR))); @@ -728,7 +678,7 @@ TEST_CASE("Calculator test with combinators and AST", "[general]") { std::function eval = [&](const Ast &ast) { if (ast.name == "NUMBER") { - return stol(ast.token); + return ast.token_to_number(); } else { const auto &nodes = ast.nodes; auto result = eval(*nodes[0]); @@ -755,28 +705,26 @@ TEST_CASE("Calculator test with combinators and AST", "[general]") { REQUIRE(val == -3); } -TEST_CASE("Ignore semantic value test", "[general]") -{ - parser parser(R"( +TEST_CASE("Ignore semantic value test", "[general]") { + parser parser(R"( START <- ~HELLO WORLD HELLO <- 'Hello' _ WORLD <- 'World' _ _ <- [ \t\r\n]* )"); - parser.enable_ast(); + parser.enable_ast(); - std::shared_ptr ast; - auto ret = parser.parse("Hello World", ast); + std::shared_ptr ast; + auto ret = parser.parse("Hello World", ast); - REQUIRE(ret == true); - REQUIRE(ast->nodes.size() == 1); - REQUIRE(ast->nodes[0]->name == "WORLD"); + REQUIRE(ret == true); + REQUIRE(ast->nodes.size() == 1); + REQUIRE(ast->nodes[0]->name == "WORLD"); } -TEST_CASE("Ignore semantic value of 'or' predicate test", "[general]") -{ - parser parser(R"( +TEST_CASE("Ignore semantic value of 'or' predicate test", "[general]") { + parser parser(R"( START <- _ !DUMMY HELLO_WORLD '.' HELLO_WORLD <- HELLO 'World' _ HELLO <- 'Hello' _ @@ -784,109 +732,102 @@ TEST_CASE("Ignore semantic value of 'or' predicate test", "[general]") ~_ <- [ \t\r\n]* )"); - parser.enable_ast(); + parser.enable_ast(); - std::shared_ptr ast; - auto ret = parser.parse("Hello World.", ast); + std::shared_ptr ast; + auto ret = parser.parse("Hello World.", ast); - REQUIRE(ret == true); - REQUIRE(ast->nodes.size() == 1); - REQUIRE(ast->nodes[0]->name == "HELLO_WORLD"); + REQUIRE(ret == true); + REQUIRE(ast->nodes.size() == 1); + REQUIRE(ast->nodes[0]->name == "HELLO_WORLD"); } -TEST_CASE("Ignore semantic value of 'and' predicate test", "[general]") -{ - parser parser(R"( +TEST_CASE("Ignore semantic value of 'and' predicate test", "[general]") { + parser parser(R"( START <- _ &HELLO HELLO_WORLD '.' HELLO_WORLD <- HELLO 'World' _ HELLO <- 'Hello' _ ~_ <- [ \t\r\n]* )"); - parser.enable_ast(); + parser.enable_ast(); - std::shared_ptr ast; - auto ret = parser.parse("Hello World.", ast); + std::shared_ptr ast; + auto ret = parser.parse("Hello World.", ast); - REQUIRE(ret == true); - REQUIRE(ast->nodes.size() == 1); - REQUIRE(ast->nodes[0]->name == "HELLO_WORLD"); + REQUIRE(ret == true); + REQUIRE(ast->nodes.size() == 1); + REQUIRE(ast->nodes[0]->name == "HELLO_WORLD"); } -TEST_CASE("Literal token on AST test1", "[general]") -{ - parser parser(R"( +TEST_CASE("Literal token on AST test1", "[general]") { + parser parser(R"( STRING_LITERAL <- '"' (('\\"' / '\\t' / '\\n') / (!["] .))* '"' )"); - parser.enable_ast(); + parser.enable_ast(); - std::shared_ptr ast; - auto ret = parser.parse(R"("a\tb")", ast); + std::shared_ptr ast; + auto ret = parser.parse(R"("a\tb")", ast); - REQUIRE(ret == true); - REQUIRE(ast->is_token == true); - REQUIRE(ast->token == R"("a\tb")"); - REQUIRE(ast->nodes.empty()); + REQUIRE(ret == true); + REQUIRE(ast->is_token == true); + REQUIRE(ast->token == R"("a\tb")"); + REQUIRE(ast->nodes.empty()); } -TEST_CASE("Literal token on AST test2", "[general]") -{ - parser parser(R"( +TEST_CASE("Literal token on AST test2", "[general]") { + parser parser(R"( STRING_LITERAL <- '"' (ESC / CHAR)* '"' ESC <- ('\\"' / '\\t' / '\\n') CHAR <- (!["] .) )"); - parser.enable_ast(); + parser.enable_ast(); - std::shared_ptr ast; - auto ret = parser.parse(R"("a\tb")", ast); + std::shared_ptr ast; + auto ret = parser.parse(R"("a\tb")", ast); - REQUIRE(ret == true); - REQUIRE(ast->is_token == false); - REQUIRE(ast->token.empty()); - REQUIRE(ast->nodes.size() == 3); + REQUIRE(ret == true); + REQUIRE(ast->is_token == false); + REQUIRE(ast->token.empty()); + REQUIRE(ast->nodes.size() == 3); } -TEST_CASE("Literal token on AST test3", "[general]") -{ - parser parser(R"( +TEST_CASE("Literal token on AST test3", "[general]") { + parser parser(R"( STRING_LITERAL <- < '"' (ESC / CHAR)* '"' > ESC <- ('\\"' / '\\t' / '\\n') CHAR <- (!["] .) )"); - parser.enable_ast(); + parser.enable_ast(); - std::shared_ptr ast; - auto ret = parser.parse(R"("a\tb")", ast); + std::shared_ptr ast; + auto ret = parser.parse(R"("a\tb")", ast); - REQUIRE(ret == true); - REQUIRE(ast->is_token == true); - REQUIRE(ast->token == R"("a\tb")"); - REQUIRE(ast->nodes.empty()); + REQUIRE(ret == true); + REQUIRE(ast->is_token == true); + REQUIRE(ast->token == R"("a\tb")"); + REQUIRE(ast->nodes.empty()); } -TEST_CASE("Missing missing definitions test", "[general]") -{ - parser parser(R"( +TEST_CASE("Missing missing definitions test", "[general]") { + parser parser(R"( A <- B C )"); - REQUIRE(!parser); + REQUIRE(!parser); } -TEST_CASE("Definition duplicates test", "[general]") -{ - parser parser(R"( +TEST_CASE("Definition duplicates test", "[general]") { + parser parser(R"( A <- '' A <- '' )"); - REQUIRE(!parser); + REQUIRE(!parser); } -TEST_CASE("Semantic values test", "[general]") -{ - parser parser(R"( +TEST_CASE("Semantic values test", "[general]") { + parser parser(R"( term <- ( a b c x )? a b c a <- 'a' b <- 'b' @@ -894,108 +835,104 @@ TEST_CASE("Semantic values test", "[general]") x <- 'x' )"); - for (const auto& rule: parser.get_rule_names()){ - parser[rule.c_str()] = [rule](const SemanticValues& sv, any&) { - if (rule == "term") { - REQUIRE(any_cast(sv[0]) == "a at 0"); - REQUIRE(any_cast(sv[1]) == "b at 1"); - REQUIRE(any_cast(sv[2]) == "c at 2"); - return std::string(); - } else { - return rule + " at " + std::to_string(sv.c_str() - sv.ss); - } - }; - } + for (const auto &rule : parser.get_rule_names()) { + parser[rule.data()] = [rule](const SemanticValues &vs, std::any &) { + if (rule == "term") { + REQUIRE(std::any_cast(vs[0]) == "a at 0"); + REQUIRE(std::any_cast(vs[1]) == "b at 1"); + REQUIRE(std::any_cast(vs[2]) == "c at 2"); + return std::string(); + } else { + return rule + " at " + std::to_string(vs.sv().data() - vs.ss); + } + }; + } - REQUIRE(parser.parse("abc")); + REQUIRE(parser.parse("abc")); } -TEST_CASE("Ordered choice count", "[general]") -{ - parser parser(R"( +TEST_CASE("Ordered choice count", "[general]") { + parser parser(R"( S <- 'a' / 'b' )"); - parser["S"] = [](const SemanticValues& sv) { - REQUIRE(sv.choice() == 1); - REQUIRE(sv.choice_count() == 2); - }; + parser["S"] = [](const SemanticValues &vs) { + REQUIRE(vs.choice() == 1); + REQUIRE(vs.choice_count() == 2); + }; - parser.parse("b"); + parser.parse("b"); } -TEST_CASE("Ordered choice count 2", "[general]") -{ - parser parser(R"( +TEST_CASE("Ordered choice count 2", "[general]") { + parser parser(R"( S <- ('a' / 'b')* )"); - parser["S"] = [](const SemanticValues& sv) { - REQUIRE(sv.choice() == 0); - REQUIRE(sv.choice_count() == 0); - }; + parser["S"] = [](const SemanticValues &vs) { + REQUIRE(vs.choice() == 0); + REQUIRE(vs.choice_count() == 0); + }; - parser.parse("b"); + parser.parse("b"); } -TEST_CASE("Semantic value tag", "[general]") -{ - parser parser(R"( +TEST_CASE("Semantic value tag", "[general]") { + parser parser(R"( S <- A? B* C? A <- 'a' B <- 'b' C <- 'c' )"); - { - using namespace udl; - parser["S"] = [](const SemanticValues& sv) { - REQUIRE(sv.size() == 1); - REQUIRE(sv.tags.size() == 1); - REQUIRE(sv.tags[0] == "C"_); - }; - auto ret = parser.parse("c"); - REQUIRE(ret == true); - } - - { - using namespace udl; - parser["S"] = [](const SemanticValues& sv) { - REQUIRE(sv.size() == 2); - REQUIRE(sv.tags.size() == 2); - REQUIRE(sv.tags[0] == "B"_); - REQUIRE(sv.tags[1] == "B"_); - }; - auto ret = parser.parse("bb"); - REQUIRE(ret == true); - } - - { - using namespace udl; - parser["S"] = [](const SemanticValues& sv) { - REQUIRE(sv.size() == 2); - REQUIRE(sv.tags.size() == 2); - REQUIRE(sv.tags[0] == "A"_); - REQUIRE(sv.tags[1] == "C"_); - }; - auto ret = parser.parse("ac"); - REQUIRE(ret == true); - } + { + using namespace udl; + parser["S"] = [](const SemanticValues &vs) { + REQUIRE(vs.size() == 1); + REQUIRE(vs.tags.size() == 1); + REQUIRE(vs.tags[0] == "C"_); + }; + auto ret = parser.parse("c"); + REQUIRE(ret == true); + } + + { + using namespace udl; + parser["S"] = [](const SemanticValues &vs) { + REQUIRE(vs.size() == 2); + REQUIRE(vs.tags.size() == 2); + REQUIRE(vs.tags[0] == "B"_); + REQUIRE(vs.tags[1] == "B"_); + }; + auto ret = parser.parse("bb"); + REQUIRE(ret == true); + } + + { + using namespace udl; + parser["S"] = [](const SemanticValues &vs) { + REQUIRE(vs.size() == 2); + REQUIRE(vs.tags.size() == 2); + REQUIRE(vs.tags[0] == "A"_); + REQUIRE(vs.tags[1] == "C"_); + }; + auto ret = parser.parse("ac"); + REQUIRE(ret == true); + } } -TEST_CASE("Negated Class test", "[general]") -{ - parser parser(R"( +TEST_CASE("Negated Class test", "[general]") { + parser parser(R"( ROOT <- [^a-z_]+ )"); - bool ret = parser; - REQUIRE(ret == true); + bool ret = parser; + REQUIRE(ret == true); - REQUIRE(parser.parse("ABC123")); - REQUIRE_FALSE(parser.parse("ABcZ")); - REQUIRE_FALSE(parser.parse("ABCZ_")); - REQUIRE_FALSE(parser.parse("")); + REQUIRE(parser.parse("ABC123")); + REQUIRE_FALSE(parser.parse("ABcZ")); + REQUIRE_FALSE(parser.parse("ABCZ_")); + REQUIRE_FALSE(parser.parse("")); } // vim: et ts=4 sw=4 cin cino={1s ff=unix diff --git a/test/test2.cc b/test/test2.cc index 2ee83f7..4c60112 100644 --- a/test/test2.cc +++ b/test/test2.cc @@ -98,100 +98,91 @@ TEST_CASE("Infinite loop 1", "[infinite loop]") WH <- [ \t]* )"); - REQUIRE(!pg); + REQUIRE(!pg); } -TEST_CASE("Infinite loop 2", "[infinite loop]") -{ - parser pg(R"( +TEST_CASE("Infinite loop 2", "[infinite loop]") { + parser pg(R"( ROOT <- WH TOKEN+ WH TOKEN <- [a-z0-9]* WH <- [ \t]* )"); - REQUIRE(!pg); + REQUIRE(!pg); } -TEST_CASE("Infinite loop 3", "[infinite loop]") -{ - parser pg(R"( +TEST_CASE("Infinite loop 3", "[infinite loop]") { + parser pg(R"( ROOT <- WH TOKEN* WH TOKEN <- !'word1' WH <- [ \t]* )"); - REQUIRE(!pg); + REQUIRE(!pg); } -TEST_CASE("Infinite loop 4", "[infinite loop]") -{ - parser pg(R"( +TEST_CASE("Infinite loop 4", "[infinite loop]") { + parser pg(R"( ROOT <- WH TOKEN* WH TOKEN <- &'word1' WH <- [ \t]* )"); - REQUIRE(!pg); + REQUIRE(!pg); } -TEST_CASE("Infinite loop 5", "[infinite loop]") -{ - parser pg(R"( +TEST_CASE("Infinite loop 5", "[infinite loop]") { + parser pg(R"( Numbers <- Number* Number <- [0-9]+ / Spacing Spacing <- ' ' / '\t' / '\n' / EOF # EOF is empty EOF <- !. )"); - REQUIRE(!pg); + REQUIRE(!pg); } -TEST_CASE("Infinite loop 6", "[infinite loop]") -{ - parser pg(R"( +TEST_CASE("Infinite loop 6", "[infinite loop]") { + parser pg(R"( S <- ''* )"); - REQUIRE(!pg); + REQUIRE(!pg); } -TEST_CASE("Infinite loop 7", "[infinite loop]") -{ - parser pg(R"( +TEST_CASE("Infinite loop 7", "[infinite loop]") { + parser pg(R"( S <- A* A <- '' )"); - REQUIRE(!pg); + REQUIRE(!pg); } -TEST_CASE("Not infinite 1", "[infinite loop]") -{ - parser pg(R"( +TEST_CASE("Not infinite 1", "[infinite loop]") { + parser pg(R"( Numbers <- Number* EOF Number <- [0-9]+ / Spacing Spacing <- ' ' / '\t' / '\n' EOF <- !. )"); - REQUIRE(!!pg); // OK + REQUIRE(!!pg); // OK } -TEST_CASE("Not infinite 2", "[infinite loop]") -{ - parser pg(R"( +TEST_CASE("Not infinite 2", "[infinite loop]") { + parser pg(R"( ROOT <- _ ('[' TAG_NAME ']' _)* # In a sequence operator, if there is at least one non-empty element, we can treat it as non-empty TAG_NAME <- (!']' .)+ _ <- [ \t]* )"); - REQUIRE(!!pg); // OK + REQUIRE(!!pg); // OK } -TEST_CASE("Not infinite 3", "[infinite loop]") -{ - parser pg(R"( +TEST_CASE("Not infinite 3", "[infinite loop]") { + parser pg(R"( EXPRESSION <- _ TERM (TERM_OPERATOR TERM)* TERM <- FACTOR (FACTOR_OPERATOR FACTOR)* FACTOR <- NUMBER / '(' _ EXPRESSION ')' _ # Recursive... @@ -201,12 +192,11 @@ TEST_CASE("Not infinite 3", "[infinite loop]") _ <- [ \t\r\n]* )"); - REQUIRE(!!pg); // OK + REQUIRE(!!pg); // OK } -TEST_CASE("Precedence climbing", "[precedence]") -{ - parser parser(R"( +TEST_CASE("Precedence climbing", "[precedence]") { + parser parser(R"( START <- _ EXPRESSION EXPRESSION <- ATOM (OPERATOR ATOM)* { precedence @@ -220,52 +210,51 @@ TEST_CASE("Precedence climbing", "[precedence]") T(S) <- < S > _ )"); - parser.enable_packrat_parsing(); - - // Setup actions - parser["EXPRESSION"] = [](const SemanticValues& sv) -> long { - auto result = any_cast(sv[0]); - if (sv.size() > 1) { - auto ope = any_cast(sv[1]); - auto num = any_cast(sv[2]); - switch (ope) { - case '+': result += num; break; - case '-': result -= num; break; - case '*': result *= num; break; - case '/': result /= num; break; - } - } - return result; - }; - parser["OPERATOR"] = [](const SemanticValues& sv) { return *sv.c_str(); }; - parser["NUMBER"] = [](const SemanticValues& sv) { return atol(sv.c_str()); }; - - bool ret = parser; - REQUIRE(ret == true); - - { - auto expr = " 1 + 2 * 3 * (4 - 5 + 6) / 7 - 8 "; - long val = 0; - ret = parser.parse(expr, val); + parser.enable_packrat_parsing(); - REQUIRE(ret == true); - REQUIRE(val == -3); + // Setup actions + parser["EXPRESSION"] = [](const SemanticValues &vs) -> long { + auto result = std::any_cast(vs[0]); + if (vs.size() > 1) { + auto ope = std::any_cast(vs[1]); + auto num = std::any_cast(vs[2]); + switch (ope) { + case '+': result += num; break; + case '-': result -= num; break; + case '*': result *= num; break; + case '/': result /= num; break; + } } + return result; + }; + parser["OPERATOR"] = [](const SemanticValues &vs) { return *vs.sv().data(); }; + parser["NUMBER"] = [](const SemanticValues &vs) { return vs.token_to_number(); }; + + bool ret = parser; + REQUIRE(ret == true); - { - auto expr = "-1+-2--3"; // -1 + -2 - -3 = 0 - long val = 0; - ret = parser.parse(expr, val); + { + auto expr = " 1 + 2 * 3 * (4 - 5 + 6) / 7 - 8 "; + long val = 0; + ret = parser.parse(expr, val); - REQUIRE(ret == true); - REQUIRE(val == 0); - } + REQUIRE(ret == true); + REQUIRE(val == -3); + } + + { + auto expr = "-1+-2--3"; // -1 + -2 - -3 = 0 + long val = 0; + ret = parser.parse(expr, val); + + REQUIRE(ret == true); + REQUIRE(val == 0); + } } -TEST_CASE("Precedence climbing with macro", "[precedence]") -{ - // Create a PEG parser - parser parser(R"( +TEST_CASE("Precedence climbing with macro", "[precedence]") { + // Create a PEG parser + parser parser(R"( EXPRESSION <- INFIX_EXPRESSION(ATOM, OPERATOR) INFIX_EXPRESSION(A, O) <- A (O A)* { precedence @@ -278,51 +267,50 @@ TEST_CASE("Precedence climbing with macro", "[precedence]") %whitespace <- [ \t]* )"); - parser.enable_packrat_parsing(); + parser.enable_packrat_parsing(); - bool ret = parser; - REQUIRE(ret == true); + bool ret = parser; + REQUIRE(ret == true); - // Setup actions - parser["INFIX_EXPRESSION"] = [](const SemanticValues& sv) -> long { - auto result = any_cast(sv[0]); - if (sv.size() > 1) { - auto ope = any_cast(sv[1]); - auto num = any_cast(sv[2]); - switch (ope) { - case '+': result += num; break; - case '-': result -= num; break; - case '*': result *= num; break; - case '/': result /= num; break; - } - } - return result; - }; - parser["OPERATOR"] = [](const SemanticValues& sv) { return *sv.c_str(); }; - parser["NUMBER"] = [](const SemanticValues& sv) { return atol(sv.c_str()); }; - - { - auto expr = " 1 + 2 * 3 * (4 - 5 + 6) / 7 - 8 "; - long val = 0; - ret = parser.parse(expr, val); - - REQUIRE(ret == true); - REQUIRE(val == -3); + // Setup actions + parser["INFIX_EXPRESSION"] = [](const SemanticValues &vs) -> long { + auto result = std::any_cast(vs[0]); + if (vs.size() > 1) { + auto ope = std::any_cast(vs[1]); + auto num = std::any_cast(vs[2]); + switch (ope) { + case '+': result += num; break; + case '-': result -= num; break; + case '*': result *= num; break; + case '/': result /= num; break; + } } + return result; + }; + parser["OPERATOR"] = [](const SemanticValues &vs) { return *vs.sv().data(); }; + parser["NUMBER"] = [](const SemanticValues &vs) { return vs.token_to_number(); }; - { - auto expr = "-1+-2--3"; // -1 + -2 - -3 = 0 - long val = 0; - ret = parser.parse(expr, val); + { + auto expr = " 1 + 2 * 3 * (4 - 5 + 6) / 7 - 8 "; + long val = 0; + ret = parser.parse(expr, val); - REQUIRE(ret == true); - REQUIRE(val == 0); - } + REQUIRE(ret == true); + REQUIRE(val == -3); + } + + { + auto expr = "-1+-2--3"; // -1 + -2 - -3 = 0 + long val = 0; + ret = parser.parse(expr, val); + + REQUIRE(ret == true); + REQUIRE(val == 0); + } } -TEST_CASE("Precedence climbing error1", "[precedence]") -{ - parser parser(R"( +TEST_CASE("Precedence climbing error1", "[precedence]") { + parser parser(R"( START <- _ EXPRESSION EXPRESSION <- ATOM (OPERATOR ATOM1)* { precedence @@ -337,13 +325,12 @@ TEST_CASE("Precedence climbing error1", "[precedence]") T(S) <- < S > _ )"); - bool ret = parser; - REQUIRE(ret == false); + bool ret = parser; + REQUIRE(ret == false); } -TEST_CASE("Precedence climbing error2", "[precedence]") -{ - parser parser(R"( +TEST_CASE("Precedence climbing error2", "[precedence]") { + parser parser(R"( START <- _ EXPRESSION EXPRESSION <- ATOM OPERATOR ATOM { precedence @@ -357,12 +344,12 @@ TEST_CASE("Precedence climbing error2", "[precedence]") T(S) <- < S > _ )"); - bool ret = parser; - REQUIRE(ret == false); + bool ret = parser; + REQUIRE(ret == false); } TEST_CASE("Precedence climbing error3", "[precedence]") { - parser parser(R"( + parser parser(R"( EXPRESSION <- PRECEDENCE_PARSING(ATOM, OPERATOR) PRECEDENCE_PARSING(A, O) <- A (O A)+ { precedence @@ -375,26 +362,25 @@ TEST_CASE("Precedence climbing error3", "[precedence]") { %whitespace <- [ \t]* )"); - bool ret = parser; - REQUIRE(ret == false); + bool ret = parser; + REQUIRE(ret == false); } TEST_CASE("Packrat parser test with %whitespace%", "[packrat]") { - peg::parser parser(R"( + peg::parser parser(R"( ROOT <- 'a' %whitespace <- SPACE* SPACE <- ' ' )"); - parser.enable_packrat_parsing(); + parser.enable_packrat_parsing(); - auto ret = parser.parse("a"); - REQUIRE(ret == true); + auto ret = parser.parse("a"); + REQUIRE(ret == true); } -TEST_CASE("Packrat parser test with macro", "[packrat]") -{ - parser parser(R"( +TEST_CASE("Packrat parser test with macro", "[packrat]") { + parser parser(R"( EXPRESSION <- _ LIST(TERM, TERM_OPERATOR) TERM <- LIST(FACTOR, FACTOR_OPERATOR) FACTOR <- NUMBER / T('(') EXPRESSION T(')') @@ -406,13 +392,14 @@ TEST_CASE("Packrat parser test with macro", "[packrat]") T(S) <- < S > _ )"); - parser.enable_packrat_parsing(); + parser.enable_packrat_parsing(); - auto ret = parser.parse(" 1 + 2 * 3 * (4 - 5 + 6) / 7 - 8 "); - REQUIRE(ret == true); + auto ret = parser.parse(" 1 + 2 * 3 * (4 - 5 + 6) / 7 - 8 "); + REQUIRE(ret == true); } -TEST_CASE("Packrat parser test with precedence expression parser", "[packrat]") { +TEST_CASE("Packrat parser test with precedence expression parser", + "[packrat]") { peg::parser parser(R"( Expression <- Atom (Operator Atom)* { precedence L + - L * / } Atom <- _? Number _? @@ -430,81 +417,74 @@ TEST_CASE("Packrat parser test with precedence expression parser", "[packrat]") REQUIRE(ret == true); } -TEST_CASE("Backreference test", "[backreference]") -{ - parser parser(R"( +TEST_CASE("Backreference test", "[backreference]") { + parser parser(R"( START <- _ LQUOTE < (!RQUOTE .)* > RQUOTE _ LQUOTE <- 'R"' $delm< [a-zA-Z]* > '(' RQUOTE <- ')' $delm '"' ~_ <- [ \t\r\n]* )"); - std::string token; - parser["START"] = [&](const SemanticValues& sv) { - token = sv.token(); - }; + std::string token; + parser["START"] = [&](const SemanticValues &vs) { token = vs.token(); }; - { - token.clear(); - auto ret = parser.parse(R"delm( + { + token.clear(); + auto ret = parser.parse(R"delm( R"("hello world")" )delm"); - REQUIRE(ret == true); - REQUIRE(token == "\"hello world\""); - } + REQUIRE(ret == true); + REQUIRE(token == "\"hello world\""); + } - { - token.clear(); - auto ret = parser.parse(R"delm( + { + token.clear(); + auto ret = parser.parse(R"delm( R"foo("(hello world)")foo" )delm"); - REQUIRE(ret == true); - REQUIRE(token == "\"(hello world)\""); - } + REQUIRE(ret == true); + REQUIRE(token == "\"(hello world)\""); + } - { - token.clear(); - auto ret = parser.parse(R"delm( + { + token.clear(); + auto ret = parser.parse(R"delm( R"foo("(hello world)foo")foo" )delm"); - REQUIRE(ret == false); - REQUIRE(token == "\"(hello world"); - } + REQUIRE(ret == false); + REQUIRE(token == "\"(hello world"); + } - { - token.clear(); - auto ret = parser.parse(R"delm( + { + token.clear(); + auto ret = parser.parse(R"delm( R"foo("(hello world)")bar" )delm"); - REQUIRE(ret == false); - REQUIRE(token.empty()); - } + REQUIRE(ret == false); + REQUIRE(token.empty()); + } } -TEST_CASE("Invalid backreference test", "[backreference]") -{ - parser parser(R"( +TEST_CASE("Invalid backreference test", "[backreference]") { + parser parser(R"( START <- _ LQUOTE (!RQUOTE .)* RQUOTE _ LQUOTE <- 'R"' $delm< [a-zA-Z]* > '(' RQUOTE <- ')' $delm2 '"' ~_ <- [ \t\r\n]* )"); - REQUIRE_THROWS_AS( - parser.parse(R"delm( + REQUIRE_THROWS_AS(parser.parse(R"delm( R"foo("(hello world)")foo" )delm"), - std::runtime_error); + std::runtime_error); } - -TEST_CASE("Nested capture test", "[backreference]") -{ - parser parser(R"( +TEST_CASE("Nested capture test", "[backreference]") { + parser parser(R"( ROOT <- CONTENT CONTENT <- (ELEMENT / TEXT)* ELEMENT <- $(STAG CONTENT ETAG) @@ -515,15 +495,14 @@ TEST_CASE("Nested capture test", "[backreference]") TEXT_DATA <- ![<] . )"); - REQUIRE(parser.parse("This is a test text.")); - REQUIRE(!parser.parse("This is a test text.")); - REQUIRE(!parser.parse("This is a test text.")); - REQUIRE(!parser.parse("This is a test text.")); + REQUIRE(parser.parse("This is a test text.")); + REQUIRE(!parser.parse("This is a test text.")); + REQUIRE(!parser.parse("This is a test text.")); + REQUIRE(!parser.parse("This is a test text.")); } -TEST_CASE("Backreference with Prioritized Choice test", "[backreference]") -{ - parser parser(R"( +TEST_CASE("Backreference with Prioritized Choice test", "[backreference]") { + parser parser(R"( TREE <- WRONG_BRANCH / CORRECT_BRANCH WRONG_BRANCH <- BRANCH THAT IS_capture WRONG CORRECT_BRANCH <- BRANCH THAT IS_backref CORRECT @@ -535,12 +514,11 @@ TEST_CASE("Backreference with Prioritized Choice test", "[backreference]") CORRECT <- 'correct' )"); - REQUIRE_THROWS_AS(parser.parse("branchthatiscorrect"), std::runtime_error); + REQUIRE_THROWS_AS(parser.parse("branchthatiscorrect"), std::runtime_error); } -TEST_CASE("Backreference with Zero or More test", "[backreference]") -{ - parser parser(R"( +TEST_CASE("Backreference with Zero or More test", "[backreference]") { + parser parser(R"( TREE <- WRONG_BRANCH* CORRECT_BRANCH WRONG_BRANCH <- BRANCH THAT IS_capture WRONG CORRECT_BRANCH <- BRANCH THAT IS_backref CORRECT @@ -552,17 +530,19 @@ TEST_CASE("Backreference with Zero or More test", "[backreference]") CORRECT <- 'correct' )"); - REQUIRE(parser.parse("branchthatiswrongbranchthatiscorrect")); - REQUIRE(!parser.parse("branchthatiswrongbranchthatIscorrect")); - REQUIRE(!parser.parse("branchthatiswrongbranchthatIswrongbranchthatiscorrect")); - REQUIRE(parser.parse("branchthatiswrongbranchthatIswrongbranchthatIscorrect")); - REQUIRE_THROWS_AS(parser.parse("branchthatiscorrect"), std::runtime_error); - REQUIRE_THROWS_AS(parser.parse("branchthatiswron_branchthatiscorrect"), std::runtime_error); + REQUIRE(parser.parse("branchthatiswrongbranchthatiscorrect")); + REQUIRE(!parser.parse("branchthatiswrongbranchthatIscorrect")); + REQUIRE( + !parser.parse("branchthatiswrongbranchthatIswrongbranchthatiscorrect")); + REQUIRE( + parser.parse("branchthatiswrongbranchthatIswrongbranchthatIscorrect")); + REQUIRE_THROWS_AS(parser.parse("branchthatiscorrect"), std::runtime_error); + REQUIRE_THROWS_AS(parser.parse("branchthatiswron_branchthatiscorrect"), + std::runtime_error); } -TEST_CASE("Backreference with One or More test", "[backreference]") -{ - parser parser(R"( +TEST_CASE("Backreference with One or More test", "[backreference]") { + parser parser(R"( TREE <- WRONG_BRANCH+ CORRECT_BRANCH WRONG_BRANCH <- BRANCH THAT IS_capture WRONG CORRECT_BRANCH <- BRANCH THAT IS_backref CORRECT @@ -574,17 +554,18 @@ TEST_CASE("Backreference with One or More test", "[backreference]") CORRECT <- 'correct' )"); - REQUIRE(parser.parse("branchthatiswrongbranchthatiscorrect")); - REQUIRE(!parser.parse("branchthatiswrongbranchthatIscorrect")); - REQUIRE(!parser.parse("branchthatiswrongbranchthatIswrongbranchthatiscorrect")); - REQUIRE(parser.parse("branchthatiswrongbranchthatIswrongbranchthatIscorrect")); - REQUIRE(!parser.parse("branchthatiscorrect")); - REQUIRE(!parser.parse("branchthatiswron_branchthatiscorrect")); + REQUIRE(parser.parse("branchthatiswrongbranchthatiscorrect")); + REQUIRE(!parser.parse("branchthatiswrongbranchthatIscorrect")); + REQUIRE( + !parser.parse("branchthatiswrongbranchthatIswrongbranchthatiscorrect")); + REQUIRE( + parser.parse("branchthatiswrongbranchthatIswrongbranchthatIscorrect")); + REQUIRE(!parser.parse("branchthatiscorrect")); + REQUIRE(!parser.parse("branchthatiswron_branchthatiscorrect")); } -TEST_CASE("Backreference with Option test", "[backreference]") -{ - parser parser(R"( +TEST_CASE("Backreference with Option test", "[backreference]") { + parser parser(R"( TREE <- WRONG_BRANCH? CORRECT_BRANCH WRONG_BRANCH <- BRANCH THAT IS_capture WRONG CORRECT_BRANCH <- BRANCH THAT IS_backref CORRECT @@ -596,175 +577,157 @@ TEST_CASE("Backreference with Option test", "[backreference]") CORRECT <- 'correct' )"); - REQUIRE(parser.parse("branchthatiswrongbranchthatiscorrect")); - REQUIRE(!parser.parse("branchthatiswrongbranchthatIscorrect")); - REQUIRE(!parser.parse("branchthatiswrongbranchthatIswrongbranchthatiscorrect")); - REQUIRE(!parser.parse("branchthatiswrongbranchthatIswrongbranchthatIscorrect")); - REQUIRE_THROWS_AS(parser.parse("branchthatiscorrect"), std::runtime_error); - REQUIRE_THROWS_AS(parser.parse("branchthatiswron_branchthatiscorrect"), std::runtime_error); + REQUIRE(parser.parse("branchthatiswrongbranchthatiscorrect")); + REQUIRE(!parser.parse("branchthatiswrongbranchthatIscorrect")); + REQUIRE( + !parser.parse("branchthatiswrongbranchthatIswrongbranchthatiscorrect")); + REQUIRE( + !parser.parse("branchthatiswrongbranchthatIswrongbranchthatIscorrect")); + REQUIRE_THROWS_AS(parser.parse("branchthatiscorrect"), std::runtime_error); + REQUIRE_THROWS_AS(parser.parse("branchthatiswron_branchthatiscorrect"), + std::runtime_error); } -TEST_CASE("Repetition {0}", "[repetition]") -{ - parser parser(R"( +TEST_CASE("Repetition {0}", "[repetition]") { + parser parser(R"( START <- '(' DIGIT{3} ') ' DIGIT{3} '-' DIGIT{4} DIGIT <- [0-9] )"); - REQUIRE(parser.parse("(123) 456-7890")); - REQUIRE(!parser.parse("(12a) 456-7890")); - REQUIRE(!parser.parse("(123) 45-7890")); - REQUIRE(!parser.parse("(123) 45-7a90")); + REQUIRE(parser.parse("(123) 456-7890")); + REQUIRE(!parser.parse("(12a) 456-7890")); + REQUIRE(!parser.parse("(123) 45-7890")); + REQUIRE(!parser.parse("(123) 45-7a90")); } -TEST_CASE("Repetition {2,4}", "[repetition]") -{ - parser parser(R"( +TEST_CASE("Repetition {2,4}", "[repetition]") { + parser parser(R"( START <- DIGIT{2,4} DIGIT <- [0-9] )"); - REQUIRE(!parser.parse("1")); - REQUIRE(parser.parse("12")); - REQUIRE(parser.parse("123")); - REQUIRE(parser.parse("1234")); - REQUIRE(!parser.parse("12345")); + REQUIRE(!parser.parse("1")); + REQUIRE(parser.parse("12")); + REQUIRE(parser.parse("123")); + REQUIRE(parser.parse("1234")); + REQUIRE(!parser.parse("12345")); } -TEST_CASE("Repetition {2,1}", "[repetition]") -{ - parser parser(R"( +TEST_CASE("Repetition {2,1}", "[repetition]") { + parser parser(R"( START <- DIGIT{2,1} # invalid range DIGIT <- [0-9] )"); - REQUIRE(!parser.parse("1")); - REQUIRE(parser.parse("12")); - REQUIRE(!parser.parse("123")); + REQUIRE(!parser.parse("1")); + REQUIRE(parser.parse("12")); + REQUIRE(!parser.parse("123")); } -TEST_CASE("Repetition {2,}", "[repetition]") -{ - parser parser(R"( +TEST_CASE("Repetition {2,}", "[repetition]") { + parser parser(R"( START <- DIGIT{2,} DIGIT <- [0-9] )"); - REQUIRE(!parser.parse("1")); - REQUIRE(parser.parse("12")); - REQUIRE(parser.parse("123")); - REQUIRE(parser.parse("1234")); + REQUIRE(!parser.parse("1")); + REQUIRE(parser.parse("12")); + REQUIRE(parser.parse("123")); + REQUIRE(parser.parse("1234")); } -TEST_CASE("Repetition {,2}", "[repetition]") -{ - parser parser(R"( +TEST_CASE("Repetition {,2}", "[repetition]") { + parser parser(R"( START <- DIGIT{,2} DIGIT <- [0-9] )"); - REQUIRE(parser.parse("1")); - REQUIRE(parser.parse("12")); - REQUIRE(!parser.parse("123")); - REQUIRE(!parser.parse("1234")); + REQUIRE(parser.parse("1")); + REQUIRE(parser.parse("12")); + REQUIRE(!parser.parse("123")); + REQUIRE(!parser.parse("1234")); } -TEST_CASE("Left recursive test", "[left recursive]") -{ - parser parser(R"( +TEST_CASE("Left recursive test", "[left recursive]") { + parser parser(R"( A <- A 'a' B <- A 'a' )"); - REQUIRE(!parser); + REQUIRE(!parser); } -TEST_CASE("Left recursive with option test", "[left recursive]") -{ - parser parser(R"( +TEST_CASE("Left recursive with option test", "[left recursive]") { + parser parser(R"( A <- 'a' / 'b'? B 'c' B <- A )"); - REQUIRE(!parser); + REQUIRE(!parser); } -TEST_CASE("Left recursive with zom test", "[left recursive]") -{ - parser parser(R"( +TEST_CASE("Left recursive with zom test", "[left recursive]") { + parser parser(R"( A <- 'a'* A* )"); - REQUIRE(!parser); + REQUIRE(!parser); } -TEST_CASE("Left recursive with a ZOM content rule", "[left recursive]") -{ - parser parser(R"( +TEST_CASE("Left recursive with a ZOM content rule", "[left recursive]") { + parser parser(R"( A <- B B <- _ A _ <- ' '* # Zero or more )"); - REQUIRE(!parser); + REQUIRE(!parser); } -TEST_CASE("Left recursive with empty string test", "[left recursive]") -{ - parser parser( - " A <- '' A" - ); +TEST_CASE("Left recursive with empty string test", "[left recursive]") { + parser parser(" A <- '' A"); - REQUIRE(!parser); + REQUIRE(!parser); } -TEST_CASE("User defined rule test", "[user rule]") -{ - auto g = parser(R"( +TEST_CASE("User defined rule test", "[user rule]") { + auto g = parser(R"( ROOT <- _ 'Hello' _ NAME '!' _ )", - { - { - "NAME", usr([](const char* s, size_t n, SemanticValues& /*sv*/, any& /*dt*/) -> size_t { - static std::vector names = { "PEG", "BNF" }; - for (const auto& name: names) { - if (name.size() <= n && !name.compare(0, name.size(), s, name.size())) { - return name.size(); - } - } - return static_cast(-1); - }) - }, - { - "~_", zom(cls(" \t\r\n")) - } - }); - - REQUIRE(g.parse(" Hello BNF! ") == true); -} - -TEST_CASE("Semantic predicate test", "[predicate]") -{ - parser parser("NUMBER <- [0-9]+"); - - parser["NUMBER"] = [](const SemanticValues& sv) { - auto val = stol(sv.token(), nullptr, 10); - if (val != 100) { - throw parse_error("value error!!"); - } - return val; - }; - - long val; - REQUIRE(parser.parse("100", val)); - REQUIRE(val == 100); - - parser.log = [](size_t line, size_t col, const std::string& msg) { - REQUIRE(line == 1); - REQUIRE(col == 1); - REQUIRE(msg == "value error!!"); - }; - REQUIRE(!parser.parse("200", val)); -} - -TEST_CASE("Japanese character", "[unicode]") -{ - peg::parser parser(u8R"( + {{"NAME", usr([](const char *s, size_t n, SemanticValues &, + std::any &) -> size_t { + static std::vector names = {"PEG", "BNF"}; + for (const auto &name : names) { + if (name.size() <= n && + !name.compare(0, name.size(), s, name.size())) { + return name.size(); + } + } + return static_cast(-1); + })}, + {"~_", zom(cls(" \t\r\n"))}}); + + REQUIRE(g.parse(" Hello BNF! ") == true); +} + +TEST_CASE("Semantic predicate test", "[predicate]") { + parser parser("NUMBER <- [0-9]+"); + + parser["NUMBER"] = [](const SemanticValues &vs) { + auto val = vs.token_to_number(); + if (val != 100) { throw parse_error("value error!!"); } + return val; + }; + + long val; + REQUIRE(parser.parse("100", val)); + REQUIRE(val == 100); + + parser.log = [](size_t line, size_t col, const std::string &msg) { + REQUIRE(line == 1); + REQUIRE(col == 1); + REQUIRE(msg == "value error!!"); + }; + REQUIRE(!parser.parse("200", val)); +} + +TEST_CASE("Japanese character", "[unicode]") { + peg::parser parser(u8R"( 文 <- 修飾語? 主語 述語 '。' 主語 <- 名詞 助詞 述語 <- 動詞 助詞 @@ -775,49 +738,46 @@ TEST_CASE("Japanese character", "[unicode]") 助詞 <- 'が' / 'を' / 'た' / 'ます' / 'に' )"); - bool ret = parser; - REQUIRE(ret == true); + bool ret = parser; + REQUIRE(ret == true); - REQUIRE(parser.parse(u8R"(サーバーを復旧します。)")); + REQUIRE(parser.parse(u8R"(サーバーを復旧します。)")); } -TEST_CASE("dot with a code", "[unicode]") -{ - peg::parser parser(" S <- 'a' . 'b' "); - REQUIRE(parser.parse(u8R"(aあb)")); +TEST_CASE("dot with a code", "[unicode]") { + peg::parser parser(" S <- 'a' . 'b' "); + REQUIRE(parser.parse(u8R"(aあb)")); } -TEST_CASE("dot with a char", "[unicode]") -{ - peg::parser parser(" S <- 'a' . 'b' "); - REQUIRE(parser.parse(u8R"(aåb)")); +TEST_CASE("dot with a char", "[unicode]") { + peg::parser parser(" S <- 'a' . 'b' "); + REQUIRE(parser.parse(u8R"(aåb)")); } -TEST_CASE("character class", "[unicode]") -{ - peg::parser parser(R"( +TEST_CASE("character class", "[unicode]") { + peg::parser parser(R"( S <- 'a' [い-おAさC-Eた-とは] 'b' )"); - bool ret = parser; - REQUIRE(ret == true); + bool ret = parser; + REQUIRE(ret == true); - REQUIRE(!parser.parse(u8R"(aあb)")); - REQUIRE(parser.parse(u8R"(aいb)")); - REQUIRE(parser.parse(u8R"(aうb)")); - REQUIRE(parser.parse(u8R"(aおb)")); - REQUIRE(!parser.parse(u8R"(aかb)")); - REQUIRE(parser.parse(u8R"(aAb)")); - REQUIRE(!parser.parse(u8R"(aBb)")); - REQUIRE(parser.parse(u8R"(aEb)")); - REQUIRE(!parser.parse(u8R"(aFb)")); - REQUIRE(!parser.parse(u8R"(aそb)")); - REQUIRE(parser.parse(u8R"(aたb)")); - REQUIRE(parser.parse(u8R"(aちb)")); - REQUIRE(parser.parse(u8R"(aとb)")); - REQUIRE(!parser.parse(u8R"(aなb)")); - REQUIRE(parser.parse(u8R"(aはb)")); - REQUIRE(!parser.parse(u8R"(a?b)")); + REQUIRE(!parser.parse(u8R"(aあb)")); + REQUIRE(parser.parse(u8R"(aいb)")); + REQUIRE(parser.parse(u8R"(aうb)")); + REQUIRE(parser.parse(u8R"(aおb)")); + REQUIRE(!parser.parse(u8R"(aかb)")); + REQUIRE(parser.parse(u8R"(aAb)")); + REQUIRE(!parser.parse(u8R"(aBb)")); + REQUIRE(parser.parse(u8R"(aEb)")); + REQUIRE(!parser.parse(u8R"(aFb)")); + REQUIRE(!parser.parse(u8R"(aそb)")); + REQUIRE(parser.parse(u8R"(aたb)")); + REQUIRE(parser.parse(u8R"(aちb)")); + REQUIRE(parser.parse(u8R"(aとb)")); + REQUIRE(!parser.parse(u8R"(aなb)")); + REQUIRE(parser.parse(u8R"(aはb)")); + REQUIRE(!parser.parse(u8R"(a?b)")); } #if 0 // TODO: Unicode Grapheme support @@ -828,77 +788,70 @@ TEST_CASE("dot with a grapheme", "[unicode]") } #endif -TEST_CASE("Macro simple test", "[macro]") -{ - parser parser(R"( +TEST_CASE("Macro simple test", "[macro]") { + parser parser(R"( S <- HELLO WORLD HELLO <- T('hello') WORLD <- T('world') T(a) <- a [ \t]* )"); - REQUIRE(parser.parse("hello \tworld ")); + REQUIRE(parser.parse("hello \tworld ")); } -TEST_CASE("Macro two parameters", "[macro]") -{ - parser parser(R"( +TEST_CASE("Macro two parameters", "[macro]") { + parser parser(R"( S <- HELLO_WORLD HELLO_WORLD <- T('hello', 'world') T(a, b) <- a [ \t]* b [ \t]* )"); - REQUIRE(parser.parse("hello \tworld ")); + REQUIRE(parser.parse("hello \tworld ")); } -TEST_CASE("Macro syntax error", "[macro]") -{ - parser parser(R"( +TEST_CASE("Macro syntax error", "[macro]") { + parser parser(R"( S <- T('hello') T (a) <- a [ \t]* )"); - bool ret = parser; - REQUIRE(ret == false); + bool ret = parser; + REQUIRE(ret == false); } -TEST_CASE("Macro missing argument", "[macro]") -{ - parser parser(R"( +TEST_CASE("Macro missing argument", "[macro]") { + parser parser(R"( S <- T ('hello') T(a, b) <- a [ \t]* b )"); - bool ret = parser; - REQUIRE(ret == false); + bool ret = parser; + REQUIRE(ret == false); } -TEST_CASE("Macro reference syntax error", "[macro]") -{ - parser parser(R"( +TEST_CASE("Macro reference syntax error", "[macro]") { + parser parser(R"( S <- T ('hello') T(a) <- a [ \t]* )"); - bool ret = parser; - REQUIRE(ret == false); + bool ret = parser; + REQUIRE(ret == false); } -TEST_CASE("Macro invalid macro reference error", "[macro]") -{ - parser parser(R"( +TEST_CASE("Macro invalid macro reference error", "[macro]") { + parser parser(R"( S <- T('hello') T <- 'world' )"); - bool ret = parser; - REQUIRE(ret == false); + bool ret = parser; + REQUIRE(ret == false); } -TEST_CASE("Macro calculator", "[macro]") -{ - // Create a PEG parser - parser parser(R"( +TEST_CASE("Macro calculator", "[macro]") { + // Create a PEG parser + parser parser(R"( # Grammar for simple calculator... EXPRESSION <- _ LIST(TERM, TERM_OPERATOR) TERM <- LIST(FACTOR, FACTOR_OPERATOR) @@ -911,83 +864,83 @@ TEST_CASE("Macro calculator", "[macro]") T(S) <- < S > _ )"); - // Setup actions - auto reduce = [](const SemanticValues& sv) -> long { - auto result = any_cast(sv[0]); - for (auto i = 1u; i < sv.size(); i += 2) { - auto num = any_cast(sv[i + 1]); - auto ope = any_cast(sv[i]); - switch (ope) { - case '+': result += num; break; - case '-': result -= num; break; - case '*': result *= num; break; - case '/': result /= num; break; - } - } - return result; - }; - - parser["EXPRESSION"] = reduce; - parser["TERM"] = reduce; - parser["TERM_OPERATOR"] = [](const SemanticValues& sv) { return static_cast(*sv.c_str()); }; - parser["FACTOR_OPERATOR"] = [](const SemanticValues& sv) { return static_cast(*sv.c_str()); }; - parser["NUMBER"] = [](const SemanticValues& sv) { return atol(sv.c_str()); }; - - bool ret = parser; - REQUIRE(ret == true); + // Setup actions + auto reduce = [](const SemanticValues &vs) { + auto result = std::any_cast(vs[0]); + for (auto i = 1u; i < vs.size(); i += 2) { + auto num = std::any_cast(vs[i + 1]); + auto ope = std::any_cast(vs[i]); + switch (ope) { + case '+': result += num; break; + case '-': result -= num; break; + case '*': result *= num; break; + case '/': result /= num; break; + } + } + return result; + }; + + parser["EXPRESSION"] = reduce; + parser["TERM"] = reduce; + parser["TERM_OPERATOR"] = [](const SemanticValues &vs) { + return static_cast(*vs.sv().data()); + }; + parser["FACTOR_OPERATOR"] = [](const SemanticValues &vs) { + return static_cast(*vs.sv().data()); + }; + parser["NUMBER"] = [](const SemanticValues &vs) { return vs.token_to_number(); }; - auto expr = " 1 + 2 * 3 * (4 - 5 + 6) / 7 - 8 "; - long val = 0; - ret = parser.parse(expr, val); + bool ret = parser; + REQUIRE(ret == true); - REQUIRE(ret == true); - REQUIRE(val == -3); + auto expr = " 1 + 2 * 3 * (4 - 5 + 6) / 7 - 8 "; + long val = 0; + ret = parser.parse(expr, val); + + REQUIRE(ret == true); + REQUIRE(val == -3); } -TEST_CASE("Macro expression arguments", "[macro]") -{ - parser parser(R"( +TEST_CASE("Macro expression arguments", "[macro]") { + parser parser(R"( S <- M('hello' / 'Hello', 'world' / 'World') M(arg0, arg1) <- arg0 [ \t]+ arg1 )"); - REQUIRE(parser.parse("Hello world")); + REQUIRE(parser.parse("Hello world")); } -TEST_CASE("Macro recursive", "[macro]") -{ - parser parser(R"( +TEST_CASE("Macro recursive", "[macro]") { + parser parser(R"( S <- M('abc') M(s) <- !s / s ' ' M(s / '123') / s )"); - REQUIRE(parser.parse("")); - REQUIRE(parser.parse("abc")); - REQUIRE(parser.parse("abc abc")); - REQUIRE(parser.parse("abc 123 abc")); + REQUIRE(parser.parse("")); + REQUIRE(parser.parse("abc")); + REQUIRE(parser.parse("abc abc")); + REQUIRE(parser.parse("abc 123 abc")); } -TEST_CASE("Macro recursive2", "[macro]") -{ - auto syntaxes = std::vector{ - "S <- M('abc') M(s) <- !s / s ' ' M(s* '-' '123') / s", - "S <- M('abc') M(s) <- !s / s ' ' M(s+ '-' '123') / s", - "S <- M('abc') M(s) <- !s / s ' ' M(s? '-' '123') / s", - "S <- M('abc') M(s) <- !s / s ' ' M(&s s+ '-' '123') / s", - "S <- M('abc') M(s) <- !s / s ' ' M(s '-' !s '123') / s", - "S <- M('abc') M(s) <- !s / s ' ' M(< s > '-' '123') / s", - "S <- M('abc') M(s) <- !s / s ' ' M(~s '-' '123') / s", - }; - - for (const auto& syntax: syntaxes) { - parser parser(syntax); - REQUIRE(parser.parse("abc abc-123")); - } -} - -TEST_CASE("Macro exclusive modifiers", "[macro]") -{ - parser parser(R"( +TEST_CASE("Macro recursive2", "[macro]") { + auto syntaxes = std::vector{ + "S <- M('abc') M(s) <- !s / s ' ' M(s* '-' '123') / s", + "S <- M('abc') M(s) <- !s / s ' ' M(s+ '-' '123') / s", + "S <- M('abc') M(s) <- !s / s ' ' M(s? '-' '123') / s", + "S <- M('abc') M(s) <- !s / s ' ' M(&s s+ '-' '123') / s", + "S <- M('abc') M(s) <- !s / s ' ' M(s '-' !s '123') / s", + "S <- M('abc') M(s) <- !s / s ' ' M(< s > '-' '123') / s", + "S <- M('abc') M(s) <- !s / s ' ' M(~s '-' '123') / s", + }; + + for (const auto &syntax : syntaxes) { + parser parser(syntax); + REQUIRE(parser.parse("abc abc-123")); + } +} + +TEST_CASE("Macro exclusive modifiers", "[macro]") { + parser parser(R"( S <- Modifiers(!"") _ Modifiers(Appeared) <- (!Appeared) ( Token('public') Modifiers(Appeared / 'public') / @@ -998,17 +951,16 @@ TEST_CASE("Macro exclusive modifiers", "[macro]") _ <- [ \t\r\n]* )"); - REQUIRE(parser.parse("public")); - REQUIRE(parser.parse("static")); - REQUIRE(parser.parse("final")); - REQUIRE(parser.parse("public static final")); - REQUIRE(!parser.parse("public public")); - REQUIRE(!parser.parse("public static public")); + REQUIRE(parser.parse("public")); + REQUIRE(parser.parse("static")); + REQUIRE(parser.parse("final")); + REQUIRE(parser.parse("public static final")); + REQUIRE(!parser.parse("public public")); + REQUIRE(!parser.parse("public static public")); } -TEST_CASE("Macro token check test", "[macro]") -{ - parser parser(R"( +TEST_CASE("Macro token check test", "[macro]") { + parser parser(R"( # Grammar for simple calculator... EXPRESSION <- _ LIST(TERM, TERM_OPERATOR) TERM <- LIST(FACTOR, FACTOR_OPERATOR) @@ -1021,14 +973,14 @@ TEST_CASE("Macro token check test", "[macro]") T(S) <- < S > _ )"); - REQUIRE(parser["EXPRESSION"].is_token() == false); - REQUIRE(parser["TERM"].is_token() == false); - REQUIRE(parser["FACTOR"].is_token() == false); - REQUIRE(parser["FACTOR_OPERATOR"].is_token() == true); - REQUIRE(parser["NUMBER"].is_token() == true); - REQUIRE(parser["_"].is_token() == true); - REQUIRE(parser["LIST"].is_token() == false); - REQUIRE(parser["T"].is_token() == true); + REQUIRE(parser["EXPRESSION"].is_token() == false); + REQUIRE(parser["TERM"].is_token() == false); + REQUIRE(parser["FACTOR"].is_token() == false); + REQUIRE(parser["FACTOR_OPERATOR"].is_token() == true); + REQUIRE(parser["NUMBER"].is_token() == true); + REQUIRE(parser["_"].is_token() == true); + REQUIRE(parser["LIST"].is_token() == false); + REQUIRE(parser["T"].is_token() == true); } TEST_CASE("Macro passes an arg to another macro", "[macro]") { @@ -1053,66 +1005,63 @@ TEST_CASE("Nested macro call", "[macro]") { REQUIRE(parser.parse("val")); } -TEST_CASE("Nested macro call2", "[macro]") -{ - parser parser(R"( +TEST_CASE("Nested macro call2", "[macro]") { + parser parser(R"( START <- A('TestVal1', 'TestVal2')+ A(Aarg1, Aarg2) <- B(Aarg1) '#End' B(Barg1) <- '#' Barg1 )"); - REQUIRE(parser.parse("#TestVal1#End")); + REQUIRE(parser.parse("#TestVal1#End")); } TEST_CASE("Line information test", "[line information]") { - parser parser(R"( + parser parser(R"( S <- _ (WORD _)+ WORD <- [A-Za-z]+ ~_ <- [ \t\r\n]+ )"); - std::vector> locations; - parser["WORD"] = [&](const peg::SemanticValues& sv) { - locations.push_back(sv.line_info()); - }; + std::vector> locations; + parser["WORD"] = [&](const peg::SemanticValues &vs) { + locations.push_back(vs.line_info()); + }; - bool ret = parser; - REQUIRE(ret == true); + bool ret = parser; + REQUIRE(ret == true); - ret = parser.parse(" Mon Tue Wed \nThu Fri Sat\nSun\n"); - REQUIRE(ret == true); + ret = parser.parse(" Mon Tue Wed \nThu Fri Sat\nSun\n"); + REQUIRE(ret == true); - REQUIRE(locations[0] == std::make_pair(1, 2)); - REQUIRE(locations[1] == std::make_pair(1, 6)); - REQUIRE(locations[2] == std::make_pair(1, 10)); - REQUIRE(locations[3] == std::make_pair(2, 1)); - REQUIRE(locations[4] == std::make_pair(2, 6)); - REQUIRE(locations[5] == std::make_pair(2, 11)); - REQUIRE(locations[6] == std::make_pair(3, 1)); + REQUIRE(locations[0] == std::make_pair(1, 2)); + REQUIRE(locations[1] == std::make_pair(1, 6)); + REQUIRE(locations[2] == std::make_pair(1, 10)); + REQUIRE(locations[3] == std::make_pair(2, 1)); + REQUIRE(locations[4] == std::make_pair(2, 6)); + REQUIRE(locations[5] == std::make_pair(2, 11)); + REQUIRE(locations[6] == std::make_pair(3, 1)); } -TEST_CASE("Dictionary", "[dic]") -{ - parser parser(R"( +TEST_CASE("Dictionary", "[dic]") { + parser parser(R"( START <- 'This month is ' MONTH '.' MONTH <- 'Jan' | 'January' | 'Feb' | 'February' )"); - REQUIRE(parser.parse("This month is Jan.")); - REQUIRE(parser.parse("This month is January.")); - REQUIRE_FALSE(parser.parse("This month is Jannuary.")); - REQUIRE_FALSE(parser.parse("This month is .")); + REQUIRE(parser.parse("This month is Jan.")); + REQUIRE(parser.parse("This month is January.")); + REQUIRE_FALSE(parser.parse("This month is Jannuary.")); + REQUIRE_FALSE(parser.parse("This month is .")); } -TEST_CASE("Dictionary invalid", "[dic]") -{ - parser parser(R"( +TEST_CASE("Dictionary invalid", "[dic]") { + parser parser(R"( START <- 'This month is ' MONTH '.' MONTH <- 'Jan' | 'January' | [a-z]+ | 'Feb' | 'February' )"); - bool ret = parser; - REQUIRE_FALSE(ret); + bool ret = parser; + REQUIRE_FALSE(ret); } // vim: et ts=4 sw=4 cin cino={1s ff=unix