diff --git a/pmd-cpp/etc/grammar/cpp.jj b/pmd-cpp/etc/grammar/cpp.jj index b535533533..2af09bd98b 100644 --- a/pmd-cpp/etc/grammar/cpp.jj +++ b/pmd-cpp/etc/grammar/cpp.jj @@ -321,6 +321,8 @@ TOKEN : < CHARACTER : ("L")? "'" ( ( ~["'","\\","\r","\n"] ) | ( "\\" ( ~["\n","\r"] ) ) )* "'" > | < STRING : ("L")? "\"" ( ( ~["\"","\\","\r","\n"] ) | ( "\\" ( ~["\n","\r"] | "\n" | "\r\n" ) ) )* "\"" > + +| < RSTRING : "R\"(" ( ~[")"] | ( ")" ~["\""] ) )* ")\"" > } void translation_unit() : diff --git a/pmd-cpp/src/test/java/net/sourceforge/pmd/cpd/CPPTokenizerTest.java b/pmd-cpp/src/test/java/net/sourceforge/pmd/cpd/CPPTokenizerTest.java index 4b78507736..8d36806bcf 100644 --- a/pmd-cpp/src/test/java/net/sourceforge/pmd/cpd/CPPTokenizerTest.java +++ b/pmd-cpp/src/test/java/net/sourceforge/pmd/cpd/CPPTokenizerTest.java @@ -124,6 +124,21 @@ public class CPPTokenizerTest { Tokens tokens = parse("szPath = m_sdcacheDir + _T(\"\\ oMedia\");" + PMD.EOL); assertEquals(10, tokens.size()); } + + @Test + public void testRawStringLiteral() { + String code = + "const char* const KDefaultConfig = R\"(\n" + + " [Sinks.1]\n" + + " Destination=Console\n" + + " AutoFlush=true\n" + + " Format=\"[%TimeStamp%] %ThreadId% %QueryIdHigh% %QueryIdLow% %LoggerFile%:%Line% (%Severity%) - %Message%\"\n" + + " Filter=\"%Severity% >= WRN\"\n" + + ")\";\n"; + Tokens tokens = parse(code); + assertTrue(TokenEntry.getEOF() != tokens.getTokens().get(0)); + assertEquals(9, tokens.size()); + } private Tokens parse(String snippet) { return parse(snippet, false);