#include #include #include #include //////////////////////////////////////////////////////////////////////////////////////////////////// TEST(UtilsTests, ParseSimple) { std::stringstream s("identifier 5 \n-51\t 0 1 expected unexpected"); plasp::utils::Parser<> p("input", s); // TODO: reimplement //ASSERT_TRUE(p.isCaseSensitive()); ASSERT_EQ(p.parse(), "identifier"); ASSERT_EQ(p.parse(), 5u); ASSERT_EQ(p.parse(), -51); ASSERT_EQ(p.parse(), false); ASSERT_EQ(p.parse(), true); ASSERT_NO_THROW(p.expect("expected")); ASSERT_THROW(p.expect("expected"), plasp::utils::ParserException); // TODO: test case-insensitive input // TODO: test probing } //////////////////////////////////////////////////////////////////////////////////////////////////// TEST(UtilsTests, ParseUnsignedNumbers) { std::stringstream s("100 200 -300 -400"); plasp::utils::Parser<> p("input", s); ASSERT_EQ(p.parse(), 100); ASSERT_EQ(p.parse(), 200u); ASSERT_EQ(p.parse(), -300); ASSERT_THROW(p.parse(), plasp::utils::ParserException); } //////////////////////////////////////////////////////////////////////////////////////////////////// TEST(UtilsTests, ParseEndOfFile) { std::stringstream s1("test"); plasp::utils::Parser<> p1("input", s1); ASSERT_NO_THROW(p1.expect("test")); ASSERT_THROW(p1.parse(), plasp::utils::ParserException); std::stringstream s2("test1 test2 test3"); plasp::utils::Parser<> p2("input", s2); ASSERT_NO_THROW(p2.expect("test1")); ASSERT_NO_THROW(p2.expect("test2")); ASSERT_NO_THROW(p2.expect("test3")); ASSERT_THROW(p2.parse(), plasp::utils::ParserException); std::stringstream s3("-127"); plasp::utils::Parser<> p3("input", s3); p3.expect(-127); ASSERT_THROW(p3.parse(), plasp::utils::ParserException); std::stringstream s4("128 -1023 -4095"); plasp::utils::Parser<> p4("input", s4); ASSERT_NO_THROW(p4.expect(128)); ASSERT_NO_THROW(p4.expect(-1023)); ASSERT_NO_THROW(p4.expect(-4095)); ASSERT_THROW(p4.parse(), plasp::utils::ParserException); std::stringstream s5("0"); plasp::utils::Parser<> p5("input", s5); p5.expect(false); ASSERT_THROW(p5.parse(), plasp::utils::ParserException); std::stringstream s6("0 1 0"); plasp::utils::Parser<> p6("input", s6); ASSERT_NO_THROW(p6.expect(false)); ASSERT_NO_THROW(p6.expect(true)); ASSERT_NO_THROW(p6.expect(false)); ASSERT_THROW(p6.parse(), plasp::utils::ParserException); } //////////////////////////////////////////////////////////////////////////////////////////////////// TEST(UtilsTests, ParserPosition) { std::stringstream s("123 \n4\ntest1\n test2\ntest3 \ntest4\n\n\n\n"); plasp::utils::Parser<> p("input", s); const auto startPosition = p.position(); plasp::utils::StreamCoordinate c; c = p.coordinate(); ASSERT_EQ(c.row, 1u); ASSERT_EQ(c.column, 1u); ASSERT_EQ(p.currentCharacter(), '1'); ASSERT_NO_THROW(p.advance()); c = p.coordinate(); ASSERT_EQ(c.row, 1u); ASSERT_EQ(c.column, 2u); ASSERT_EQ(p.currentCharacter(), '2'); ASSERT_NO_THROW(p.advance()); c = p.coordinate(); ASSERT_EQ(c.row, 1u); ASSERT_EQ(c.column, 3u); ASSERT_EQ(p.currentCharacter(), '3'); ASSERT_NO_THROW(p.advance()); c = p.coordinate(); ASSERT_EQ(c.row, 1u); ASSERT_EQ(c.column, 4u); ASSERT_EQ(p.currentCharacter(), ' '); ASSERT_NO_THROW(p.advance()); c = p.coordinate(); ASSERT_EQ(c.row, 1u); ASSERT_EQ(c.column, 5u); ASSERT_EQ(p.currentCharacter(), '\n'); ASSERT_NO_THROW(p.advance()); c = p.coordinate(); ASSERT_EQ(c.row, 2u); ASSERT_EQ(c.column, 1u); ASSERT_EQ(p.currentCharacter(), '4'); ASSERT_NO_THROW(p.advance()); ASSERT_NO_THROW(p.expect("test1")); c = p.coordinate(); ASSERT_EQ(c.row, 3u); ASSERT_EQ(c.column, 6u); ASSERT_NO_THROW(p.expect("test2")); c = p.coordinate(); ASSERT_EQ(c.row, 4u); ASSERT_EQ(c.column, 7u); ASSERT_NO_THROW(p.expect("test3")); c = p.coordinate(); ASSERT_EQ(c.row, 5u); ASSERT_EQ(c.column, 6u); ASSERT_NO_THROW(p.skipLine()); c = p.coordinate(); ASSERT_EQ(c.row, 6u); ASSERT_EQ(c.column, 1u); ASSERT_NO_THROW(p.skipLine()); c = p.coordinate(); ASSERT_EQ(c.row, 7u); ASSERT_EQ(c.column, 1u); ASSERT_NO_THROW(p.skipWhiteSpace()); c = p.coordinate(); ASSERT_EQ(c.row, 10u); ASSERT_EQ(c.column, 1u); ASSERT_TRUE(p.atEnd()); p.reset(); ASSERT_EQ(p.position(), startPosition); ASSERT_FALSE(p.atEnd()); for (size_t i = 0; i < 5; i++) p.advance(); ASSERT_EQ(p.position(), static_cast(5)); p.seek(static_cast(7)); ASSERT_EQ(p.position(), static_cast(7)); ASSERT_NO_THROW(p.expect("test1")); // TODO: test parser with multiple sections } //////////////////////////////////////////////////////////////////////////////////////////////////// TEST(UtilsTests, ParserRemoveComments) { std::stringstream s1("; comment at beginning\ntest1; comment in between\ntest2; comment at end"); plasp::utils::Parser<> p1("input", s1); p1.removeComments(";", "\n", false); plasp::utils::StreamCoordinate c; ASSERT_NO_THROW(p1.expect("test1")); c = p1.coordinate(); ASSERT_EQ(c.row, 2u); ASSERT_EQ(c.column, 6u); ASSERT_NO_THROW(p1.expect("test2")); c = p1.coordinate(); ASSERT_EQ(c.row, 3u); ASSERT_EQ(c.column, 6u); p1.skipWhiteSpace(); ASSERT_TRUE(p1.atEnd()); std::stringstream s2("test;"); plasp::utils::Parser<> p2("input", s2); p2.removeComments(";", "\n", false); ASSERT_NO_THROW(p2.expect("test")); p2.skipWhiteSpace(); ASSERT_TRUE(p2.atEnd()); std::stringstream s3("/* comment at start */ test1 /* comment in between */ test2 /*"); plasp::utils::Parser<> p3("input", s3); p3.removeComments("/*", "*/", true); ASSERT_NO_THROW(p3.expect("test1")); ASSERT_NO_THROW(p3.expect("test2")); p3.skipWhiteSpace(); ASSERT_TRUE(p3.atEnd()); } //////////////////////////////////////////////////////////////////////////////////////////////////// TEST(UtilsTests, EscapeASP) { const std::string predicate = "action(stack_on(block-1, block-2, value@3, value@4))"; const auto escaped = plasp::utils::escapeASP(predicate); const auto unescaped = plasp::utils::unescapeASP(escaped); ASSERT_EQ(escaped.find("-"), std::string::npos); ASSERT_EQ(escaped.find("@"), std::string::npos); ASSERT_EQ(predicate, unescaped); }