diff --git a/CMakeLists.txt b/CMakeLists.txt index a9a7cf6..2712443 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,37 +1,26 @@ -cmake_minimum_required(VERSION 2.8) - -# Check if a supported compiler is used and add c++11 flag: -if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) - message(FATAL_ERROR "Need at least gcc 4.9 to compile.") - endif() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") -elseif(MSVC) - if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19) - message(FATAL_ERROR "Visual Studio 2015 or newer is required.") - endif() -elseif(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") - if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0) - message(FATAL_ERROR "Need at least AppleClang 7.0 to compile.") +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() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") -elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.4) - message(FATAL_ERROR "Clang below version 3.4 will most likely not work. Please upgrade your compiler.") - endif() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") -else() # no GNU, no MSVC, no Clang - message(WARNING "You are using an unsupported compiler. Compilation has only been tested with MSVC, GCC and Clang.") +endif() - include(CheckCXXCompilerFlag) - check_cxx_compiler_flag(-std=c++11 HAS_CXX11_FLAG) - if(HAS_CXX11_FLAG) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") - else() - message(FATAL_ERROR "Your compiler doesn't support the '-std=c++11' flag.") - endif() +if(${found} EQUAL -1) + message(FATAL_ERROR "Your compiler is not supported.") endif() +set(CMAKE_CXX_EXTENSIONS OFF) if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") diff --git a/README.md b/README.md index ac8025c..56136a2 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,14 @@ 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 [boost::any](http://www.boost.org/doc/libs/1_57_0/doc/html/any.html). It can wrap arbitrary data type. +`peg::any` is a simpler implementatin of [boost::any](http://www.boost.org/doc/libs/1_57_0/doc/html/any.html). It can wrap arbitrary data type. +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.) diff --git a/example/calc.cc b/example/calc.cc index 99caeb6..2b0c4db 100644 --- a/example/calc.cc +++ b/example/calc.cc @@ -10,20 +10,19 @@ #include using namespace peg; -using namespace std; int main(int argc, const char** argv) { - if (argc < 2 || string("--help") == argv[1]) { - cout << "usage: calc [formula]" << endl; + 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 = sv[0].get(); + auto result = any_cast(sv[0]); for (auto i = 1u; i < sv.size(); i += 2) { - auto num = sv[i + 1].get(); - auto ope = sv[i].get(); + auto num = any_cast(sv[i + 1]); + auto ope = any_cast(sv[i]); switch (ope) { case '+': result += num; break; case '-': result -= num; break; @@ -53,11 +52,11 @@ int main(int argc, const char** argv) auto expr = argv[1]; long val = 0; if (parser.parse(expr, val)) { - cout << expr << " = " << val << endl; + std::cout << expr << " = " << val << std::endl; return 0; } - cout << "syntax error..." << endl; + std::cout << "syntax error..." << std::endl; return -1; } diff --git a/example/calc2.cc b/example/calc2.cc index 59dd234..1ba00fa 100644 --- a/example/calc2.cc +++ b/example/calc2.cc @@ -10,7 +10,6 @@ #include using namespace peg; -using namespace std; // // PEG syntax: @@ -24,16 +23,16 @@ using namespace std; // int main(int argc, const char** argv) { - if (argc < 2 || string("--help") == argv[1]) { - cout << "usage: calc [formula]" << endl; + 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 = sv[0].get(); + auto result = any_cast(sv[0]); for (auto i = 1u; i < sv.size(); i += 2) { - auto num = sv[i + 1].get(); - auto ope = sv[i].get(); + auto num = any_cast(sv[i + 1]); + auto ope = any_cast(sv[i]); switch (ope) { case '+': result += num; break; case '-': result -= num; break; @@ -56,7 +55,7 @@ int main(int argc, const char** argv) auto expr = argv[1]; long val = 0; if (EXPRESSION.parse_and_get_value(expr, val).ret) { - cout << expr << " = " << val << endl; + std::cout << expr << " = " << val << std::endl; return 0; } diff --git a/example/calc3.cc b/example/calc3.cc index 723e7bf..f8f85bb 100644 --- a/example/calc3.cc +++ b/example/calc3.cc @@ -10,16 +10,15 @@ #include using namespace peg; -using namespace std; int main(int argc, const char** argv) { - if (argc < 2 || string("--help") == argv[1]) { - cout << "usage: calc3 [formula]" << endl; + if (argc < 2 || std::string("--help") == argv[1]) { + std::cout << "usage: calc3 [formula]" << std::endl; return 1; } - function eval = [&](const Ast& ast) { + std::function eval = [&](const Ast& ast) { if (ast.name == "NUMBER") { return stol(ast.token); } else { @@ -54,15 +53,15 @@ int main(int argc, const char** argv) parser.enable_ast(); auto expr = argv[1]; - shared_ptr ast; + std::shared_ptr ast; if (parser.parse(expr, ast)) { ast = AstOptimizer(true).optimize(ast); - cout << ast_to_s(ast); - cout << expr << " = " << eval(*ast) << endl; + std::cout << ast_to_s(ast); + std::cout << expr << " = " << eval(*ast) << std::endl; return 0; } - cout << "syntax error..." << endl; + std::cout << "syntax error..." << std::endl; return -1; } diff --git a/peglib.h b/peglib.h index 1ee75d2..e5ecc13 100644 --- a/peglib.h +++ b/peglib.h @@ -8,6 +8,14 @@ #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 + #include #include #include @@ -23,6 +31,9 @@ #include #include #include +#if PEGLIB_USE_STD_ANY +#include +#endif // guard for older versions of VC++ #ifdef _MSC_VER @@ -45,7 +56,15 @@ 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: @@ -85,55 +104,15 @@ public: delete content_; } - bool is_undefined() const { - return content_ == nullptr; - } - - template < - typename T, - typename std::enable_if::value, std::nullptr_t>::type = nullptr - > - T& get() { - if (!content_) { - throw std::bad_cast(); - } - auto p = dynamic_cast*>(content_); - assert(p); - if (!p) { - throw std::bad_cast(); - } - return p->value_; - } - - template < - typename T, - typename std::enable_if::value, std::nullptr_t>::type = nullptr - > - T& get() { - return *this; + bool has_value() const { + return content_ != nullptr; } - template < - typename T, - typename std::enable_if::value, std::nullptr_t>::type = nullptr - > - const T& get() const { - assert(content_); - auto p = dynamic_cast*>(content_); - assert(p); - if (!p) { - throw std::bad_cast(); - } - return p->value_; - } + template + friend T& any_cast(any& val); - template < - typename T, - typename std::enable_if::value, std::nullptr_t>::type = nullptr - > - const any& get() const { - return *this; - } + template + friend const T& any_cast(const any& val); private: struct placeholder { @@ -157,6 +136,41 @@ private: placeholder* content_; }; +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 <> +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 <> +const any& any_cast(const any& val) { + return val; +} +#endif + /*----------------------------------------------------------------------------- * scope_exit *---------------------------------------------------------------------------*/ @@ -499,7 +513,7 @@ struct SemanticValues : protected std::vector // Transform the semantic value vector to another vector template auto transform(size_t beg = 0, size_t end = static_cast(-1)) const -> vector { - return this->transform(beg, end, [](const any& v) { return v.get(); }); + return this->transform(beg, end, [](const any& v) { return any_cast(v); }); } SemanticValues() : s_(nullptr), n_(0), choice_count_(0), choice_(0) {} @@ -2061,8 +2075,8 @@ public: SemanticValues sv; any dt; auto r = parse_core(s, n, sv, dt, path); - if (r.ret && !sv.empty() && !sv.front().is_undefined()) { - val = sv[0].get(); + if (r.ret && !sv.empty() && sv.front().has_value()) { + val = any_cast(sv[0]); } return r; } @@ -2077,8 +2091,8 @@ public: Result parse_and_get_value(const char* s, size_t n, 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().is_undefined()) { - val = sv[0].get(); + if (r.ret && !sv.empty() && sv.front().has_value()) { + val = any_cast(sv[0]); } return r; } @@ -2645,19 +2659,19 @@ private: void setup_actions() { g["Definition"] = [&](const SemanticValues& sv, any& dt) { auto is_macro = sv.choice() == 0; - auto ignore = sv[0].get(); - auto name = sv[1].get(); + auto ignore = any_cast(sv[0]); + auto name = any_cast(sv[ 1 ]); std::vector params; std::shared_ptr ope; if (is_macro) { - params = sv[2].get>(); - ope = sv[4].get>(); + params = any_cast>(sv[2]); + ope = any_cast>(sv[4]); } else { - ope = sv[3].get>(); + ope = any_cast>(sv[3]); } - Data& data = *dt.get(); + Data& data = *any_cast(dt); auto& grammar = *data.grammar; if (!grammar.count(name)) { @@ -2678,11 +2692,11 @@ private: g["Expression"] = [&](const SemanticValues& sv) { if (sv.size() == 1) { - return sv[0].get>(); + return any_cast>(sv[0]); } else { std::vector> opes; for (auto i = 0u; i < sv.size(); i++) { - opes.emplace_back(sv[i].get>()); + opes.emplace_back(any_cast>(sv[i])); } const std::shared_ptr ope = std::make_shared(opes); return ope; @@ -2691,11 +2705,11 @@ private: g["Sequence"] = [&](const SemanticValues& sv) { if (sv.size() == 1) { - return sv[0].get>(); + return any_cast>(sv[0]); } else { std::vector> opes; for (const auto& x: sv) { - opes.emplace_back(x.get>()); + opes.emplace_back(any_cast>(x)); } const std::shared_ptr ope = std::make_shared(opes); return ope; @@ -2705,11 +2719,11 @@ private: g["Prefix"] = [&](const SemanticValues& sv) { std::shared_ptr ope; if (sv.size() == 1) { - ope = sv[0].get>(); + ope = any_cast>(sv[0]); } else { assert(sv.size() == 2); - auto tok = sv[0].get(); - ope = sv[1].get>(); + auto tok = any_cast(sv[0]); + ope = any_cast>(sv[1]); if (tok == '&') { ope = apd(ope); } else { // '!' @@ -2720,12 +2734,12 @@ private: }; g["Suffix"] = [&](const SemanticValues& sv) { - auto ope = sv[0].get>(); + auto ope = any_cast>(sv[0]); if (sv.size() == 1) { return ope; } else { assert(sv.size() == 2); - auto tok = sv[1].get(); + auto tok = any_cast(sv[1]); if (tok == '?') { return opt(ope); } else if (tok == '*') { @@ -2737,18 +2751,18 @@ private: }; g["Primary"] = [&](const SemanticValues& sv, any& dt) -> std::shared_ptr { - Data& data = *dt.get(); + Data& data = *any_cast(dt); switch (sv.choice()) { case 0: // Macro Reference case 1: { // Reference auto is_macro = sv.choice() == 0; - auto ignore = sv[0].get(); - const auto& ident = sv[1].get(); + auto ignore = any_cast(sv[0]); + const auto& ident = any_cast(sv[1]); std::vector> args; if (is_macro) { - args = sv[2].get>>(); + args = any_cast>>(sv[2]); } if (ignore) { @@ -2758,23 +2772,23 @@ private: } } case 2: { // (Expression) - return sv[0].get>(); + return any_cast>(sv[0]); } case 3: { // TokenBoundary - return tok(sv[0].get>()); + return tok(any_cast>(sv[0])); } case 4: { // CaptureScope - return csc(sv[0].get>()); + return csc(any_cast>(sv[0])); } case 5: { // Capture - const auto& name = sv[0].get(); - auto ope = sv[1].get>(); + const auto& name = any_cast(sv[0]); + auto ope = any_cast>(sv[1]); return cap(ope, [name](const char* a_s, size_t a_n, Context& c) { c.capture_scope_stack.back()[name] = std::string(a_s, a_n); }); } default: { - return sv[0].get>(); + return any_cast>(sv[0]); } } }; @@ -2805,14 +2819,14 @@ private: g["Range"] = [](const SemanticValues& sv) { switch (sv.choice()) { case 0: { - auto s1 = sv[0].get(); - auto s2 = sv[1].get(); + 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); } case 1: { - auto s = sv[0].get(); + auto s = any_cast(sv[0]); auto cp = decode_codepoint(s.c_str(), s.length()); return std::make_pair(cp, cp); } diff --git a/test/test.cc b/test/test.cc index 679aa69..1a00e03 100644 --- a/test/test.cc +++ b/test/test.cc @@ -44,7 +44,7 @@ TEST_CASE("Action taking non const Semantic Values parameter", "[general]") )"); parser["ROOT"] = [&](peg::SemanticValues& sv) { - auto& s = sv[0].get(); + auto s = peg::any_cast(sv[0]); s[0] = 'H'; // mutate return std::string(std::move(s)); // move }; @@ -83,11 +83,10 @@ TEST_CASE("String capture test", "[general]") } using namespace peg; -using namespace std; TEST_CASE("String capture test2", "[general]") { - vector tags; + std::vector tags; Definition ROOT, TAG, TAG_NAME, WS; ROOT <= seq(WS, zom(TAG)); @@ -178,7 +177,7 @@ TEST_CASE("Lambda action test", "[general]") CHAR <- . )"); - string ss; + std::string ss; parser["CHAR"] = [&](const SemanticValues& sv) { ss += *sv.c_str(); }; @@ -198,18 +197,18 @@ TEST_CASE("enter/leave handlers test", "[general]") )"); parser["LTOKEN"].enter = [&](const char*, size_t, any& dt) { - auto& require_upper_case = *dt.get(); + 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 = *dt.get(); + auto& require_upper_case = *any_cast(dt); require_upper_case = true; }; auto message = "should be upper case string..."; parser["TOKEN"] = [&](const SemanticValues& sv, any& dt) { - auto& require_upper_case = *dt.get(); + 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)) { @@ -225,7 +224,7 @@ TEST_CASE("enter/leave handlers test", "[general]") REQUIRE(parser.parse("hello=WORLD", dt) == true); REQUIRE(parser.parse("HELLO=WORLD", dt) == true); - parser.log = [&](size_t ln, size_t col, const string& msg) { + parser.log = [&](size_t ln, size_t col, const std::string& msg) { REQUIRE(ln == 1); REQUIRE(col == 7); REQUIRE(msg == message); @@ -264,7 +263,7 @@ TEST_CASE("WHITESPACE test2", "[general]") TAB <- '\t' )"); - vector items; + std::vector items; parser["ITEM"] = [&](const SemanticValues& sv) { items.push_back(sv.token()); }; @@ -398,7 +397,7 @@ TEST_CASE("Backtracking with AST", "[general]") )"); parser.enable_ast(); - shared_ptr ast; + std::shared_ptr ast; bool ret = parser.parse("ba", ast); REQUIRE(ret == true); REQUIRE(ast->nodes.size() == 2); @@ -437,7 +436,7 @@ TEST_CASE("Ignore case test", "[general]") { TEST_CASE("mutable lambda test", "[general]") { - vector vec; + std::vector vec; parser pg("ROOT <- 'mutable lambda test'"); @@ -459,18 +458,18 @@ TEST_CASE("Simple calculator test", "[general]") parser["Additive"] = [](const SemanticValues& sv) { switch (sv.choice()) { case 0: - return sv[0].get() + sv[1].get(); + return any_cast(sv[0]) + any_cast(sv[1]); default: - return sv[0].get(); + return any_cast(sv[0]); } }; parser["Multitive"] = [](const SemanticValues& sv) { switch (sv.choice()) { case 0: - return sv[0].get() * sv[1].get(); + return any_cast(sv[0]) * any_cast(sv[1]); default: - return sv[0].get(); + return any_cast(sv[0]); } }; @@ -498,10 +497,10 @@ TEST_CASE("Calculator test", "[general]") // Setup actions auto reduce = [](const SemanticValues& sv) -> long { - long ret = sv[0].get(); + long ret = any_cast(sv[0]); for (auto i = 1u; i < sv.size(); i += 2) { - auto num = sv[i + 1].get(); - switch (sv[i].get()) { + auto num = any_cast(sv[i + 1]); + switch (any_cast(sv[i])) { case '+': ret += num; break; case '-': ret -= num; break; case '*': ret *= num; break; @@ -538,16 +537,16 @@ TEST_CASE("Calculator test2", "[general]") NUMBER <- [0-9]+ )"; - string start; + 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 = sv[0].get(); + long ret = any_cast(sv[0]); for (auto i = 1u; i < sv.size(); i += 2) { - auto num = sv[i + 1].get(); - switch (sv[i].get()) { + auto num = any_cast(sv[i + 1]); + switch (any_cast(sv[i])) { case '+': ret += num; break; case '-': ret -= num; break; case '*': ret *= num; break; @@ -585,10 +584,10 @@ TEST_CASE("Calculator test3", "[general]") )"); auto reduce = [](const SemanticValues& sv) -> long { - long ret = sv[0].get(); + long ret = any_cast(sv[0]); for (auto i = 1u; i < sv.size(); i += 2) { - auto num = sv[i + 1].get(); - switch (sv[i].get()) { + auto num = any_cast(sv[i + 1]); + switch (any_cast(sv[i])) { case '+': ret += num; break; case '-': ret -= num; break; case '*': ret *= num; break; @@ -627,7 +626,7 @@ TEST_CASE("Calculator test with AST", "[general]") parser.enable_ast(); - function eval = [&](const Ast& ast) { + std::function eval = [&](const Ast& ast) { if (ast.name == "NUMBER") { return stol(ast.token); } else { @@ -647,7 +646,7 @@ TEST_CASE("Calculator test with AST", "[general]") } }; - shared_ptr ast; + std::shared_ptr ast; auto ret = parser.parse("1+2*3*(4-5+6)/7-8", ast); ast = peg::AstOptimizer(true).optimize(ast); auto val = eval(*ast); @@ -667,7 +666,7 @@ TEST_CASE("Ignore semantic value test", "[general]") parser.enable_ast(); - shared_ptr ast; + std::shared_ptr ast; auto ret = parser.parse("Hello World", ast); REQUIRE(ret == true); @@ -687,7 +686,7 @@ TEST_CASE("Ignore semantic value of 'or' predicate test", "[general]") parser.enable_ast(); - shared_ptr ast; + std::shared_ptr ast; auto ret = parser.parse("Hello World.", ast); REQUIRE(ret == true); @@ -706,7 +705,7 @@ TEST_CASE("Ignore semantic value of 'and' predicate test", "[general]") parser.enable_ast(); - shared_ptr ast; + std::shared_ptr ast; auto ret = parser.parse("Hello World.", ast); REQUIRE(ret == true); @@ -721,7 +720,7 @@ TEST_CASE("Literal token on AST test1", "[general]") )"); parser.enable_ast(); - shared_ptr ast; + std::shared_ptr ast; auto ret = parser.parse(R"("a\tb")", ast); REQUIRE(ret == true); @@ -739,7 +738,7 @@ TEST_CASE("Literal token on AST test2", "[general]") )"); parser.enable_ast(); - shared_ptr ast; + std::shared_ptr ast; auto ret = parser.parse(R"("a\tb")", ast); REQUIRE(ret == true); @@ -757,7 +756,7 @@ TEST_CASE("Literal token on AST test3", "[general]") )"); parser.enable_ast(); - shared_ptr ast; + std::shared_ptr ast; auto ret = parser.parse(R"("a\tb")", ast); REQUIRE(ret == true); @@ -798,12 +797,12 @@ TEST_CASE("Semantic values test", "[general]") for (const auto& rule: parser.get_rule_names()){ parser[rule.c_str()] = [rule](const SemanticValues& sv, any&) { if (rule == "term") { - REQUIRE(sv[0].get() == "a at 0"); - REQUIRE(sv[1].get() == "b at 1"); - REQUIRE(sv[2].get() == "c at 2"); - return string(); + 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 " + to_string(sv.c_str() - sv.ss); + return rule + " at " + std::to_string(sv.c_str() - sv.ss); } }; } @@ -1149,7 +1148,7 @@ TEST_CASE("User defined rule test", "[user rule]") { { "NAME", usr([](const char* s, size_t n, SemanticValues& /*sv*/, any& /*dt*/) -> size_t { - static vector names = { "PEG", "BNF" }; + 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(); @@ -1336,10 +1335,10 @@ TEST_CASE("Macro calculator", "[macro]") // Setup actions auto reduce = [](const SemanticValues& sv) -> long { - auto result = sv[0].get(); + auto result = any_cast(sv[0]); for (auto i = 1u; i < sv.size(); i += 2) { - auto num = sv[i + 1].get(); - auto ope = sv[i].get(); + auto num = any_cast(sv[i + 1]); + auto ope = any_cast(sv[i]); switch (ope) { case '+': result += num; break; case '-': result -= num; break; @@ -1462,7 +1461,7 @@ TEST_CASE("Line information test", "[line information]") ~_ <- [ \t\r\n]+ )"); - std::vector> locations; + std::vector> locations; parser["WORD"] = [&](const peg::SemanticValues& sv) { locations.push_back(sv.line_info()); }; @@ -1473,13 +1472,13 @@ TEST_CASE("Line information test", "[line information]") 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)); } bool exact(Grammar& g, const char* d, const char* s) {