diff --git a/src/language/PEGGrammar.hpp b/src/language/PEGGrammar.hpp index fb3b1d74abf6ba0d33113ec95996c6a270edb77d..553a2797c8cf227ab88d4b977f9f727b671a4c7a 100644 --- a/src/language/PEGGrammar.hpp +++ b/src/language/PEGGrammar.hpp @@ -55,11 +55,13 @@ struct character : if_must_else< one< '\\' >, escaped_c, ascii::any> {}; struct open_parent : seq< one< '(' >, ignored > {}; struct close_parent : seq< one< ')' >, ignored > {}; -struct literal : if_must< one< '"' >, until< one< '"' >, character > > {}; +struct literal : star< minus<character, one < '"' > > >{}; + +struct quoted_literal : if_must< one< '"' >, seq< literal, one< '"' > > >{}; struct import_kw : TAO_PEGTL_KEYWORD("import") {}; -struct LITERAL : seq< literal, ignored >{}; +struct LITERAL : seq< quoted_literal, ignored >{}; struct REAL : seq< real, ignored >{}; diff --git a/src/language/utils/ASTPrinter.cpp b/src/language/utils/ASTPrinter.cpp index 9bf18bdcf88f6399283750dac9ab0b38d8bf0400..8cc88b530997eb3cc9cccb176c3812c41dceea1f 100644 --- a/src/language/utils/ASTPrinter.cpp +++ b/src/language/utils/ASTPrinter.cpp @@ -14,9 +14,10 @@ ASTPrinter::_print(std::ostream& os, const ASTNode& node) const } os << rang::fg::reset; - if (node.is_type<language::name>() or node.is_type<language::literal>() or node.is_type<language::integer>() or - node.is_type<language::real>()) { + if (node.is_type<language::name>() or node.is_type<language::integer>() or node.is_type<language::real>()) { os << ':' << rang::fgB::green << node.string() << rang::fg::reset; + } else if (node.is_type<language::literal>()) { + os << ":\"" << rang::fgB::green << node.string() << rang::fg::reset << '"'; } if (m_info & static_cast<InfoBaseType>(Info::data_type)) { diff --git a/src/utils/EscapedString.hpp b/src/utils/EscapedString.hpp index ed525abd0368614fb756fd8c7795bb1c7ea178c6..cf0f0c676ebd2998673c62870b07e52bf04e0269 100644 --- a/src/utils/EscapedString.hpp +++ b/src/utils/EscapedString.hpp @@ -1,6 +1,7 @@ #ifndef ESCAPED_STRING_HPP #define ESCAPED_STRING_HPP +#include <utils/Exceptions.hpp> #include <utils/PugsMacros.hpp> #include <sstream> @@ -11,7 +12,7 @@ PUGS_INLINE std::string unescapeString(std::string_view input_string) { std::stringstream ss; - for (size_t i = 1; i < input_string.size() - 1; ++i) { + for (size_t i = 0; i < input_string.size(); ++i) { char c = input_string[i]; if (c == '\\') { ++i; @@ -81,11 +82,15 @@ escapeString(std::string_view input_string) ss << R"(\\)"; break; } + case '\'': { + ss << R"(\')"; + break; + } case '\"': { ss << R"(\")"; break; } - case '?': { + case '\?': { ss << R"(\?)"; break; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 027b1293fd477360d3dffc78da4ab1f2417ee3a6..b58ed3cf808860f9500755dd1cebecb1e255d05f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -60,6 +60,7 @@ add_executable (unit_tests test_Demangle.cpp test_DoWhileProcessor.cpp test_EmbeddedData.cpp + test_EscapedString.cpp test_ExecutionPolicy.cpp test_FakeProcessor.cpp test_ForProcessor.cpp diff --git a/tests/test_EscapedString.cpp b/tests/test_EscapedString.cpp new file mode 100644 index 0000000000000000000000000000000000000000..925ebadbda1f8851d7d2ee208bbaa619b8dd435b --- /dev/null +++ b/tests/test_EscapedString.cpp @@ -0,0 +1,27 @@ +#ifndef TEST_ESCAPED_STRING_HPP +#define TEST_ESCAPED_STRING_HPP + +#include <catch2/catch.hpp> + +#include <utils/EscapedString.hpp> + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("EscapedString", "[utils]") +{ + SECTION("escape string") + { + const std::string s = "foo\'\\\"\?\a\b\f\n\r\t\vbar"; + + REQUIRE(escapeString(s) == R"(foo\'\\\"\?\a\b\f\n\r\t\vbar)"); + } + + SECTION("unescape string") + { + const std::string s = R"(foo\'\\\"\?\a\b\f\n\r\t\vbar)"; + + REQUIRE(unescapeString(s) == std::string{"foo\'\\\"\?\a\b\f\n\r\t\vbar"}); + } +} + +#endif // TEST_ESCAPED_STRING_HPP