diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ebcef9..2ed8dab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ -cmake_minimum_required(VERSION 3.1.0) -project("cpp-peglib") +cmake_minimum_required(VERSION 3.14) +project(cpp-peglib) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_EXTENSIONS OFF) diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 2c6aef2..74704bb 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -1,10 +1,8 @@ -cmake_minimum_required(VERSION 3.1) +cmake_minimum_required(VERSION 3.14) project(example) include_directories(..) -set(CMAKE_CXX_STANDARD 17) - add_executable(calc calc.cc) target_link_libraries(calc ${add_link_deps}) diff --git a/lint/CMakeLists.txt b/lint/CMakeLists.txt index 1c7e632..c91dcd2 100644 --- a/lint/CMakeLists.txt +++ b/lint/CMakeLists.txt @@ -1,9 +1,7 @@ -cmake_minimum_required(VERSION 3.1) +cmake_minimum_required(VERSION 3.14) project(peglint) include_directories(..) -set(CMAKE_CXX_STANDARD 17) - add_executable(peglint peglint.cc) target_link_libraries(peglint ${add_link_deps}) diff --git a/pl0/CMakeLists.txt b/pl0/CMakeLists.txt index 5d88b45..ed24527 100644 --- a/pl0/CMakeLists.txt +++ b/pl0/CMakeLists.txt @@ -1,10 +1,8 @@ -cmake_minimum_required(VERSION 3.1) +/Users/yhirose/Projects/cpp-peglib/.travis.yml project(pl0) include_directories(..) -set(CMAKE_CXX_STANDARD 17) - add_executable(pl0 pl0.cc) find_package(LLVM REQUIRED CONFIG) set(add_link_deps ${add_link_deps} LLVM) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 036f16d..8d62d0d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,23 +1,21 @@ -cmake_minimum_required(VERSION 3.1) +cmake_minimum_required(VERSION 3.14) project(test) -Include(FetchContent) - +include(FetchContent) FetchContent_Declare( - Catch2 - GIT_REPOSITORY https://github.com/catchorg/Catch2.git - GIT_TAG v3.0.0-preview3 + googletest + URL https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip ) -FetchContent_MakeAvailable(Catch2) +# For Windows: Prevent overriding the parent project's compiler/linker settings +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +FetchContent_MakeAvailable(googletest) -set(CMAKE_CXX_STANDARD 17) +enable_testing() add_executable(test-main test1.cc test2.cc test3.cc) target_include_directories(test-main PRIVATE ..) -target_link_libraries(test-main PRIVATE Catch2::Catch2WithMain) -add_test( - NAME TestMain - COMMAND test-main - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) +include(GoogleTest) +gtest_discover_tests(test-main) +target_link_libraries(test-main PRIVATE gtest_main) diff --git a/test/test1.cc b/test/test1.cc index adcfee3..dcee09f 100644 --- a/test/test1.cc +++ b/test/test1.cc @@ -1,75 +1,75 @@ -#include +#include #include using namespace peg; #if !defined(PEGLIB_NO_UNICODE_CHARS) -TEST_CASE("Simple syntax test (with unicode)", "[general]") { +TEST(GeneralTest, Simple_syntax_test_with_unicode) { parser parser(u8" ROOT ← _ " " _ <- ' ' "); bool ret = parser; - REQUIRE(ret == true); + EXPECT_TRUE(ret); } #endif -TEST_CASE("Simple syntax test", "[general]") { +TEST(GeneralTest, Simple_syntax_test) { parser parser(R"( ROOT <- _ _ <- ' ' )"); bool ret = parser; - REQUIRE(ret == true); + EXPECT_TRUE(ret); } -TEST_CASE("Empty syntax test", "[general]") { +TEST(GeneralTest, Empty_syntax_test) { parser parser(""); bool ret = parser; - REQUIRE(ret == false); + EXPECT_FALSE(ret); } -TEST_CASE("Start rule with ignore operator test", "[general]") { +TEST(GeneralTest, Start_rule_with_ignore_operator_test) { parser parser(R"( ~ROOT <- _ _ <- ' ' )"); bool ret = parser; - REQUIRE(ret == false); + EXPECT_FALSE(ret); } -TEST_CASE("Invalid UTF-8 text test", "[general]") { +TEST(GeneralTest, Invalid_UTF8_text_test) { std::string s = "a <- '"; s += static_cast(0xe8); // Make invalid utf8 text... parser parser(s.data()); bool ret = parser; - REQUIRE(ret == false); + EXPECT_FALSE(ret); } -TEST_CASE("Backslash escape sequence test", "[general]") { +TEST(GeneralTest, Backslash_escape_sequence_test) { parser parser(R"( ROOT <- _ _ <- '\\' )"); bool ret = parser; - REQUIRE(ret == true); + EXPECT_TRUE(ret); } -TEST_CASE("Invalid escape sequence test", "[general]") { +TEST(GeneralTest, Invalid_escape_sequence_test) { parser parser(R"( ROOT <- _ _ <- '\' )"); bool ret = parser; - REQUIRE(ret == false); + EXPECT_FALSE(ret); } -TEST_CASE("Action taking non const Semantic Values parameter", "[general]") { +TEST(GeneralTest, Action_taking_non_const_Semantic_Values_parameter) { parser parser(R"( ROOT <- TEXT TEXT <- [a-zA-Z]+ @@ -85,11 +85,11 @@ TEST_CASE("Action taking non const Semantic Values parameter", "[general]") { std::string val; auto ret = parser.parse("hello", val); - REQUIRE(ret == true); - REQUIRE(val == "Hello"); + EXPECT_TRUE(ret); + EXPECT_EQ("Hello", val); } -TEST_CASE("String capture test", "[general]") { +TEST(GeneralTest, String_capture_test) { parser parser(R"( ROOT <- _ ('[' TAG_NAME ']' _)* TAG_NAME <- (!']' .)+ @@ -104,16 +104,16 @@ TEST_CASE("String capture test", "[general]") { 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"); + EXPECT_TRUE(ret); + EXPECT_EQ(3, tags.size()); + EXPECT_EQ("tag1", tags[0]); + EXPECT_EQ("tag:2", tags[1]); + EXPECT_EQ("tag-3", tags[2]); } using namespace peg; -TEST_CASE("String capture test2", "[general]") { +TEST(GeneralTest, String_capture_test2) { std::vector tags; Definition ROOT, TAG, TAG_NAME, WS; @@ -125,14 +125,14 @@ TEST_CASE("String capture test2", "[general]") { 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"); + EXPECT_TRUE(r.ret); + EXPECT_EQ(3, tags.size()); + EXPECT_EQ("tag1", tags[0]); + EXPECT_EQ("tag:2", tags[1]); + EXPECT_EQ("tag-3", tags[2]); } -TEST_CASE("String capture test3", "[general]") { +TEST(GeneralTest, String_capture_test3) { parser pg(R"( ROOT <- _ TOKEN* TOKEN <- '[' < (!']' .)+ > ']' _ @@ -145,14 +145,14 @@ TEST_CASE("String capture test3", "[general]") { 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"); + EXPECT_TRUE(ret); + EXPECT_EQ(3, tags.size()); + EXPECT_EQ("tag1", tags[0]); + EXPECT_EQ("tag:2", tags[1]); + EXPECT_EQ("tag-3", tags[2]); } -TEST_CASE("Cyclic grammer test", "[general]") { +TEST(GeneralTest, Cyclic_grammer_test) { Definition PARENT; Definition CHILD; @@ -160,7 +160,7 @@ TEST_CASE("Cyclic grammer test", "[general]") { CHILD <= seq(PARENT); } -TEST_CASE("Visit test", "[general]") { +TEST(GeneralTest, Visit_test) { Definition ROOT, TAG, TAG_NAME, WS; ROOT <= seq(WS, zom(TAG)); @@ -171,10 +171,10 @@ TEST_CASE("Visit test", "[general]") { AssignIDToDefinition defIds; ROOT.accept(defIds); - REQUIRE(defIds.ids.size() == 4); + EXPECT_EQ(4, defIds.ids.size()); } -TEST_CASE("Token check test", "[general]") { +TEST(GeneralTest, Token_check_test) { parser parser(R"( EXPRESSION <- _ TERM (TERM_OPERATOR TERM)* TERM <- FACTOR (FACTOR_OPERATOR FACTOR)* @@ -185,14 +185,14 @@ 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); + EXPECT_FALSE(parser["EXPRESSION"].is_token()); + EXPECT_FALSE(parser["FACTOR"].is_token()); + EXPECT_TRUE(parser["FACTOR_OPERATOR"].is_token()); + EXPECT_TRUE(parser["NUMBER"].is_token()); + EXPECT_TRUE(parser["_"].is_token()); } -TEST_CASE("Lambda action test", "[general]") { +TEST(GeneralTest, Lambda_action_test) { parser parser(R"( START <- (CHAR)* CHAR <- . @@ -202,11 +202,11 @@ TEST_CASE("Lambda action test", "[general]") { parser["CHAR"] = [&](const SemanticValues &vs) { ss += *vs.sv().data(); }; bool ret = parser.parse("hello"); - REQUIRE(ret == true); - REQUIRE(ss == "hello"); + EXPECT_TRUE(ret); + EXPECT_EQ("hello", ss); } -TEST_CASE("enter/leave handlers test", "[general]") { +TEST(GeneralTest, enter_leave_handlers_test) { parser parser(R"( START <- LTOKEN '=' RTOKEN LTOKEN <- TOKEN @@ -238,20 +238,20 @@ TEST_CASE("enter/leave handlers test", "[general]") { 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); + EXPECT_FALSE(parser.parse("hello=world", dt)); + EXPECT_FALSE(parser.parse("HELLO=world", dt)); + EXPECT_TRUE(parser.parse("hello=WORLD", dt)); + EXPECT_TRUE(parser.parse("HELLO=WORLD", dt)); parser.log = [&](size_t ln, size_t col, const std::string &msg) { - REQUIRE(ln == 1); - REQUIRE(col == 7); - REQUIRE(msg == message); + EXPECT_EQ(1, ln); + EXPECT_EQ(7, col); + EXPECT_EQ(message, msg); }; parser.parse("hello=world", dt); } -TEST_CASE("WHITESPACE test", "[general]") { +TEST(GeneralTest, WHITESPACE_test) { parser parser(R"( # Rules ROOT <- ITEM (',' ITEM)* @@ -266,10 +266,10 @@ TEST_CASE("WHITESPACE test", "[general]") { auto ret = parser.parse(R"( one, "two, three", four )"); - REQUIRE(ret == true); + EXPECT_TRUE(ret); } -TEST_CASE("WHITESPACE test2", "[general]") { +TEST(GeneralTest, WHITESPACE_test2) { parser parser(R"( # Rules ROOT <- ITEM (',' ITEM)* @@ -287,14 +287,14 @@ TEST_CASE("WHITESPACE test2", "[general]") { 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"); + EXPECT_TRUE(ret); + EXPECT_EQ(3, items.size()); + EXPECT_EQ("one", items[0]); + EXPECT_EQ("two", items[1]); + EXPECT_EQ("three", items[2]); } -TEST_CASE("WHITESPACE test3", "[general]") { +TEST(GeneralTest, WHITESPACE_test3) { parser parser(R"( StrQuot <- < '"' < (StrEscape / StrChars)* > '"' > StrEscape <- '\\' any @@ -304,14 +304,14 @@ TEST_CASE("WHITESPACE test3", "[general]") { )"); parser["StrQuot"] = [](const SemanticValues &vs) { - REQUIRE(vs.token() == R"( aaa \" bbb )"); + EXPECT_EQ(R"( aaa \" bbb )", vs.token()); }; auto ret = parser.parse(R"( " aaa \" bbb " )"); - REQUIRE(ret == true); + EXPECT_TRUE(ret); } -TEST_CASE("WHITESPACE test4", "[general]") { +TEST(GeneralTest, WHITESPACE_test4) { parser parser(R"( ROOT <- HELLO OPE WORLD HELLO <- 'hello' @@ -321,60 +321,66 @@ TEST_CASE("WHITESPACE test4", "[general]") { )"); parser["HELLO"] = [](const SemanticValues &vs) { - REQUIRE(vs.token() == "hello"); + EXPECT_EQ("hello", vs.token()); }; - parser["OPE"] = [](const SemanticValues &vs) { REQUIRE(vs.token() == "+"); }; + parser["OPE"] = [](const SemanticValues &vs) { + EXPECT_EQ("+", vs.token()); + }; parser["WORLD"] = [](const SemanticValues &vs) { - REQUIRE(vs.token() == "world"); + EXPECT_EQ("world", vs.token()); }; auto ret = parser.parse(" hello + world "); - REQUIRE(ret == true); + EXPECT_TRUE(ret); } -TEST_CASE("Word expression test", "[general]") { +TEST(GeneralTest, Word_expression_test) { 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); + EXPECT_FALSE(parser.parse("helloworld")); + EXPECT_TRUE(parser.parse("hello world")); + EXPECT_TRUE(parser.parse("hello,world")); + EXPECT_TRUE(parser.parse("hello, world")); + EXPECT_TRUE(parser.parse("hello , world")); } -TEST_CASE("Skip token test", "[general]") { +TEST(GeneralTest, Skip_token_test) { parser parser(" ROOT <- _ ITEM (',' _ ITEM _)* " " ITEM <- ([a-z0-9])+ " " ~_ <- [ \t]* "); - parser["ROOT"] = [&](const SemanticValues &vs) { REQUIRE(vs.size() == 2); }; + parser["ROOT"] = [&](const SemanticValues &vs) { + EXPECT_EQ(2, vs.size()); + }; auto ret = parser.parse(" item1, item2 "); - REQUIRE(ret == true); + EXPECT_TRUE(ret); } -TEST_CASE("Skip token test2", "[general]") { +TEST(GeneralTest, Skip_token_test2) { parser parser(R"( ROOT <- ITEM (',' ITEM)* ITEM <- < ([a-z0-9])+ > %whitespace <- [ \t]* )"); - parser["ROOT"] = [&](const SemanticValues &vs) { REQUIRE(vs.size() == 2); }; + parser["ROOT"] = [&](const SemanticValues &vs) { + EXPECT_EQ(2, vs.size()); + }; auto ret = parser.parse(" item1, item2 "); - REQUIRE(ret == true); + EXPECT_TRUE(ret); } -TEST_CASE("Custom AST test", "[general]") { +TEST(GeneralTest, Custom_AST_test) { struct CustomType {}; using CustomAst = AstBase; @@ -387,11 +393,11 @@ TEST_CASE("Custom AST test", "[general]") { parser.enable_ast(); std::shared_ptr ast; bool ret = parser.parse("a b c", ast); - REQUIRE(ret == true); - REQUIRE(ast->nodes.size() == 4); + EXPECT_TRUE(ret); + EXPECT_EQ(4, ast->nodes.size()); } -TEST_CASE("Backtracking test", "[general]") { +TEST(GeneralTest, Backtracking_test) { parser parser(R"( START <- PAT1 / PAT2 PAT1 <- HELLO ' One' @@ -405,11 +411,11 @@ TEST_CASE("Backtracking test", "[general]") { parser.enable_packrat_parsing(); bool ret = parser.parse("Hello Two"); - REQUIRE(ret == true); - REQUIRE(count == 1); // Skip second time + EXPECT_TRUE(ret); + EXPECT_EQ(1, count); // Skip second time } -TEST_CASE("Backtracking with AST", "[general]") { +TEST(GeneralTest, Backtracking_with_AST) { parser parser(R"( S <- A? B (A B)* A A <- 'a' @@ -419,19 +425,19 @@ TEST_CASE("Backtracking with AST", "[general]") { parser.enable_ast(); std::shared_ptr ast; bool ret = parser.parse("ba", ast); - REQUIRE(ret == true); - REQUIRE(ast->nodes.size() == 2); + EXPECT_TRUE(ret); + EXPECT_EQ(2, ast->nodes.size()); } -TEST_CASE("Octal/Hex/Unicode value test", "[general]") { +TEST(GeneralTest, Octal_Hex_Unicode_value_test) { parser parser(R"( ROOT <- '\132\x7a\u30f3' )"); auto ret = parser.parse("Zzン"); - REQUIRE(ret == true); + EXPECT_TRUE(ret); } -TEST_CASE("Ignore case test", "[general]") { +TEST(GeneralTest, Ignore_case_test) { parser parser(R"( ROOT <- HELLO WORLD HELLO <- 'hello'i @@ -440,18 +446,18 @@ TEST_CASE("Ignore case test", "[general]") { )"); parser["HELLO"] = [](const SemanticValues &vs) { - REQUIRE(vs.token() == "Hello"); + EXPECT_EQ("Hello", vs.token()); }; parser["WORLD"] = [](const SemanticValues &vs) { - REQUIRE(vs.token() == "World"); + EXPECT_EQ("World", vs.token()); }; auto ret = parser.parse(" Hello World "); - REQUIRE(ret == true); + EXPECT_TRUE(ret); } -TEST_CASE("mutable lambda test", "[general]") { +TEST(GeneralTest, mutable_lambda_test) { std::vector vec; parser pg("ROOT <- 'mutable lambda test'"); @@ -462,7 +468,7 @@ TEST_CASE("mutable lambda test", "[general]") { }; } -TEST_CASE("Simple calculator test", "[general]") { +TEST(GeneralTest, Simple_calculator_test) { parser parser(R"( Additive <- Multitive '+' Additive / Multitive Multitive <- Primary '*' Multitive / Primary @@ -484,15 +490,17 @@ TEST_CASE("Simple calculator test", "[general]") { } }; - parser["Number"] = [](const SemanticValues &vs) { return vs.token_to_number(); }; + parser["Number"] = [](const SemanticValues &vs) { + return vs.token_to_number(); + }; int val; parser.parse("(1+2)*3", val); - REQUIRE(val == 9); + EXPECT_EQ(9, val); } -TEST_CASE("Calculator test", "[general]") { +TEST(GeneralTest, Calculator_test) { // Construct grammer Definition EXPRESSION, TERM, FACTOR, TERM_OPERATOR, FACTOR_OPERATOR, NUMBER; @@ -528,11 +536,11 @@ TEST_CASE("Calculator test", "[general]") { 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); + EXPECT_TRUE(r.ret); + EXPECT_EQ(-3, val); } -TEST_CASE("Calculator test2", "[general]") { +TEST(GeneralTest, Calculator_test2) { // Parse syntax auto syntax = R"( # Grammar for Calculator... @@ -546,7 +554,8 @@ TEST_CASE("Calculator test2", "[general]") { std::string start; bool enablePackratParsing = false; - auto grammar = ParserGenerator::parse(syntax, strlen(syntax), start, enablePackratParsing, nullptr); + auto grammar = ParserGenerator::parse(syntax, strlen(syntax), start, + enablePackratParsing, nullptr); auto &g = *grammar; // Setup actions @@ -567,18 +576,22 @@ TEST_CASE("Calculator test2", "[general]") { 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(); }; + 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); - REQUIRE(r.ret == true); - REQUIRE(val == -3); + EXPECT_TRUE(r.ret); + EXPECT_EQ(-3, val); } -TEST_CASE("Calculator test3", "[general]") { +TEST(GeneralTest, Calculator_test3) { // Parse syntax parser parser(R"( # Grammar for Calculator... @@ -613,17 +626,19 @@ TEST_CASE("Calculator test3", "[general]") { parser["FACTOR_OPERATOR"] = [](const SemanticValues &vs) { return static_cast(*vs.sv().data()); }; - parser["NUMBER"] = [](const SemanticValues &vs) { return vs.token_to_number(); }; + 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); - REQUIRE(ret == true); - REQUIRE(val == -3); + EXPECT_TRUE(ret); + EXPECT_EQ(-3, val); } -TEST_CASE("Calculator test with AST", "[general]") { +TEST(GeneralTest, Calculator_test_with_AST) { parser parser(R"( EXPRESSION <- _ TERM (TERM_OPERATOR TERM)* TERM <- FACTOR (FACTOR_OPERATOR FACTOR)* @@ -661,11 +676,11 @@ TEST_CASE("Calculator test with AST", "[general]") { ast = parser.optimize_ast(ast); auto val = eval(*ast); - REQUIRE(ret == true); - REQUIRE(val == -3); + EXPECT_TRUE(ret); + EXPECT_EQ(-3, val); } -TEST_CASE("Calculator test with combinators and AST", "[general]") { +TEST(GeneralTest, Calculator_test_with_combinators_and_AST) { // Construct grammer AST_DEFINITIONS(EXPRESSION, TERM, FACTOR, TERM_OPERATOR, FACTOR_OPERATOR, NUMBER); @@ -702,11 +717,11 @@ TEST_CASE("Calculator test with combinators and AST", "[general]") { ast = AstOptimizer(true).optimize(ast); auto val = eval(*ast); - REQUIRE(r.ret == true); - REQUIRE(val == -3); + EXPECT_TRUE(r.ret); + EXPECT_EQ(-3, val); } -TEST_CASE("Ignore semantic value test", "[general]") { +TEST(GeneralTest, Ignore_semantic_value_test) { parser parser(R"( START <- ~HELLO WORLD HELLO <- 'Hello' _ @@ -719,12 +734,12 @@ TEST_CASE("Ignore semantic value test", "[general]") { 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"); + EXPECT_TRUE(ret); + EXPECT_EQ(1, ast->nodes.size()); + EXPECT_EQ("WORLD", ast->nodes[0]->name); } -TEST_CASE("Ignore semantic value of 'or' predicate test", "[general]") { +TEST(GeneralTest, Ignore_semantic_value_of_or_predicate_test) { parser parser(R"( START <- _ !DUMMY HELLO_WORLD '.' HELLO_WORLD <- HELLO 'World' _ @@ -738,12 +753,12 @@ TEST_CASE("Ignore semantic value of 'or' predicate test", "[general]") { 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"); + EXPECT_TRUE(ret); + EXPECT_EQ(1, ast->nodes.size()); + EXPECT_EQ("HELLO_WORLD", ast->nodes[0]->name); } -TEST_CASE("Ignore semantic value of 'and' predicate test", "[general]") { +TEST(GeneralTest, Ignore_semantic_value_of_and_predicate_test) { parser parser(R"( START <- _ &HELLO HELLO_WORLD '.' HELLO_WORLD <- HELLO 'World' _ @@ -756,12 +771,12 @@ TEST_CASE("Ignore semantic value of 'and' predicate test", "[general]") { 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"); + EXPECT_TRUE(ret); + EXPECT_EQ(1, ast->nodes.size()); + EXPECT_EQ("HELLO_WORLD", ast->nodes[0]->name); } -TEST_CASE("Literal token on AST test1", "[general]") { +TEST(GeneralTest, Literal_token_on_AST_test1) { parser parser(R"( STRING_LITERAL <- '"' (('\\"' / '\\t' / '\\n') / (!["] .))* '"' )"); @@ -770,13 +785,13 @@ TEST_CASE("Literal token on AST test1", "[general]") { 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()); + EXPECT_TRUE(ret); + EXPECT_TRUE(ast->is_token); + EXPECT_EQ(R"("a\tb")", ast->token); + EXPECT_TRUE(ast->nodes.empty()); } -TEST_CASE("Literal token on AST test2", "[general]") { +TEST(GeneralTest, Literal_token_on_AST_test2) { parser parser(R"( STRING_LITERAL <- '"' (ESC / CHAR)* '"' ESC <- ('\\"' / '\\t' / '\\n') @@ -787,13 +802,13 @@ TEST_CASE("Literal token on AST test2", "[general]") { 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); + EXPECT_TRUE(ret); + EXPECT_FALSE(ast->is_token); + EXPECT_TRUE(ast->token.empty()); + EXPECT_EQ(3, ast->nodes.size()); } -TEST_CASE("Literal token on AST test3", "[general]") { +TEST(GeneralTest, Literal_token_on_AST_test3) { parser parser(R"( STRING_LITERAL <- < '"' (ESC / CHAR)* '"' > ESC <- ('\\"' / '\\t' / '\\n') @@ -804,30 +819,30 @@ TEST_CASE("Literal token on AST test3", "[general]") { 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()); + EXPECT_TRUE(ret); + EXPECT_TRUE(ast->is_token); + EXPECT_EQ(R"("a\tb")", ast->token); + EXPECT_TRUE(ast->nodes.empty()); } -TEST_CASE("Missing missing definitions test", "[general]") { +TEST(GeneralTest, Missing_missing_definitions_test) { parser parser(R"( A <- B C )"); - REQUIRE(!parser); + EXPECT_FALSE(parser); } -TEST_CASE("Definition duplicates test", "[general]") { +TEST(GeneralTest, Definition_duplicates_test) { parser parser(R"( A <- '' A <- '' )"); - REQUIRE(!parser); + EXPECT_FALSE(parser); } -TEST_CASE("Semantic values test", "[general]") { +TEST(GeneralTest, Semantic_values_test) { parser parser(R"( term <- ( a b c x )? a b c a <- 'a' @@ -839,9 +854,9 @@ TEST_CASE("Semantic values test", "[general]") { 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"); + EXPECT_EQ("a at 0", std::any_cast(vs[0])); + EXPECT_EQ("b at 1", std::any_cast(vs[1])); + EXPECT_EQ("c at 2", std::any_cast(vs[2])); return std::string(); } else { return rule + " at " + std::to_string(vs.sv().data() - vs.ss); @@ -849,36 +864,36 @@ TEST_CASE("Semantic values test", "[general]") { }; } - REQUIRE(parser.parse("abc")); + EXPECT_TRUE(parser.parse("abc")); } -TEST_CASE("Ordered choice count", "[general]") { +TEST(GeneralTest, Ordered_choice_count) { parser parser(R"( S <- 'a' / 'b' )"); parser["S"] = [](const SemanticValues &vs) { - REQUIRE(vs.choice() == 1); - REQUIRE(vs.choice_count() == 2); + EXPECT_EQ(1, vs.choice()); + EXPECT_EQ(2, vs.choice_count()); }; parser.parse("b"); } -TEST_CASE("Ordered choice count 2", "[general]") { +TEST(GeneralTest, Ordered_choice_count_2) { parser parser(R"( S <- ('a' / 'b')* )"); parser["S"] = [](const SemanticValues &vs) { - REQUIRE(vs.choice() == 0); - REQUIRE(vs.choice_count() == 0); + EXPECT_EQ(0, vs.choice()); + EXPECT_EQ(0, vs.choice_count()); }; parser.parse("b"); } -TEST_CASE("Semantic value tag", "[general]") { +TEST(GeneralTest, Semantic_value_tag) { parser parser(R"( S <- A? B* C? A <- 'a' @@ -889,54 +904,54 @@ TEST_CASE("Semantic value tag", "[general]") { { using namespace udl; parser["S"] = [](const SemanticValues &vs) { - REQUIRE(vs.size() == 1); - REQUIRE(vs.tags.size() == 1); - REQUIRE(vs.tags[0] == "C"_); + EXPECT_EQ(1, vs.size()); + EXPECT_EQ(1, vs.tags.size()); + EXPECT_EQ("C"_, vs.tags[0]); }; auto ret = parser.parse("c"); - REQUIRE(ret == true); + EXPECT_TRUE(ret); } { 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"_); + EXPECT_EQ(2, vs.size()); + EXPECT_EQ(2, vs.tags.size()); + EXPECT_EQ("B"_, vs.tags[0]); + EXPECT_EQ("B"_, vs.tags[1]); }; auto ret = parser.parse("bb"); - REQUIRE(ret == true); + EXPECT_TRUE(ret); } { 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"_); + EXPECT_EQ(2, vs.size()); + EXPECT_EQ(2, vs.tags.size()); + EXPECT_EQ("A"_, vs.tags[0]); + EXPECT_EQ("C"_, vs.tags[1]); }; auto ret = parser.parse("ac"); - REQUIRE(ret == true); + EXPECT_TRUE(ret); } } -TEST_CASE("Negated Class test", "[general]") { +TEST(GeneralTest, Negated_Class_test) { parser parser(R"( ROOT <- [^a-z_]+ )"); bool ret = parser; - REQUIRE(ret == true); + EXPECT_TRUE(ret); - REQUIRE(parser.parse("ABC123")); - REQUIRE_FALSE(parser.parse("ABcZ")); - REQUIRE_FALSE(parser.parse("ABCZ_")); - REQUIRE_FALSE(parser.parse("")); + EXPECT_TRUE(parser.parse("ABC123")); + EXPECT_FALSE(parser.parse("ABcZ")); + EXPECT_FALSE(parser.parse("ABCZ_")); + EXPECT_FALSE(parser.parse("")); } -TEST_CASE("`token_to_number` test", "[general]") { +TEST(GeneralTest, token_to_number_float_test) { parser parser(R"( S <- '1.1' )"); @@ -945,10 +960,10 @@ TEST_CASE("`token_to_number` test", "[general]") { std::shared_ptr ast; auto ret = parser.parse("1.1", ast); - REQUIRE(ret == true); - REQUIRE(ast->is_token == true); - REQUIRE(ast->token == "1.1"); - REQUIRE(ast->token_to_number() == 1.1f); - REQUIRE(ast->nodes.empty()); + EXPECT_TRUE(ret); + EXPECT_TRUE(ast->is_token); + EXPECT_EQ("1.1", ast->token); + EXPECT_EQ(1.1f, ast->token_to_number()); + EXPECT_TRUE(ast->nodes.empty()); } diff --git a/test/test2.cc b/test/test2.cc index 3e203ea..ddac8d3 100644 --- a/test/test2.cc +++ b/test/test2.cc @@ -1,58 +1,53 @@ -#include +#include #include #include using namespace peg; -TEST_CASE("Token boundary 1", "[token boundary]") -{ - parser pg(R"( +TEST(TokenBoundaryTest, Token_boundary_1) { + parser pg(R"( ROOT <- TOP TOP <- 'a' 'b' 'c' %whitespace <- [ \t\r\n]* )"); - REQUIRE(pg.parse(" a b c ")); + EXPECT_TRUE(pg.parse(" a b c ")); } -TEST_CASE("Token boundary 2", "[token boundary]") -{ - parser pg(R"( +TEST(TokenBoundaryTest, Token_boundary_2) { + parser pg(R"( ROOT <- TOP TOP <- < 'a' 'b' 'c' > %whitespace <- [ \t\r\n]* )"); - REQUIRE(!pg.parse(" a b c ")); + EXPECT_FALSE(pg.parse(" a b c ")); } -TEST_CASE("Token boundary 3", "[token boundary]") -{ - parser pg(R"( +TEST(TokenBoundaryTest, Token_boundary_3) { + parser pg(R"( ROOT <- TOP TOP <- < 'a' B 'c' > B <- 'b' %whitespace <- [ \t\r\n]* )"); - REQUIRE(!pg.parse(" a b c ")); + EXPECT_FALSE(pg.parse(" a b c ")); } -TEST_CASE("Token boundary 4", "[token boundary]") -{ - parser pg(R"( +TEST(TokenBoundaryTest, Token_boundary_4) { + parser pg(R"( ROOT <- TOP TOP <- < A 'b' 'c' > A <- 'a' %whitespace <- [ \t\r\n]* )"); - REQUIRE(!pg.parse(" a b c ")); + EXPECT_FALSE(pg.parse(" a b c ")); } -TEST_CASE("Token boundary 5", "[token boundary]") -{ - parser pg(R"( +TEST(TokenBoundaryTest, Token_boundary_5) { + parser pg(R"( ROOT <- TOP TOP <- A < 'b' C > A <- 'a' @@ -60,12 +55,11 @@ TEST_CASE("Token boundary 5", "[token boundary]") %whitespace <- [ \t\r\n]* )"); - REQUIRE(!pg.parse(" a b c ")); + EXPECT_FALSE(pg.parse(" a b c ")); } -TEST_CASE("Token boundary 6", "[token boundary]") -{ - parser pg(R"( +TEST(TokenBoundaryTest, Token_boundary_6) { + parser pg(R"( ROOT <- TOP TOP <- < A > B C A <- 'a' @@ -74,12 +68,11 @@ TEST_CASE("Token boundary 6", "[token boundary]") %whitespace <- [ \t\r\n]* )"); - REQUIRE(pg.parse(" a b c ")); + EXPECT_TRUE(pg.parse(" a b c ")); } -TEST_CASE("Token boundary 7", "[token boundary]") -{ - parser pg(R"( +TEST(TokenBoundaryTest, Token_boundary_7) { + parser pg(R"( ROOT <- TOP TOP <- < A B C > A <- 'a' @@ -88,51 +81,50 @@ TEST_CASE("Token boundary 7", "[token boundary]") %whitespace <- [ \t\r\n]* )"); - REQUIRE(!pg.parse(" a b c ")); + EXPECT_FALSE(pg.parse(" a b c ")); } -TEST_CASE("Infinite loop 1", "[infinite loop]") -{ - parser pg(R"( +TEST(InfiniteLoopTest, Infinite_loop_1) { + parser pg(R"( ROOT <- WH TOKEN* WH TOKEN <- [a-z0-9]* WH <- [ \t]* )"); - REQUIRE(!pg); + EXPECT_FALSE(pg); } -TEST_CASE("Infinite loop 2", "[infinite loop]") { +TEST(InfiniteLoopTest, Infinite_loop_2) { parser pg(R"( ROOT <- WH TOKEN+ WH TOKEN <- [a-z0-9]* WH <- [ \t]* )"); - REQUIRE(!pg); + EXPECT_FALSE(pg); } -TEST_CASE("Infinite loop 3", "[infinite loop]") { +TEST(InfiniteLoopTest, Infinite_loop_3) { parser pg(R"( ROOT <- WH TOKEN* WH TOKEN <- !'word1' WH <- [ \t]* )"); - REQUIRE(!pg); + EXPECT_FALSE(pg); } -TEST_CASE("Infinite loop 4", "[infinite loop]") { +TEST(InfiniteLoopTest, Infinite_loop_4) { parser pg(R"( ROOT <- WH TOKEN* WH TOKEN <- &'word1' WH <- [ \t]* )"); - REQUIRE(!pg); + EXPECT_FALSE(pg); } -TEST_CASE("Infinite loop 5", "[infinite loop]") { +TEST(InfiniteLoopTest, Infinite_loop_5) { parser pg(R"( Numbers <- Number* Number <- [0-9]+ / Spacing @@ -140,43 +132,43 @@ TEST_CASE("Infinite loop 5", "[infinite loop]") { EOF <- !. )"); - REQUIRE(!pg); + EXPECT_FALSE(pg); } -TEST_CASE("Infinite loop 6", "[infinite loop]") { +TEST(InfiniteLoopTest, Infinite_loop_6) { parser pg(R"( S <- ''* )"); - REQUIRE(!pg); + EXPECT_FALSE(pg); } -TEST_CASE("Infinite loop 7", "[infinite loop]") { +TEST(InfiniteLoopTest, Infinite_loop_7) { parser pg(R"( S <- A* A <- '' )"); - REQUIRE(!pg); + EXPECT_FALSE(pg); } -TEST_CASE("Infinite loop 8", "[infinite loop]") { - parser pg(R"( +TEST(InfiniteLoopTest, Infinite_loop_8) { + parser pg(R"( ROOT <- ('A' /)* )"); - REQUIRE(!pg); + EXPECT_FALSE(pg); } -TEST_CASE("Infinite loop 9", "[infinite loop]") { - parser pg(R"( +TEST(InfiniteLoopTest, Infinite_loop_9) { + parser pg(R"( ROOT <- %recover(('A' /)*) )"); - REQUIRE(!pg); + EXPECT_FALSE(pg); } -TEST_CASE("Not infinite 1", "[infinite loop]") { +TEST(InfiniteLoopTest, Not_infinite_1) { parser pg(R"( Numbers <- Number* EOF Number <- [0-9]+ / Spacing @@ -184,10 +176,10 @@ TEST_CASE("Not infinite 1", "[infinite loop]") { EOF <- !. )"); - REQUIRE(!!pg); // OK + EXPECT_TRUE(!!pg); } -TEST_CASE("Not infinite 2", "[infinite loop]") { +TEST(InfiniteLoopTest, Not_infinite_2) { 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 @@ -195,10 +187,10 @@ TEST_CASE("Not infinite 2", "[infinite loop]") { _ <- [ \t]* )"); - REQUIRE(!!pg); // OK + EXPECT_TRUE(!!pg); } -TEST_CASE("Not infinite 3", "[infinite loop]") { +TEST(InfiniteLoopTest, Not_infinite_3) { parser pg(R"( EXPRESSION <- _ TERM (TERM_OPERATOR TERM)* TERM <- FACTOR (FACTOR_OPERATOR FACTOR)* @@ -209,10 +201,10 @@ TEST_CASE("Not infinite 3", "[infinite loop]") { _ <- [ \t\r\n]* )"); - REQUIRE(!!pg); // OK + EXPECT_TRUE(!!pg); } -TEST_CASE("Precedence climbing", "[precedence]") { +TEST(PrecedenceTest, Precedence_climbing) { parser parser(R"( START <- _ EXPRESSION EXPRESSION <- ATOM (OPERATOR ATOM)* { @@ -227,7 +219,7 @@ TEST_CASE("Precedence climbing", "[precedence]") { T(S) <- < S > _ )"); - REQUIRE(!!parser); // OK + EXPECT_TRUE(!!parser); parser.enable_packrat_parsing(); @@ -247,18 +239,20 @@ TEST_CASE("Precedence climbing", "[precedence]") { return result; }; parser["OPERATOR"] = [](const SemanticValues &vs) { return *vs.sv().data(); }; - parser["NUMBER"] = [](const SemanticValues &vs) { return vs.token_to_number(); }; + parser["NUMBER"] = [](const SemanticValues &vs) { + return vs.token_to_number(); + }; bool ret = parser; - REQUIRE(ret == true); + EXPECT_TRUE(ret); { auto expr = " 1 + 2 * 3 * (4 - 5 + 6) / 7 - 8 "; long val = 0; ret = parser.parse(expr, val); - REQUIRE(ret == true); - REQUIRE(val == -3); + EXPECT_TRUE(ret); + EXPECT_EQ(-3, val); } { @@ -266,12 +260,12 @@ TEST_CASE("Precedence climbing", "[precedence]") { long val = 0; ret = parser.parse(expr, val); - REQUIRE(ret == true); - REQUIRE(val == 0); + EXPECT_TRUE(ret); + EXPECT_EQ(0, val); } } -TEST_CASE("Precedence climbing with literal operator", "[precedence]") { +TEST(PrecedenceTest, Precedence_climbing_with_literal_operator) { parser parser(R"( START <- _ EXPRESSION EXPRESSION <- ATOM (OPERATOR ATOM)* { @@ -286,7 +280,7 @@ TEST_CASE("Precedence climbing with literal operator", "[precedence]") { T(S) <- < S > _ )"); - REQUIRE(!!parser); // OK + EXPECT_TRUE(!!parser); parser.enable_packrat_parsing(); @@ -308,19 +302,24 @@ TEST_CASE("Precedence climbing with literal operator", "[precedence]") { } return result; }; - parser["OPERATOR"] = [](const SemanticValues &vs) { return vs.token_to_string(); }; - parser["NUMBER"] = [](const SemanticValues &vs) { return vs.token_to_number(); }; + parser["OPERATOR"] = [](const SemanticValues &vs) { + return vs.token_to_string(); + }; + parser["NUMBER"] = [](const SemanticValues &vs) { + return vs.token_to_number(); + }; bool ret = parser; - REQUIRE(ret == true); + EXPECT_TRUE(ret); { - auto expr = " 1 #plus# 2 #multiply# 3 #multiply# (4 - 5 #plus# 6) / 7 - 8 "; + auto expr = + " 1 #plus# 2 #multiply# 3 #multiply# (4 - 5 #plus# 6) / 7 - 8 "; long val = 0; ret = parser.parse(expr, val); - REQUIRE(ret == true); - REQUIRE(val == -3); + EXPECT_TRUE(ret); + EXPECT_EQ(-3, val); } { @@ -328,12 +327,12 @@ TEST_CASE("Precedence climbing with literal operator", "[precedence]") { long val = 0; ret = parser.parse(expr, val); - REQUIRE(ret == true); - REQUIRE(val == 0); + EXPECT_TRUE(ret); + EXPECT_EQ(0, val); } } -TEST_CASE("Precedence climbing with macro", "[precedence]") { +TEST(PrecedenceTest, Precedence_climbing_with_macro) { // Create a PEG parser parser parser(R"( EXPRESSION <- INFIX_EXPRESSION(ATOM, OPERATOR) @@ -351,7 +350,7 @@ TEST_CASE("Precedence climbing with macro", "[precedence]") { parser.enable_packrat_parsing(); bool ret = parser; - REQUIRE(ret == true); + EXPECT_TRUE(ret); // Setup actions parser["INFIX_EXPRESSION"] = [](const SemanticValues &vs) -> long { @@ -369,15 +368,17 @@ TEST_CASE("Precedence climbing with macro", "[precedence]") { return result; }; parser["OPERATOR"] = [](const SemanticValues &vs) { return *vs.sv().data(); }; - parser["NUMBER"] = [](const SemanticValues &vs) { return vs.token_to_number(); }; + 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); - REQUIRE(ret == true); - REQUIRE(val == -3); + EXPECT_TRUE(ret); + EXPECT_EQ(-3, val); } { @@ -385,12 +386,12 @@ TEST_CASE("Precedence climbing with macro", "[precedence]") { long val = 0; ret = parser.parse(expr, val); - REQUIRE(ret == true); - REQUIRE(val == 0); + EXPECT_TRUE(ret); + EXPECT_EQ(0, val); } } -TEST_CASE("Precedence climbing error1", "[precedence]") { +TEST(PrecedenceTest, Precedence_climbing_error1) { parser parser(R"( START <- _ EXPRESSION EXPRESSION <- ATOM (OPERATOR ATOM1)* { @@ -407,10 +408,10 @@ TEST_CASE("Precedence climbing error1", "[precedence]") { )"); bool ret = parser; - REQUIRE(ret == false); + EXPECT_FALSE(ret); } -TEST_CASE("Precedence climbing error2", "[precedence]") { +TEST(PrecedenceTest, Precedence_climbing_error2) { parser parser(R"( START <- _ EXPRESSION EXPRESSION <- ATOM OPERATOR ATOM { @@ -426,10 +427,10 @@ TEST_CASE("Precedence climbing error2", "[precedence]") { )"); bool ret = parser; - REQUIRE(ret == false); + EXPECT_FALSE(ret); } -TEST_CASE("Precedence climbing error3", "[precedence]") { +TEST(PrecedenceTest, Precedence_climbing_error3) { parser parser(R"( EXPRESSION <- PRECEDENCE_PARSING(ATOM, OPERATOR) PRECEDENCE_PARSING(A, O) <- A (O A)+ { @@ -444,10 +445,10 @@ TEST_CASE("Precedence climbing error3", "[precedence]") { )"); bool ret = parser; - REQUIRE(ret == false); + EXPECT_FALSE(ret); } -TEST_CASE("Packrat parser test with %whitespace%", "[packrat]") { +TEST(PackratTest, Packrat_parser_test_with_whitespace) { peg::parser parser(R"( ROOT <- 'a' %whitespace <- SPACE* @@ -457,10 +458,10 @@ TEST_CASE("Packrat parser test with %whitespace%", "[packrat]") { parser.enable_packrat_parsing(); auto ret = parser.parse("a"); - REQUIRE(ret == true); + EXPECT_TRUE(ret); } -TEST_CASE("Packrat parser test with macro", "[packrat]") { +TEST(PackratText, Packrat_parser_test_with_macro) { parser parser(R"( EXPRESSION <- _ LIST(TERM, TERM_OPERATOR) TERM <- LIST(FACTOR, FACTOR_OPERATOR) @@ -476,11 +477,10 @@ TEST_CASE("Packrat parser test with macro", "[packrat]") { parser.enable_packrat_parsing(); auto ret = parser.parse(" 1 + 2 * 3 * (4 - 5 + 6) / 7 - 8 "); - REQUIRE(ret == true); + EXPECT_TRUE(ret); } -TEST_CASE("Packrat parser test with precedence expression parser", - "[packrat]") { +TEST(PackratText, Packrat_parser_test_with_precedence_expression_parser) { peg::parser parser(R"( Expression <- Atom (Operator Atom)* { precedence L + - L * / } Atom <- _? Number _? @@ -490,15 +490,15 @@ TEST_CASE("Packrat parser test with precedence expression parser", )"); bool ret = parser; - REQUIRE(ret == true); + EXPECT_TRUE(ret); parser.enable_packrat_parsing(); ret = parser.parse(" 1 + 2 * 3 "); - REQUIRE(ret == true); + EXPECT_TRUE(ret); } -TEST_CASE("Backreference test", "[backreference]") { +TEST(BackreferenceText, Backreference_test) { parser parser(R"( START <- _ LQUOTE < (!RQUOTE .)* > RQUOTE _ LQUOTE <- 'R"' $delm< [a-zA-Z]* > '(' @@ -515,8 +515,8 @@ TEST_CASE("Backreference test", "[backreference]") { R"("hello world")" )delm"); - REQUIRE(ret == true); - REQUIRE(token == "\"hello world\""); + EXPECT_TRUE(ret); + EXPECT_EQ("\"hello world\"", token); } { @@ -525,8 +525,8 @@ TEST_CASE("Backreference test", "[backreference]") { R"foo("(hello world)")foo" )delm"); - REQUIRE(ret == true); - REQUIRE(token == "\"(hello world)\""); + EXPECT_TRUE(ret); + EXPECT_EQ("\"(hello world)\"", token); } { @@ -535,8 +535,8 @@ TEST_CASE("Backreference test", "[backreference]") { R"foo("(hello world)foo")foo" )delm"); - REQUIRE(ret == false); - REQUIRE(token == "\"(hello world"); + EXPECT_FALSE(ret); + EXPECT_EQ("\"(hello world", token); } { @@ -545,12 +545,12 @@ TEST_CASE("Backreference test", "[backreference]") { R"foo("(hello world)")bar" )delm"); - REQUIRE(ret == false); - REQUIRE(token.empty()); + EXPECT_FALSE(ret); + EXPECT_TRUE(token.empty()); } } -TEST_CASE("Invalid backreference test", "[backreference]") { +TEST(BackreferenceText, Invalid_backreference_test) { parser parser(R"( START <- _ LQUOTE (!RQUOTE .)* RQUOTE _ LQUOTE <- 'R"' $delm< [a-zA-Z]* > '(' @@ -558,13 +558,13 @@ TEST_CASE("Invalid backreference test", "[backreference]") { ~_ <- [ \t\r\n]* )"); - REQUIRE_THROWS_AS(parser.parse(R"delm( + EXPECT_THROW(parser.parse(R"delm( R"foo("(hello world)")foo" )delm"), - std::runtime_error); + std::runtime_error); } -TEST_CASE("Nested capture test", "[backreference]") { +TEST(BackreferenceText, Nested_capture_test) { parser parser(R"( ROOT <- CONTENT CONTENT <- (ELEMENT / TEXT)* @@ -576,13 +576,13 @@ 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.")); + EXPECT_TRUE(parser.parse("This is a test text.")); + EXPECT_FALSE(parser.parse("This is a test text.")); + EXPECT_FALSE(parser.parse("This is a test text.")); + EXPECT_FALSE(parser.parse("This is a test text.")); } -TEST_CASE("Backreference with Prioritized Choice test", "[backreference]") { +TEST(BackreferenceText, Backreference_with_Prioritized_Choice_test) { parser parser(R"( TREE <- WRONG_BRANCH / CORRECT_BRANCH WRONG_BRANCH <- BRANCH THAT IS_capture WRONG @@ -595,10 +595,10 @@ TEST_CASE("Backreference with Prioritized Choice test", "[backreference]") { CORRECT <- 'correct' )"); - REQUIRE_THROWS_AS(parser.parse("branchthatiscorrect"), std::runtime_error); + EXPECT_THROW(parser.parse("branchthatiscorrect"), std::runtime_error); } -TEST_CASE("Backreference with Zero or More test", "[backreference]") { +TEST(BackreferenceText, Backreference_with_Zero_or_More_test) { parser parser(R"( TREE <- WRONG_BRANCH* CORRECT_BRANCH WRONG_BRANCH <- BRANCH THAT IS_capture WRONG @@ -611,18 +611,18 @@ TEST_CASE("Backreference with Zero or More test", "[backreference]") { CORRECT <- 'correct' )"); - REQUIRE(parser.parse("branchthatiswrongbranchthatiscorrect")); - REQUIRE(!parser.parse("branchthatiswrongbranchthatIscorrect")); - REQUIRE( - !parser.parse("branchthatiswrongbranchthatIswrongbranchthatiscorrect")); - REQUIRE( + EXPECT_TRUE(parser.parse("branchthatiswrongbranchthatiscorrect")); + EXPECT_FALSE(parser.parse("branchthatiswrongbranchthatIscorrect")); + EXPECT_FALSE( + parser.parse("branchthatiswrongbranchthatIswrongbranchthatiscorrect")); + EXPECT_TRUE( parser.parse("branchthatiswrongbranchthatIswrongbranchthatIscorrect")); - REQUIRE_THROWS_AS(parser.parse("branchthatiscorrect"), std::runtime_error); - REQUIRE_THROWS_AS(parser.parse("branchthatiswron_branchthatiscorrect"), - std::runtime_error); + EXPECT_THROW(parser.parse("branchthatiscorrect"), std::runtime_error); + EXPECT_THROW(parser.parse("branchthatiswron_branchthatiscorrect"), + std::runtime_error); } -TEST_CASE("Backreference with One or More test", "[backreference]") { +TEST(BackreferenceText, Backreference_with_One_or_More_test) { parser parser(R"( TREE <- WRONG_BRANCH+ CORRECT_BRANCH WRONG_BRANCH <- BRANCH THAT IS_capture WRONG @@ -635,17 +635,17 @@ TEST_CASE("Backreference with One or More test", "[backreference]") { CORRECT <- 'correct' )"); - REQUIRE(parser.parse("branchthatiswrongbranchthatiscorrect")); - REQUIRE(!parser.parse("branchthatiswrongbranchthatIscorrect")); - REQUIRE( - !parser.parse("branchthatiswrongbranchthatIswrongbranchthatiscorrect")); - REQUIRE( + EXPECT_TRUE(parser.parse("branchthatiswrongbranchthatiscorrect")); + EXPECT_FALSE(parser.parse("branchthatiswrongbranchthatIscorrect")); + EXPECT_FALSE( + parser.parse("branchthatiswrongbranchthatIswrongbranchthatiscorrect")); + EXPECT_TRUE( parser.parse("branchthatiswrongbranchthatIswrongbranchthatIscorrect")); - REQUIRE(!parser.parse("branchthatiscorrect")); - REQUIRE(!parser.parse("branchthatiswron_branchthatiscorrect")); + EXPECT_FALSE(parser.parse("branchthatiscorrect")); + EXPECT_FALSE(parser.parse("branchthatiswron_branchthatiscorrect")); } -TEST_CASE("Backreference with Option test", "[backreference]") { +TEST(BackreferenceText, Backreference_with_Option_test) { parser parser(R"( TREE <- WRONG_BRANCH? CORRECT_BRANCH WRONG_BRANCH <- BRANCH THAT IS_capture WRONG @@ -658,115 +658,115 @@ 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); + EXPECT_TRUE(parser.parse("branchthatiswrongbranchthatiscorrect")); + EXPECT_FALSE(parser.parse("branchthatiswrongbranchthatIscorrect")); + EXPECT_FALSE( + parser.parse("branchthatiswrongbranchthatIswrongbranchthatiscorrect")); + EXPECT_FALSE( + parser.parse("branchthatiswrongbranchthatIswrongbranchthatIscorrect")); + EXPECT_THROW(parser.parse("branchthatiscorrect"), std::runtime_error); + EXPECT_THROW(parser.parse("branchthatiswron_branchthatiscorrect"), + std::runtime_error); } -TEST_CASE("Repetition {0}", "[repetition]") { +TEST(RepetitionText, Repetition_0) { 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")); + EXPECT_TRUE(parser.parse("(123) 456-7890")); + EXPECT_FALSE(parser.parse("(12a) 456-7890")); + EXPECT_FALSE(parser.parse("(123) 45-7890")); + EXPECT_FALSE(parser.parse("(123) 45-7a90")); } -TEST_CASE("Repetition {2,4}", "[repetition]") { +TEST(RepetitionText, Repetition_2_4) { 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")); + EXPECT_FALSE(parser.parse("1")); + EXPECT_TRUE(parser.parse("12")); + EXPECT_TRUE(parser.parse("123")); + EXPECT_TRUE(parser.parse("1234")); + EXPECT_FALSE(parser.parse("12345")); } -TEST_CASE("Repetition {2,1}", "[repetition]") { +TEST(RepetitionText, Repetition_2_1) { parser parser(R"( START <- DIGIT{2,1} # invalid range DIGIT <- [0-9] )"); - REQUIRE(!parser.parse("1")); - REQUIRE(parser.parse("12")); - REQUIRE(!parser.parse("123")); + EXPECT_FALSE(parser.parse("1")); + EXPECT_TRUE(parser.parse("12")); + EXPECT_FALSE(parser.parse("123")); } -TEST_CASE("Repetition {2,}", "[repetition]") { +TEST(RepetitionText, Repetition_2) { 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")); + EXPECT_FALSE(parser.parse("1")); + EXPECT_TRUE(parser.parse("12")); + EXPECT_TRUE(parser.parse("123")); + EXPECT_TRUE(parser.parse("1234")); } -TEST_CASE("Repetition {,2}", "[repetition]") { +TEST(RepetitionText, Repetition__2) { 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")); + EXPECT_TRUE(parser.parse("1")); + EXPECT_TRUE(parser.parse("12")); + EXPECT_FALSE(parser.parse("123")); + EXPECT_FALSE(parser.parse("1234")); } -TEST_CASE("Left recursive test", "[left recursive]") { +TEST(LeftRecursiveTest, Left_recursive_test) { parser parser(R"( A <- A 'a' B <- A 'a' )"); - REQUIRE(!parser); + EXPECT_FALSE(parser); } -TEST_CASE("Left recursive with option test", "[left recursive]") { +TEST(LeftRecursiveTest, Left_recursive_with_option_test) { parser parser(R"( A <- 'a' / 'b'? B 'c' B <- A )"); - REQUIRE(!parser); + EXPECT_FALSE(parser); } -TEST_CASE("Left recursive with zom test", "[left recursive]") { +TEST(LeftRecursiveTest, Left_recursive_with_zom_test) { parser parser(R"( A <- 'a'* A* )"); - REQUIRE(!parser); + EXPECT_FALSE(parser); } -TEST_CASE("Left recursive with a ZOM content rule", "[left recursive]") { +TEST(LeftRecursiveTest, Left_recursive_with_a_ZOM_content_rule) { parser parser(R"( A <- B B <- _ A _ <- ' '* # Zero or more )"); - REQUIRE(!parser); + EXPECT_FALSE(parser); } -TEST_CASE("Left recursive with empty string test", "[left recursive]") { +TEST(LeftRecursiveTest, Left_recursive_with_empty_string_test) { parser parser(" A <- '' A"); - REQUIRE(!parser); + EXPECT_FALSE(parser); } -TEST_CASE("User defined rule test", "[user rule]") { +TEST(UserRuleTest, User_defined_rule_test) { auto g = parser(R"( ROOT <- _ 'Hello' _ NAME '!' _ )", @@ -783,10 +783,10 @@ TEST_CASE("User defined rule test", "[user rule]") { })}, {"~_", zom(cls(" \t\r\n"))}}); - REQUIRE(g.parse(" Hello BNF! ") == true); + EXPECT_TRUE(g.parse(" Hello BNF! ")); } -TEST_CASE("Semantic predicate test", "[predicate]") { +TEST(PredicateText, Semantic_predicate_test) { parser parser("NUMBER <- [0-9]+"); parser["NUMBER"] = [](const SemanticValues &vs) { @@ -796,18 +796,18 @@ TEST_CASE("Semantic predicate test", "[predicate]") { }; long val; - REQUIRE(parser.parse("100", val)); - REQUIRE(val == 100); + EXPECT_TRUE(parser.parse("100", val)); + EXPECT_EQ(100, val); parser.log = [](size_t line, size_t col, const std::string &msg) { - REQUIRE(line == 1); - REQUIRE(col == 1); - REQUIRE(msg == "value error!!"); + EXPECT_EQ(1, line); + EXPECT_EQ(1, col); + EXPECT_EQ("value error!!", msg); }; - REQUIRE(!parser.parse("200", val)); + EXPECT_FALSE(parser.parse("200", val)); } -TEST_CASE("Japanese character", "[unicode]") { +TEST(UnicodeText, Japanese_character) { peg::parser parser(u8R"( 文 <- 修飾語? 主語 述語 '。' 主語 <- 名詞 助詞 @@ -820,56 +820,56 @@ TEST_CASE("Japanese character", "[unicode]") { )"); bool ret = parser; - REQUIRE(ret == true); + EXPECT_TRUE(ret); - REQUIRE(parser.parse(u8R"(サーバーを復旧します。)")); + EXPECT_TRUE(parser.parse(u8R"(サーバーを復旧します。)")); } -TEST_CASE("dot with a code", "[unicode]") { +TEST(UnicodeText, dot_with_a_code) { peg::parser parser(" S <- 'a' . 'b' "); - REQUIRE(parser.parse(u8R"(aあb)")); + EXPECT_TRUE(parser.parse(u8R"(aあb)")); } -TEST_CASE("dot with a char", "[unicode]") { +TEST(UnicodeText, dot_with_a_char) { peg::parser parser(" S <- 'a' . 'b' "); - REQUIRE(parser.parse(u8R"(aåb)")); + EXPECT_TRUE(parser.parse(u8R"(aåb)")); } -TEST_CASE("character class", "[unicode]") { +TEST(UnicodeText, character_class) { peg::parser parser(R"( S <- 'a' [い-おAさC-Eた-とは] 'b' )"); bool ret = parser; - REQUIRE(ret == true); + EXPECT_TRUE(ret); - 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)")); + EXPECT_FALSE(parser.parse(u8R"(aあb)")); + EXPECT_TRUE(parser.parse(u8R"(aいb)")); + EXPECT_TRUE(parser.parse(u8R"(aうb)")); + EXPECT_TRUE(parser.parse(u8R"(aおb)")); + EXPECT_FALSE(parser.parse(u8R"(aかb)")); + EXPECT_TRUE(parser.parse(u8R"(aAb)")); + EXPECT_FALSE(parser.parse(u8R"(aBb)")); + EXPECT_TRUE(parser.parse(u8R"(aEb)")); + EXPECT_FALSE(parser.parse(u8R"(aFb)")); + EXPECT_FALSE(parser.parse(u8R"(aそb)")); + EXPECT_TRUE(parser.parse(u8R"(aたb)")); + EXPECT_TRUE(parser.parse(u8R"(aちb)")); + EXPECT_TRUE(parser.parse(u8R"(aとb)")); + EXPECT_FALSE(parser.parse(u8R"(aなb)")); + EXPECT_TRUE(parser.parse(u8R"(aはb)")); + EXPECT_FALSE(parser.parse(u8R"(a?b)")); } #if 0 // TODO: Unicode Grapheme support -TEST_CASE("dot with a grapheme", "[unicode]") +TEST(UnicodeText, dot_with_a_grapheme) { peg::parser parser(" S <- 'a' . 'b' "); - REQUIRE(parser.parse(u8R"(aसिb)")); + EXPECT_TRUE(parser.parse(u8R"(aसिb)")); } #endif -TEST_CASE("Macro simple test", "[macro]") { +TEST(MacroText, Macro_simple_test) { parser parser(R"( S <- HELLO WORLD HELLO <- T('hello') @@ -877,60 +877,60 @@ TEST_CASE("Macro simple test", "[macro]") { T(a) <- a [ \t]* )"); - REQUIRE(parser.parse("hello \tworld ")); + EXPECT_TRUE(parser.parse("hello \tworld ")); } -TEST_CASE("Macro two parameters", "[macro]") { +TEST(MacroText, Macro_two_parameters) { parser parser(R"( S <- HELLO_WORLD HELLO_WORLD <- T('hello', 'world') T(a, b) <- a [ \t]* b [ \t]* )"); - REQUIRE(parser.parse("hello \tworld ")); + EXPECT_TRUE(parser.parse("hello \tworld ")); } -TEST_CASE("Macro syntax error", "[macro]") { +TEST(MacroText, Macro_syntax_error) { parser parser(R"( S <- T('hello') T (a) <- a [ \t]* )"); bool ret = parser; - REQUIRE(ret == false); + EXPECT_FALSE(ret); } -TEST_CASE("Macro missing argument", "[macro]") { +TEST(MacroText, Macro_missing_argument) { parser parser(R"( S <- T ('hello') T(a, b) <- a [ \t]* b )"); bool ret = parser; - REQUIRE(ret == false); + EXPECT_FALSE(ret); } -TEST_CASE("Macro reference syntax error", "[macro]") { +TEST(MacroText, Macro_reference_syntax_error) { parser parser(R"( S <- T ('hello') T(a) <- a [ \t]* )"); bool ret = parser; - REQUIRE(ret == false); + EXPECT_FALSE(ret); } -TEST_CASE("Macro invalid macro reference error", "[macro]") { +TEST(MacroText, Macro_invalid_macro_reference_error) { parser parser(R"( S <- T('hello') T <- 'world' )"); bool ret = parser; - REQUIRE(ret == false); + EXPECT_FALSE(ret); } -TEST_CASE("Macro calculator", "[macro]") { +TEST(MacroText, Macro_calculator) { // Create a PEG parser parser parser(R"( # Grammar for simple calculator... @@ -969,41 +969,43 @@ TEST_CASE("Macro calculator", "[macro]") { parser["FACTOR_OPERATOR"] = [](const SemanticValues &vs) { return static_cast(*vs.sv().data()); }; - parser["NUMBER"] = [](const SemanticValues &vs) { return vs.token_to_number(); }; + parser["NUMBER"] = [](const SemanticValues &vs) { + return vs.token_to_number(); + }; bool ret = parser; - REQUIRE(ret == true); + EXPECT_TRUE(ret); auto expr = " 1 + 2 * 3 * (4 - 5 + 6) / 7 - 8 "; long val = 0; ret = parser.parse(expr, val); - REQUIRE(ret == true); - REQUIRE(val == -3); + EXPECT_TRUE(ret); + EXPECT_EQ(-3, val); } -TEST_CASE("Macro expression arguments", "[macro]") { +TEST(MacroText, Macro_expression_arguments) { parser parser(R"( S <- M('hello' / 'Hello', 'world' / 'World') M(arg0, arg1) <- arg0 [ \t]+ arg1 )"); - REQUIRE(parser.parse("Hello world")); + EXPECT_TRUE(parser.parse("Hello world")); } -TEST_CASE("Macro recursive", "[macro]") { +TEST(MacroText, Macro_recursive) { 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")); + EXPECT_TRUE(parser.parse("")); + EXPECT_TRUE(parser.parse("abc")); + EXPECT_TRUE(parser.parse("abc abc")); + EXPECT_TRUE(parser.parse("abc 123 abc")); } -TEST_CASE("Macro recursive2", "[macro]") { +TEST(MacroText, Macro_recursive2) { 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", @@ -1016,11 +1018,11 @@ TEST_CASE("Macro recursive2", "[macro]") { for (const auto &syntax : syntaxes) { parser parser(syntax); - REQUIRE(parser.parse("abc abc-123")); + EXPECT_TRUE(parser.parse("abc abc-123")); } } -TEST_CASE("Macro exclusive modifiers", "[macro]") { +TEST(MacroText, Macro_exclusive_modifiers) { parser parser(R"( S <- Modifiers(!"") _ Modifiers(Appeared) <- (!Appeared) ( @@ -1032,15 +1034,15 @@ 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")); + EXPECT_TRUE(parser.parse("public")); + EXPECT_TRUE(parser.parse("static")); + EXPECT_TRUE(parser.parse("final")); + EXPECT_TRUE(parser.parse("public static final")); + EXPECT_FALSE(parser.parse("public public")); + EXPECT_FALSE(parser.parse("public static public")); } -TEST_CASE("Macro token check test", "[macro]") { +TEST(MacroText, Macro_token_check_test) { parser parser(R"( # Grammar for simple calculator... EXPRESSION <- _ LIST(TERM, TERM_OPERATOR) @@ -1054,27 +1056,27 @@ 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); + EXPECT_FALSE(parser["EXPRESSION"].is_token()); + EXPECT_FALSE(parser["TERM"].is_token()); + EXPECT_FALSE(parser["FACTOR"].is_token()); + EXPECT_TRUE(parser["FACTOR_OPERATOR"].is_token()); + EXPECT_TRUE(parser["NUMBER"].is_token()); + EXPECT_TRUE(parser["_"].is_token()); + EXPECT_FALSE(parser["LIST"].is_token()); + EXPECT_TRUE(parser["T"].is_token()); } -TEST_CASE("Macro passes an arg to another macro", "[macro]") { +TEST(MacroText, Macro_passes_an_arg_to_another_macro) { parser parser(R"( A <- B(C) B(D) <- D C <- 'c' )"); - REQUIRE(parser.parse("c")); + EXPECT_TRUE(parser.parse("c")); } -TEST_CASE("Unreferenced rule", "[macro]") { +TEST(MacroText, Unreferenced_rule) { parser parser(R"( A <- B(C) B(D) <- D @@ -1083,10 +1085,10 @@ TEST_CASE("Unreferenced rule", "[macro]") { )"); bool ret = parser; - REQUIRE(ret == true); // This is OK, because it's a warning, not an erro... + EXPECT_TRUE(ret); // This is OK, because it's a warning, not an erro... } -TEST_CASE("Nested macro call", "[macro]") { +TEST(MacroText, Nested_macro_call) { parser parser(R"( A <- B(T) B(X) <- C(X) @@ -1094,20 +1096,20 @@ TEST_CASE("Nested macro call", "[macro]") { T <- 'val' )"); - REQUIRE(parser.parse("val")); + EXPECT_TRUE(parser.parse("val")); } -TEST_CASE("Nested macro call2", "[macro]") { +TEST(MacroText, Nested_macro_call2) { parser parser(R"( START <- A('TestVal1', 'TestVal2')+ A(Aarg1, Aarg2) <- B(Aarg1) '#End' B(Barg1) <- '#' Barg1 )"); - REQUIRE(parser.parse("#TestVal1#End")); + EXPECT_TRUE(parser.parse("#TestVal1#End")); } -TEST_CASE("Line information test", "[line information]") { +TEST(LineInformationTest, Line_information_test) { parser parser(R"( S <- _ (WORD _)+ WORD <- [A-Za-z]+ @@ -1120,43 +1122,64 @@ TEST_CASE("Line information test", "[line information]") { }; bool ret = parser; - REQUIRE(ret == true); + EXPECT_TRUE(ret); ret = parser.parse(" Mon Tue Wed \nThu Fri Sat\nSun\n"); - REQUIRE(ret == true); + EXPECT_TRUE(ret); - 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)); + { + auto val = std::make_pair(1, 2); + EXPECT_TRUE(val == locations[0]); + } + { + auto val = std::make_pair(1, 6); + EXPECT_TRUE(val == locations[1]); + } + { + auto val = std::make_pair(1, 10); + EXPECT_TRUE(val == locations[2]); + } + { + auto val = std::make_pair(2, 1); + EXPECT_TRUE(val == locations[3]); + } + { + auto val = std::make_pair(2, 6); + EXPECT_TRUE(val == locations[4]); + } + { + auto val = std::make_pair(2, 11); + EXPECT_TRUE(val == locations[5]); + } + { + auto val = std::make_pair(3, 1); + EXPECT_TRUE(val == locations[6]); + } } -TEST_CASE("Dictionary", "[dic]") { +TEST(DicText, Dictionary) { 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 .")); + EXPECT_TRUE(parser.parse("This month is Jan.")); + EXPECT_TRUE(parser.parse("This month is January.")); + EXPECT_FALSE(parser.parse("This month is Jannuary.")); + EXPECT_FALSE(parser.parse("This month is .")); } -TEST_CASE("Dictionary invalid", "[dic]") { +TEST(DicText, Dictionary_invalid) { parser parser(R"( START <- 'This month is ' MONTH '.' MONTH <- 'Jan' | 'January' | [a-z]+ | 'Feb' | 'February' )"); bool ret = parser; - REQUIRE_FALSE(ret); + EXPECT_FALSE(ret); } -TEST_CASE("Error recovery 1", "[error]") { +TEST(ErrorText, Error_recovery_1) { parser pg(R"( START <- __? SECTION* @@ -1188,26 +1211,26 @@ header <- (!__ .)* { message "invalid section header, missing ']'." } entry <- (!(__ / HEADER) .)+ { message "invalid entry." } )"); - REQUIRE(!!pg); // OK + EXPECT_TRUE(!!pg); std::vector errors{ - R"(3:1: invalid entry.)", - R"(7:1: invalid entry.)", - R"(10:11: invalid section header, missing ']'.)", - R"(18:1: invalid entry.)", + R"(3:1: invalid entry.)", + R"(7:1: invalid entry.)", + R"(10:11: invalid section header, missing ']'.)", + R"(18:1: invalid entry.)", }; size_t i = 0; pg.log = [&](size_t ln, size_t col, const std::string &msg) { std::stringstream ss; ss << ln << ":" << col << ": " << msg; - REQUIRE(ss.str() == errors[i++]); + EXPECT_EQ(errors[i++], ss.str()); }; pg.enable_ast(); std::shared_ptr ast; - REQUIRE_FALSE(pg.parse(R"([Section 1] + EXPECT_FALSE(pg.parse(R"([Section 1] 111 = 222 | 333 aaa || bbb ccc = ddd @@ -1229,12 +1252,12 @@ lll = mmm | nnn = ooo [Section 5] rrr | sss - )", ast)); + )", + ast)); ast = pg.optimize_ast(ast); - REQUIRE(ast_to_s(ast) == -R"(+ START + EXPECT_EQ(R"(+ START + SECTION - HEADER/0[CATEGORY] (Section 1) + ENTRIES @@ -1278,10 +1301,10 @@ R"(+ START + ENTRY/1 - PHRASE/0[WORD] (rrr) - PHRASE/0[WORD] (sss) -)"); +)", ast_to_s(ast)); } -TEST_CASE("Error recovery 2", "[error]") { +TEST(ErrorText, Error_recovery_2) { parser pg(R"( START <- ENTRY ((',' ENTRY) / %recover((!(',' / Space) .)+))* (_ / %recover(.*)) ENTRY <- '[' ITEM (',' ITEM)* ']' @@ -1293,36 +1316,37 @@ TEST_CASE("Error recovery 2", "[error]") { Space <- [ \n] )"); - REQUIRE(!!pg); // OK + EXPECT_TRUE(!!pg); std::vector errors{ - R"(1:6: syntax error, unexpected ']'.)", - R"(1:18: syntax error, unexpected 'z', expecting .)", - R"(1:24: syntax error, unexpected ',', expecting .)", - R"(1:31: syntax error, unexpected 'ccc', expecting .)", - R"(1:38: syntax error, unexpected 'ddd', expecting .)", - R"(1:55: syntax error, unexpected ']', expecting .)", - R"(1:58: syntax error, unexpected '\n', expecting .)", - R"(2:3: syntax error.)", + R"(1:6: syntax error, unexpected ']'.)", + R"(1:18: syntax error, unexpected 'z', expecting .)", + R"(1:24: syntax error, unexpected ',', expecting .)", + R"(1:31: syntax error, unexpected 'ccc', expecting .)", + R"(1:38: syntax error, unexpected 'ddd', expecting .)", + R"(1:55: syntax error, unexpected ']', expecting .)", + R"(1:58: syntax error, unexpected '\n', expecting .)", + R"(2:3: syntax error.)", }; size_t i = 0; pg.log = [&](size_t ln, size_t col, const std::string &msg) { std::stringstream ss; ss << ln << ":" << col << ": " << msg; - REQUIRE(ss.str() == errors[i++]); + EXPECT_EQ(errors[i++], ss.str()); }; pg.enable_ast(); std::shared_ptr ast; - REQUIRE_FALSE(pg.parse(R"([000]],[111],[222z,"aaa,"bbb",ccc"],[ddd",444,555,"eee],[ - )", ast)); + EXPECT_FALSE( + pg.parse(R"([000]],[111],[222z,"aaa,"bbb",ccc"],[ddd",444,555,"eee],[ + )", + ast)); ast = pg.optimize_ast(ast); - REQUIRE(ast_to_s(ast) == -R"(+ START + EXPECT_EQ(R"(+ START - ENTRY/0[NUM] (000) - ENTRY/0[NUM] (111) + ENTRY @@ -1335,10 +1359,11 @@ R"(+ START - ITEM/1[NUM] (444) - ITEM/1[NUM] (555) + ITEM/2 -)"); +)", + ast_to_s(ast)); } -TEST_CASE("Error recovery 3", "[error]") { +TEST(ErrorText, Error_recovery_3) { parser pg(R"~( # Grammar START <- __? SECTION* @@ -1386,36 +1411,36 @@ skip <- (!(__) .)* skip_puncs <- [|=]* _ )~"); - REQUIRE(!!pg); // OK + EXPECT_TRUE(!!pg); std::vector errors{ - R"(3:7: Wildcard characters (*) should not be used)", - R"(4:6: Wildcard characters (?) should not be used)", - R"(5:6: Duplicate OR operator (|))", - R"(9:4: Missing OR operator (|))", - R"(11:16: Expect phrase)", - R"(13:11: Missing opening/closing square bracket)", - R"(16:10: Section name 日 must be in English)", - R"(16:11: Section name 本 must be in English)", - R"(16:12: Section name 語 must be in English)", - R"(16:13: Section name で must be in English)", - R"(16:14: Section name す must be in English)", - R"(21:17: Use of invalid operator)", - R"(24:10: Use of invalid operator combination)", - R"(26:10: Missing OR operator (|))", + R"(3:7: Wildcard characters (*) should not be used)", + R"(4:6: Wildcard characters (?) should not be used)", + R"(5:6: Duplicate OR operator (|))", + R"(9:4: Missing OR operator (|))", + R"(11:16: Expect phrase)", + R"(13:11: Missing opening/closing square bracket)", + R"(16:10: Section name 日 must be in English)", + R"(16:11: Section name 本 must be in English)", + R"(16:12: Section name 語 must be in English)", + R"(16:13: Section name で must be in English)", + R"(16:14: Section name す must be in English)", + R"(21:17: Use of invalid operator)", + R"(24:10: Use of invalid operator combination)", + R"(26:10: Missing OR operator (|))", }; size_t i = 0; pg.log = [&](size_t ln, size_t col, const std::string &msg) { std::stringstream ss; ss << ln << ":" << col << ": " << msg; - REQUIRE(ss.str() == errors[i++]); + EXPECT_EQ(errors[i++], ss.str()); }; pg.enable_ast(); std::shared_ptr ast; - REQUIRE_FALSE(pg.parse(R"([Section 1] + EXPECT_FALSE(pg.parse(R"([Section 1] 111 = 222 | 333 AAA BB* | CCC AAA B?B | CCC @@ -1442,12 +1467,12 @@ ppp qqq |= rrr Section 6] sss | ttt - )", ast)); + )", + ast)); ast = pg.optimize_ast(ast); - REQUIRE(ast_to_s(ast) == -R"(+ START + EXPECT_EQ(R"(+ START + SECTION - HEADER/0[CATEGORY] (Section 1) + ENTRIES @@ -1546,10 +1571,10 @@ R"(+ START - WORD (sss) + PHRASE - WORD (ttt) -)"); +)", ast_to_s(ast)); } -TEST_CASE("Error recovery Java", "[error]") { +TEST(ErrorText, Error_recovery_Java) { parser pg(R"( Prog ← PUBLIC CLASS NAME LCUR PUBLIC STATIC VOID MAIN LPAR STRING LBRA RBRA NAME RPAR BlockStmt RCUR BlockStmt ← LCUR (Stmt)* RCUR^rcblk @@ -1611,24 +1636,24 @@ semia ← '' { message "missing simicolon in assignment." } SkipToRCUR ← (!RCUR (LCUR SkipToRCUR / .))* RCUR )"); - REQUIRE(!!pg); // OK + EXPECT_TRUE(!!pg); std::vector errors{ - R"(8:5: missing simicolon in assignment.)", - R"(8:6: missing end of block.)", + R"(8:5: missing simicolon in assignment.)", + R"(8:6: missing end of block.)", }; size_t i = 0; pg.log = [&](size_t ln, size_t col, const std::string &msg) { std::stringstream ss; ss << ln << ":" << col << ": " << msg; - REQUIRE(ss.str() == errors[i++]); + EXPECT_EQ(errors[i++], ss.str()); }; pg.enable_ast(); std::shared_ptr ast; - REQUIRE_FALSE(pg.parse(R"(public class Example { + EXPECT_FALSE(pg.parse(R"(public class Example { public static void main(String[] args) { int n = 5; int f = 1; @@ -1639,12 +1664,12 @@ SkipToRCUR ← (!RCUR (LCUR SkipToRCUR / .))* RCUR System.out.println(f); } } - )", ast)); + )", + ast)); ast = pg.optimize_ast(ast); - REQUIRE(ast_to_s(ast) == -R"(+ Prog + EXPECT_EQ(R"(+ Prog - PUBLIC (public) - CLASS (class) - NAME (Example) @@ -1680,5 +1705,6 @@ R"(+ Prog - MulExp/0[NAME] (n) - MINUS (-) - MulExp/0[NUMBER] (1) -)"); +)", + ast_to_s(ast)); } diff --git a/test/test3.cc b/test/test3.cc index 4a6445b..1d42559 100644 --- a/test/test3.cc +++ b/test/test3.cc @@ -1,323 +1,304 @@ -#include +#include #include using namespace peg; -inline bool exact(Grammar& g, const char* d, const char* s) { - auto n = strlen(s); - auto r = g[d].parse(s, n); - return r.ret && r.len == n; +inline bool exact(Grammar &g, const char *d, const char *s) { + auto n = strlen(s); + auto r = g[d].parse(s, n); + return r.ret && r.len == n; } -inline Grammar& make_peg_grammar() { - return ParserGenerator::grammar(); +inline Grammar &make_peg_grammar() { return ParserGenerator::grammar(); } + +TEST(PEGTest, PEG_Grammar) { + auto g = ParserGenerator::grammar(); + EXPECT_TRUE( + exact(g, "Grammar", + " Definition <- a / ( b c ) / d \n rule2 <- [a-zA-Z][a-z0-9-]+ ")); } -TEST_CASE("PEG Grammar", "[peg]") -{ - auto g = ParserGenerator::grammar(); - REQUIRE(exact(g, "Grammar", " Definition <- a / ( b c ) / d \n rule2 <- [a-zA-Z][a-z0-9-]+ ") == true); +TEST(LeftRecursiveTest, PEG_Definition) { + auto g = ParserGenerator::grammar(); + EXPECT_TRUE(exact(g, "Definition", "Definition <- a / (b c) / d ")); + EXPECT_TRUE(exact(g, "Definition", "Definition <- a / b c / d ")); + EXPECT_TRUE(exact(g, "Definition", u8"Definitiond ← a ")); + EXPECT_FALSE(exact(g, "Definition", "Definition ")); + EXPECT_FALSE(exact(g, "Definition", " ")); + EXPECT_FALSE(exact(g, "Definition", "")); + EXPECT_FALSE(exact(g, "Definition", "Definition = a / (b c) / d ")); + EXPECT_TRUE(exact(g, "Definition", "Macro(param) <- a ")); + EXPECT_FALSE(exact(g, "Definition", "Macro (param) <- a ")); } -TEST_CASE("PEG Definition", "[peg]") -{ - auto g = ParserGenerator::grammar(); - REQUIRE(exact(g, "Definition", "Definition <- a / (b c) / d ") == true); - REQUIRE(exact(g, "Definition", "Definition <- a / b c / d ") == true); - REQUIRE(exact(g, "Definition", u8"Definitiond ← a ") == true); - REQUIRE(exact(g, "Definition", "Definition ") == false); - REQUIRE(exact(g, "Definition", " ") == false); - REQUIRE(exact(g, "Definition", "") == false); - REQUIRE(exact(g, "Definition", "Definition = a / (b c) / d ") == false); - REQUIRE(exact(g, "Definition", "Macro(param) <- a ") == true); - REQUIRE(exact(g, "Definition", "Macro (param) <- a ") == false); +TEST(LeftRecursiveTest, PEG_Expression) { + auto g = ParserGenerator::grammar(); + EXPECT_TRUE(exact(g, "Expression", "a / (b c) / d ")); + EXPECT_TRUE(exact(g, "Expression", "a / b c / d ")); + EXPECT_TRUE(exact(g, "Expression", "a b ")); + EXPECT_TRUE(exact(g, "Expression", "")); + EXPECT_FALSE(exact(g, "Expression", " ")); + EXPECT_FALSE(exact(g, "Expression", " a b ")); + + // NOTE: The followings are actually allowed in the original Ford's paper... + EXPECT_TRUE(exact(g, "Expression", "a//b ")); + EXPECT_TRUE(exact(g, "Expression", "a // b ")); + EXPECT_TRUE(exact(g, "Expression", "a / / b ")); } -TEST_CASE("PEG Expression", "[peg]") -{ - auto g = ParserGenerator::grammar(); - REQUIRE(exact(g, "Expression", "a / (b c) / d ") == true); - REQUIRE(exact(g, "Expression", "a / b c / d ") == true); - REQUIRE(exact(g, "Expression", "a b ") == true); - REQUIRE(exact(g, "Expression", "") == true); - REQUIRE(exact(g, "Expression", " ") == false); - REQUIRE(exact(g, "Expression", " a b ") == false); - - // NOTE: The followings are actually allowed in the original Ford's paper... - REQUIRE(exact(g, "Expression", "a//b ") == true); - REQUIRE(exact(g, "Expression", "a // b ") == true); - REQUIRE(exact(g, "Expression", "a / / b ") == true); +TEST(LeftRecursiveTest, PEG_Sequence) { + auto g = ParserGenerator::grammar(); + EXPECT_TRUE(exact(g, "Sequence", "a b c d ")); + EXPECT_TRUE(exact(g, "Sequence", "")); + EXPECT_FALSE(exact(g, "Sequence", "!")); + EXPECT_FALSE(exact(g, "Sequence", "<-")); + EXPECT_FALSE(exact(g, "Sequence", " a")); } -TEST_CASE("PEG Sequence", "[peg]") -{ - auto g = ParserGenerator::grammar(); - REQUIRE(exact(g, "Sequence", "a b c d ") == true); - REQUIRE(exact(g, "Sequence", "") == true); - REQUIRE(exact(g, "Sequence", "!") == false); - REQUIRE(exact(g, "Sequence", "<-") == false); - REQUIRE(exact(g, "Sequence", " a") == false); +TEST(LeftRecursiveTest, PEG_Prefix) { + auto g = ParserGenerator::grammar(); + EXPECT_TRUE(exact(g, "Prefix", "&[a]")); + EXPECT_TRUE(exact(g, "Prefix", "![']")); + EXPECT_FALSE(exact(g, "Prefix", "-[']")); + EXPECT_FALSE(exact(g, "Prefix", "")); + EXPECT_FALSE(exact(g, "Prefix", " a")); } -TEST_CASE("PEG Prefix", "[peg]") -{ - auto g = ParserGenerator::grammar(); - REQUIRE(exact(g, "Prefix", "&[a]") == true); - REQUIRE(exact(g, "Prefix", "![']") == true); - REQUIRE(exact(g, "Prefix", "-[']") == false); - REQUIRE(exact(g, "Prefix", "") == false); - REQUIRE(exact(g, "Prefix", " a") == false); +TEST(LeftRecursiveTest, PEG_Suffix) { + auto g = ParserGenerator::grammar(); + EXPECT_TRUE(exact(g, "Suffix", "aaa ")); + EXPECT_TRUE(exact(g, "Suffix", "aaa? ")); + EXPECT_TRUE(exact(g, "Suffix", "aaa* ")); + EXPECT_TRUE(exact(g, "Suffix", "aaa+ ")); + EXPECT_FALSE(exact(g, "Suffix", "aaa{} ")); + EXPECT_TRUE(exact(g, "Suffix", "aaa{10} ")); + EXPECT_TRUE(exact(g, "Suffix", "aaa{10,} ")); + EXPECT_TRUE(exact(g, "Suffix", "aaa{10,100} ")); + EXPECT_TRUE(exact(g, "Suffix", "aaa{,100} ")); + EXPECT_TRUE(exact(g, "Suffix", ". + ")); + EXPECT_TRUE(exact(g, "Suffix", ". {10} ")); + EXPECT_FALSE(exact(g, "Suffix", "?")); + EXPECT_FALSE(exact(g, "Suffix", "+")); + EXPECT_FALSE(exact(g, "Suffix", "{10}")); + EXPECT_FALSE(exact(g, "Suffix", "")); + EXPECT_FALSE(exact(g, "Suffix", " a")); } -TEST_CASE("PEG Suffix", "[peg]") -{ - auto g = ParserGenerator::grammar(); - REQUIRE(exact(g, "Suffix", "aaa ") == true); - REQUIRE(exact(g, "Suffix", "aaa? ") == true); - REQUIRE(exact(g, "Suffix", "aaa* ") == true); - REQUIRE(exact(g, "Suffix", "aaa+ ") == true); - REQUIRE(exact(g, "Suffix", "aaa{} ") == false); - REQUIRE(exact(g, "Suffix", "aaa{10} ") == true); - REQUIRE(exact(g, "Suffix", "aaa{10,} ") == true); - REQUIRE(exact(g, "Suffix", "aaa{10,100} ") == true); - REQUIRE(exact(g, "Suffix", "aaa{,100} ") == true); - REQUIRE(exact(g, "Suffix", ". + ") == true); - REQUIRE(exact(g, "Suffix", ". {10} ") == true); - REQUIRE(exact(g, "Suffix", "?") == false); - REQUIRE(exact(g, "Suffix", "+") == false); - REQUIRE(exact(g, "Suffix", "{10}") == false); - REQUIRE(exact(g, "Suffix", "") == false); - REQUIRE(exact(g, "Suffix", " a") == false); +TEST(LeftRecursiveTest, PEG_Primary) { + auto g = ParserGenerator::grammar(); + EXPECT_TRUE(exact(g, "Primary", "_Identifier0_ ")); + EXPECT_FALSE(exact(g, "Primary", "_Identifier0_<-")); + EXPECT_TRUE(exact(g, "Primary", "( _Identifier0_ _Identifier1_ )")); + EXPECT_TRUE(exact(g, "Primary", "'Literal String'")); + EXPECT_TRUE(exact(g, "Primary", "\"Literal String\"")); + EXPECT_TRUE(exact(g, "Primary", "[a-zA-Z]")); + EXPECT_TRUE(exact(g, "Primary", ".")); + EXPECT_FALSE(exact(g, "Primary", "")); + EXPECT_FALSE(exact(g, "Primary", " ")); + EXPECT_FALSE(exact(g, "Primary", " a")); + EXPECT_FALSE(exact(g, "Primary", "")); } -TEST_CASE("PEG Primary", "[peg]") -{ - auto g = ParserGenerator::grammar(); - REQUIRE(exact(g, "Primary", "_Identifier0_ ") == true); - REQUIRE(exact(g, "Primary", "_Identifier0_<-") == false); - REQUIRE(exact(g, "Primary", "( _Identifier0_ _Identifier1_ )") == true); - REQUIRE(exact(g, "Primary", "'Literal String'") == true); - REQUIRE(exact(g, "Primary", "\"Literal String\"") == true); - REQUIRE(exact(g, "Primary", "[a-zA-Z]") == true); - REQUIRE(exact(g, "Primary", ".") == true); - REQUIRE(exact(g, "Primary", "") == false); - REQUIRE(exact(g, "Primary", " ") == false); - REQUIRE(exact(g, "Primary", " a") == false); - REQUIRE(exact(g, "Primary", "") == false); +TEST(LeftRecursiveTest, PEG_Identifier) { + auto g = ParserGenerator::grammar(); + EXPECT_TRUE(exact(g, "Identifier", "_Identifier0_ ")); + EXPECT_FALSE(exact(g, "Identifier", "0Identifier_ ")); + EXPECT_FALSE(exact(g, "Identifier", "Iden|t ")); + EXPECT_FALSE(exact(g, "Identifier", " ")); + EXPECT_FALSE(exact(g, "Identifier", " a")); + EXPECT_FALSE(exact(g, "Identifier", "")); } -TEST_CASE("PEG Identifier", "[peg]") -{ - auto g = ParserGenerator::grammar(); - REQUIRE(exact(g, "Identifier", "_Identifier0_ ") == true); - REQUIRE(exact(g, "Identifier", "0Identifier_ ") == false); - REQUIRE(exact(g, "Identifier", "Iden|t ") == false); - REQUIRE(exact(g, "Identifier", " ") == false); - REQUIRE(exact(g, "Identifier", " a") == false); - REQUIRE(exact(g, "Identifier", "") == false); +TEST(LeftRecursiveTest, PEG_IdentStart) { + auto g = ParserGenerator::grammar(); + EXPECT_TRUE(exact(g, "IdentStart", "_")); + EXPECT_TRUE(exact(g, "IdentStart", "a")); + EXPECT_TRUE(exact(g, "IdentStart", "Z")); + EXPECT_FALSE(exact(g, "IdentStart", "")); + EXPECT_FALSE(exact(g, "IdentStart", " ")); + EXPECT_FALSE(exact(g, "IdentStart", "0")); } -TEST_CASE("PEG IdentStart", "[peg]") -{ - auto g = ParserGenerator::grammar(); - REQUIRE(exact(g, "IdentStart", "_") == true); - REQUIRE(exact(g, "IdentStart", "a") == true); - REQUIRE(exact(g, "IdentStart", "Z") == true); - REQUIRE(exact(g, "IdentStart", "") == false); - REQUIRE(exact(g, "IdentStart", " ") == false); - REQUIRE(exact(g, "IdentStart", "0") == false); +TEST(LeftRecursiveTest, PEG_IdentRest) { + auto g = ParserGenerator::grammar(); + EXPECT_TRUE(exact(g, "IdentRest", "_")); + EXPECT_TRUE(exact(g, "IdentRest", "a")); + EXPECT_TRUE(exact(g, "IdentRest", "Z")); + EXPECT_FALSE(exact(g, "IdentRest", "")); + EXPECT_FALSE(exact(g, "IdentRest", " ")); + EXPECT_TRUE(exact(g, "IdentRest", "0")); } -TEST_CASE("PEG IdentRest", "[peg]") -{ - auto g = ParserGenerator::grammar(); - REQUIRE(exact(g, "IdentRest", "_") == true); - REQUIRE(exact(g, "IdentRest", "a") == true); - REQUIRE(exact(g, "IdentRest", "Z") == true); - REQUIRE(exact(g, "IdentRest", "") == false); - REQUIRE(exact(g, "IdentRest", " ") == false); - REQUIRE(exact(g, "IdentRest", "0") == true); +TEST(LeftRecursiveTest, PEG_Literal) { + auto g = ParserGenerator::grammar(); + EXPECT_TRUE(exact(g, "Literal", "'abc' ")); + EXPECT_TRUE(exact(g, "Literal", "'a\\nb\\tc' ")); + EXPECT_TRUE(exact(g, "Literal", "'a\\277\tc' ")); + EXPECT_TRUE(exact(g, "Literal", "'a\\77\tc' ")); + EXPECT_FALSE(exact(g, "Literal", "'a\\80\tc' ")); + EXPECT_TRUE(exact(g, "Literal", "'\n' ")); + EXPECT_TRUE(exact(g, "Literal", "'a\\'b' ")); + EXPECT_FALSE(exact(g, "Literal", "'a'b' ")); + EXPECT_FALSE(exact(g, "Literal", "'a\"'b' ")); + EXPECT_TRUE(exact(g, "Literal", "\"'\\\"abc\\\"'\" ")); + EXPECT_FALSE(exact(g, "Literal", "\"'\"abc\"'\" ")); + EXPECT_FALSE(exact(g, "Literal", "abc")); + EXPECT_FALSE(exact(g, "Literal", "")); + EXPECT_FALSE(exact(g, "Literal", "\\")); + EXPECT_TRUE(exact(g, "Literal", u8"'日本語'")); + EXPECT_TRUE(exact(g, "Literal", u8"\"日本語\"")); + EXPECT_FALSE(exact(g, "Literal", u8"日本語")); } -TEST_CASE("PEG Literal", "[peg]") -{ - auto g = ParserGenerator::grammar(); - REQUIRE(exact(g, "Literal", "'abc' ") == true); - REQUIRE(exact(g, "Literal", "'a\\nb\\tc' ") == true); - REQUIRE(exact(g, "Literal", "'a\\277\tc' ") == true); - REQUIRE(exact(g, "Literal", "'a\\77\tc' ") == true); - REQUIRE(exact(g, "Literal", "'a\\80\tc' ") == false); - REQUIRE(exact(g, "Literal", "'\n' ") == true); - REQUIRE(exact(g, "Literal", "'a\\'b' ") == true); - REQUIRE(exact(g, "Literal", "'a'b' ") == false); - REQUIRE(exact(g, "Literal", "'a\"'b' ") == false); - REQUIRE(exact(g, "Literal", "\"'\\\"abc\\\"'\" ") == true); - REQUIRE(exact(g, "Literal", "\"'\"abc\"'\" ") == false); - REQUIRE(exact(g, "Literal", "abc") == false); - REQUIRE(exact(g, "Literal", "") == false); - REQUIRE(exact(g, "Literal", "\\") == false); - REQUIRE(exact(g, "Literal", u8"'日本語'") == true); - REQUIRE(exact(g, "Literal", u8"\"日本語\"") == true); - REQUIRE(exact(g, "Literal", u8"日本語") == false); +TEST(LeftRecursiveTest, PEG_Class) { + auto g = ParserGenerator::grammar(); + EXPECT_FALSE(exact(g, "Class", "[]")); // NOTE: This is different from the Brian Ford's paper, but + // same as RegExp + EXPECT_TRUE(exact(g, "Class", "[a]")); + EXPECT_TRUE(exact(g, "Class", "[a-z]")); + EXPECT_TRUE(exact(g, "Class", "[az]")); + EXPECT_TRUE(exact(g, "Class", "[a-zA-Z-]")); + EXPECT_TRUE(exact(g, "Class", "[a-zA-Z-0-9]")); + EXPECT_FALSE(exact(g, "Class", "[a-]")); + EXPECT_TRUE(exact(g, "Class", "[-a]")); + EXPECT_FALSE(exact(g, "Class", "[")); + EXPECT_FALSE(exact(g, "Class", "[a")); + EXPECT_FALSE(exact(g, "Class", "]")); + EXPECT_FALSE(exact(g, "Class", "a]")); + EXPECT_TRUE(exact(g, "Class", u8"[あ-ん]")); + EXPECT_FALSE(exact(g, "Class", u8"あ-ん")); + EXPECT_TRUE(exact(g, "Class", "[-+]")); + EXPECT_FALSE(exact(g, "Class", "[+-]")); + EXPECT_TRUE(exact(g, "Class", "[\\^]")); } -TEST_CASE("PEG Class", "[peg]") -{ - auto g = ParserGenerator::grammar(); - REQUIRE(exact(g, "Class", "[]") == false); // NOTE: This is different from the Brian Ford's paper, but same as RegExp - REQUIRE(exact(g, "Class", "[a]") == true); - REQUIRE(exact(g, "Class", "[a-z]") == true); - REQUIRE(exact(g, "Class", "[az]") == true); - REQUIRE(exact(g, "Class", "[a-zA-Z-]") == true); - REQUIRE(exact(g, "Class", "[a-zA-Z-0-9]") == true); - REQUIRE(exact(g, "Class", "[a-]") == false); - REQUIRE(exact(g, "Class", "[-a]") == true); - REQUIRE(exact(g, "Class", "[") == false); - REQUIRE(exact(g, "Class", "[a") == false); - REQUIRE(exact(g, "Class", "]") == false); - REQUIRE(exact(g, "Class", "a]") == false); - REQUIRE(exact(g, "Class", u8"[あ-ん]") == true); - REQUIRE(exact(g, "Class", u8"あ-ん") == false); - REQUIRE(exact(g, "Class", "[-+]") == true); - REQUIRE(exact(g, "Class", "[+-]") == false); - REQUIRE(exact(g, "Class", "[\\^]") == true); +TEST(LeftRecursiveTest, PEG_Negated_Class) { + auto g = ParserGenerator::grammar(); + EXPECT_FALSE(exact(g, "NegatedClass", "[^]")); + EXPECT_TRUE(exact(g, "NegatedClass", "[^a]")); + EXPECT_TRUE(exact(g, "NegatedClass", "[^a-z]")); + EXPECT_TRUE(exact(g, "NegatedClass", "[^az]")); + EXPECT_TRUE(exact(g, "NegatedClass", "[^a-zA-Z-]")); + EXPECT_TRUE(exact(g, "NegatedClass", "[^a-zA-Z-0-9]")); + EXPECT_FALSE(exact(g, "NegatedClass", "[^a-]")); + EXPECT_TRUE(exact(g, "NegatedClass", "[^-a]")); + EXPECT_FALSE(exact(g, "NegatedClass", "[^")); + EXPECT_FALSE(exact(g, "NegatedClass", "[^a")); + EXPECT_FALSE(exact(g, "NegatedClass", "^]")); + EXPECT_FALSE(exact(g, "NegatedClass", "^a]")); + EXPECT_TRUE(exact(g, "NegatedClass", u8"[^あ-ん]")); + EXPECT_FALSE(exact(g, "NegatedClass", u8"^あ-ん")); + EXPECT_TRUE(exact(g, "NegatedClass", "[^-+]")); + EXPECT_FALSE(exact(g, "NegatedClass", "[^+-]")); + EXPECT_TRUE(exact(g, "NegatedClass", "[^^]")); } -TEST_CASE("PEG Negated Class", "[peg]") -{ - auto g = ParserGenerator::grammar(); - REQUIRE(exact(g, "NegatedClass", "[^]") == false); - REQUIRE(exact(g, "NegatedClass", "[^a]") == true); - REQUIRE(exact(g, "NegatedClass", "[^a-z]") == true); - REQUIRE(exact(g, "NegatedClass", "[^az]") == true); - REQUIRE(exact(g, "NegatedClass", "[^a-zA-Z-]") == true); - REQUIRE(exact(g, "NegatedClass", "[^a-zA-Z-0-9]") == true); - REQUIRE(exact(g, "NegatedClass", "[^a-]") == false); - REQUIRE(exact(g, "NegatedClass", "[^-a]") == true); - REQUIRE(exact(g, "NegatedClass", "[^") == false); - REQUIRE(exact(g, "NegatedClass", "[^a") == false); - REQUIRE(exact(g, "NegatedClass", "^]") == false); - REQUIRE(exact(g, "NegatedClass", "^a]") == false); - REQUIRE(exact(g, "NegatedClass", u8"[^あ-ん]") == true); - REQUIRE(exact(g, "NegatedClass", u8"^あ-ん") == false); - REQUIRE(exact(g, "NegatedClass", "[^-+]") == true); - REQUIRE(exact(g, "NegatedClass", "[^+-]") == false); - REQUIRE(exact(g, "NegatedClass", "[^^]") == true); +TEST(LeftRecursiveTest, PEG_Range) { + auto g = ParserGenerator::grammar(); + EXPECT_TRUE(exact(g, "Range", "a")); + EXPECT_TRUE(exact(g, "Range", "a-z")); + EXPECT_FALSE(exact(g, "Range", "az")); + EXPECT_FALSE(exact(g, "Range", "")); + EXPECT_FALSE(exact(g, "Range", "a-")); + EXPECT_FALSE(exact(g, "Range", "-a")); } -TEST_CASE("PEG Range", "[peg]") -{ - auto g = ParserGenerator::grammar(); - REQUIRE(exact(g, "Range", "a") == true); - REQUIRE(exact(g, "Range", "a-z") == true); - REQUIRE(exact(g, "Range", "az") == false); - REQUIRE(exact(g, "Range", "") == false); - REQUIRE(exact(g, "Range", "a-") == false); - REQUIRE(exact(g, "Range", "-a") == false); +TEST(LeftRecursiveTest, PEG_Char) { + auto g = ParserGenerator::grammar(); + EXPECT_TRUE(exact(g, "Char", "\\n")); + EXPECT_TRUE(exact(g, "Char", "\\r")); + EXPECT_TRUE(exact(g, "Char", "\\t")); + EXPECT_TRUE(exact(g, "Char", "\\'")); + EXPECT_TRUE(exact(g, "Char", "\\\"")); + EXPECT_TRUE(exact(g, "Char", "\\[")); + EXPECT_TRUE(exact(g, "Char", "\\]")); + EXPECT_TRUE(exact(g, "Char", "\\\\")); + EXPECT_TRUE(exact(g, "Char", "\\000")); + EXPECT_TRUE(exact(g, "Char", "\\377")); + EXPECT_FALSE(exact(g, "Char", "\\477")); + EXPECT_FALSE(exact(g, "Char", "\\087")); + EXPECT_FALSE(exact(g, "Char", "\\079")); + EXPECT_TRUE(exact(g, "Char", "\\00")); + EXPECT_TRUE(exact(g, "Char", "\\77")); + EXPECT_FALSE(exact(g, "Char", "\\80")); + EXPECT_FALSE(exact(g, "Char", "\\08")); + EXPECT_TRUE(exact(g, "Char", "\\0")); + EXPECT_TRUE(exact(g, "Char", "\\7")); + EXPECT_FALSE(exact(g, "Char", "\\8")); + EXPECT_TRUE(exact(g, "Char", "\\x0")); + EXPECT_TRUE(exact(g, "Char", "\\x00")); + EXPECT_FALSE(exact(g, "Char", "\\x000")); + EXPECT_TRUE(exact(g, "Char", "\\xa")); + EXPECT_TRUE(exact(g, "Char", "\\xab")); + EXPECT_FALSE(exact(g, "Char", "\\xabc")); + EXPECT_TRUE(exact(g, "Char", "\\xA")); + EXPECT_TRUE(exact(g, "Char", "\\xAb")); + EXPECT_FALSE(exact(g, "Char", "\\xAbc")); + EXPECT_FALSE(exact(g, "Char", "\\xg")); + EXPECT_FALSE(exact(g, "Char", "\\xga")); + EXPECT_FALSE(exact(g, "Char", "\\u0")); + EXPECT_FALSE(exact(g, "Char", "\\u00")); + EXPECT_TRUE(exact(g, "Char", "\\u0000")); + EXPECT_TRUE(exact(g, "Char", "\\u000000")); + EXPECT_FALSE(exact(g, "Char", "\\u0000000")); + EXPECT_TRUE(exact(g, "Char", "\\uFFFF")); + EXPECT_TRUE(exact(g, "Char", "\\u10000")); + EXPECT_TRUE(exact(g, "Char", "\\u10FFFF")); + EXPECT_FALSE(exact(g, "Char", "\\u110000")); + EXPECT_FALSE(exact(g, "Char", "\\uFFFFFF")); + EXPECT_TRUE(exact(g, "Char", "a")); + EXPECT_TRUE(exact(g, "Char", ".")); + EXPECT_TRUE(exact(g, "Char", "0")); + EXPECT_FALSE(exact(g, "Char", "\\")); + EXPECT_TRUE(exact(g, "Char", " ")); + EXPECT_FALSE(exact(g, "Char", " ")); + EXPECT_FALSE(exact(g, "Char", "")); + EXPECT_TRUE(exact(g, "Char", u8"あ")); } -TEST_CASE("PEG Char", "[peg]") -{ - auto g = ParserGenerator::grammar(); - REQUIRE(exact(g, "Char", "\\n") == true); - REQUIRE(exact(g, "Char", "\\r") == true); - REQUIRE(exact(g, "Char", "\\t") == true); - REQUIRE(exact(g, "Char", "\\'") == true); - REQUIRE(exact(g, "Char", "\\\"") == true); - REQUIRE(exact(g, "Char", "\\[") == true); - REQUIRE(exact(g, "Char", "\\]") == true); - REQUIRE(exact(g, "Char", "\\\\") == true); - REQUIRE(exact(g, "Char", "\\000") == true); - REQUIRE(exact(g, "Char", "\\377") == true); - REQUIRE(exact(g, "Char", "\\477") == false); - REQUIRE(exact(g, "Char", "\\087") == false); - REQUIRE(exact(g, "Char", "\\079") == false); - REQUIRE(exact(g, "Char", "\\00") == true); - REQUIRE(exact(g, "Char", "\\77") == true); - REQUIRE(exact(g, "Char", "\\80") == false); - REQUIRE(exact(g, "Char", "\\08") == false); - REQUIRE(exact(g, "Char", "\\0") == true); - REQUIRE(exact(g, "Char", "\\7") == true); - REQUIRE(exact(g, "Char", "\\8") == false); - REQUIRE(exact(g, "Char", "\\x0") == true); - REQUIRE(exact(g, "Char", "\\x00") == true); - REQUIRE(exact(g, "Char", "\\x000") == false); - REQUIRE(exact(g, "Char", "\\xa") == true); - REQUIRE(exact(g, "Char", "\\xab") == true); - REQUIRE(exact(g, "Char", "\\xabc") == false); - REQUIRE(exact(g, "Char", "\\xA") == true); - REQUIRE(exact(g, "Char", "\\xAb") == true); - REQUIRE(exact(g, "Char", "\\xAbc") == false); - REQUIRE(exact(g, "Char", "\\xg") == false); - REQUIRE(exact(g, "Char", "\\xga") == false); - REQUIRE(exact(g, "Char", "\\u0") == false); - REQUIRE(exact(g, "Char", "\\u00") == false); - REQUIRE(exact(g, "Char", "\\u0000") == true); - REQUIRE(exact(g, "Char", "\\u000000") == true); - REQUIRE(exact(g, "Char", "\\u0000000") == false); - REQUIRE(exact(g, "Char", "\\uFFFF") == true); - REQUIRE(exact(g, "Char", "\\u10000") == true); - REQUIRE(exact(g, "Char", "\\u10FFFF") == true); - REQUIRE(exact(g, "Char", "\\u110000") == false); - REQUIRE(exact(g, "Char", "\\uFFFFFF") == false); - REQUIRE(exact(g, "Char", "a") == true); - REQUIRE(exact(g, "Char", ".") == true); - REQUIRE(exact(g, "Char", "0") == true); - REQUIRE(exact(g, "Char", "\\") == false); - REQUIRE(exact(g, "Char", " ") == true); - REQUIRE(exact(g, "Char", " ") == false); - REQUIRE(exact(g, "Char", "") == false); - REQUIRE(exact(g, "Char", u8"あ") == true); +TEST(LeftRecursiveTest, PEG_Operators) { + auto g = ParserGenerator::grammar(); + EXPECT_TRUE(exact(g, "LEFTARROW", "<-")); + EXPECT_TRUE(exact(g, "SLASH", "/ ")); + EXPECT_TRUE(exact(g, "AND", "& ")); + EXPECT_TRUE(exact(g, "NOT", "! ")); + EXPECT_TRUE(exact(g, "QUESTION", "? ")); + EXPECT_TRUE(exact(g, "STAR", "* ")); + EXPECT_TRUE(exact(g, "PLUS", "+ ")); + EXPECT_TRUE(exact(g, "OPEN", "( ")); + EXPECT_TRUE(exact(g, "CLOSE", ") ")); + EXPECT_TRUE(exact(g, "DOT", ". ")); } -TEST_CASE("PEG Operators", "[peg]") -{ - auto g = ParserGenerator::grammar(); - REQUIRE(exact(g, "LEFTARROW", "<-") == true); - REQUIRE(exact(g, "SLASH", "/ ") == true); - REQUIRE(exact(g, "AND", "& ") == true); - REQUIRE(exact(g, "NOT", "! ") == true); - REQUIRE(exact(g, "QUESTION", "? ") == true); - REQUIRE(exact(g, "STAR", "* ") == true); - REQUIRE(exact(g, "PLUS", "+ ") == true); - REQUIRE(exact(g, "OPEN", "( ") == true); - REQUIRE(exact(g, "CLOSE", ") ") == true); - REQUIRE(exact(g, "DOT", ". ") == true); +TEST(LeftRecursiveTest, PEG_Comment) { + auto g = ParserGenerator::grammar(); + EXPECT_TRUE(exact(g, "Comment", "# Comment.\n")); + EXPECT_FALSE(exact(g, "Comment", "# Comment.")); + EXPECT_FALSE(exact(g, "Comment", " ")); + EXPECT_FALSE(exact(g, "Comment", "a")); } -TEST_CASE("PEG Comment", "[peg]") -{ - auto g = ParserGenerator::grammar(); - REQUIRE(exact(g, "Comment", "# Comment.\n") == true); - REQUIRE(exact(g, "Comment", "# Comment.") == false); - REQUIRE(exact(g, "Comment", " ") == false); - REQUIRE(exact(g, "Comment", "a") == false); +TEST(LeftRecursiveTest, PEG_Space) { + auto g = ParserGenerator::grammar(); + EXPECT_TRUE(exact(g, "Space", " ")); + EXPECT_TRUE(exact(g, "Space", "\t")); + EXPECT_TRUE(exact(g, "Space", "\n")); + EXPECT_FALSE(exact(g, "Space", "")); + EXPECT_FALSE(exact(g, "Space", "a")); } -TEST_CASE("PEG Space", "[peg]") -{ - auto g = ParserGenerator::grammar(); - REQUIRE(exact(g, "Space", " ") == true); - REQUIRE(exact(g, "Space", "\t") == true); - REQUIRE(exact(g, "Space", "\n") == true); - REQUIRE(exact(g, "Space", "") == false); - REQUIRE(exact(g, "Space", "a") == false); +TEST(LeftRecursiveTest, PEG_EndOfLine) { + auto g = ParserGenerator::grammar(); + EXPECT_TRUE(exact(g, "EndOfLine", "\r\n")); + EXPECT_TRUE(exact(g, "EndOfLine", "\n")); + EXPECT_TRUE(exact(g, "EndOfLine", "\r")); + EXPECT_FALSE(exact(g, "EndOfLine", " ")); + EXPECT_FALSE(exact(g, "EndOfLine", "")); + EXPECT_FALSE(exact(g, "EndOfLine", "a")); } -TEST_CASE("PEG EndOfLine", "[peg]") -{ - auto g = ParserGenerator::grammar(); - REQUIRE(exact(g, "EndOfLine", "\r\n") == true); - REQUIRE(exact(g, "EndOfLine", "\n") == true); - REQUIRE(exact(g, "EndOfLine", "\r") == true); - REQUIRE(exact(g, "EndOfLine", " ") == false); - REQUIRE(exact(g, "EndOfLine", "") == false); - REQUIRE(exact(g, "EndOfLine", "a") == false); -} - -TEST_CASE("PEG EndOfFile", "[peg]") -{ - Grammar g = make_peg_grammar(); - REQUIRE(exact(g, "EndOfFile", "") == true); - REQUIRE(exact(g, "EndOfFile", " ") == false); +TEST(LeftRecursiveTest, PEG_EndOfFile) { + Grammar g = make_peg_grammar(); + EXPECT_TRUE(exact(g, "EndOfFile", "")); + EXPECT_FALSE(exact(g, "EndOfFile", " ")); }