From 92df957564222e0bc8555560f2f789f4ef9a65af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phan=20Kochen?= Date: Tue, 8 Aug 2023 14:53:05 +0200 Subject: [PATCH 1/2] Add failing test for raw strings with quotes --- tests/GrammarTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/GrammarTest.php b/tests/GrammarTest.php index 798c91c..639d593 100644 --- a/tests/GrammarTest.php +++ b/tests/GrammarTest.php @@ -55,6 +55,7 @@ public function strings(): array ['r#"foo"#', 'foo'], ['r##"foo"##', 'foo'], ['r"\nfoo\r"', '\nfoo\r'], + ['r#"foo"bar"#', 'foo"bar'], ['r##"foo"#', self::ERROR], ]; } From 50f1a61f22ae459cb43f54e8858ce79fa6209876 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phan=20Kochen?= Date: Tue, 8 Aug 2023 15:38:32 +0200 Subject: [PATCH 2/2] Fix raw string with quotes --- src/grammar.php | 43 +++++++++++++++++-------------------------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/src/grammar.php b/src/grammar.php index 46dd89e..80fdf79 100644 --- a/src/grammar.php +++ b/src/grammar.php @@ -35,6 +35,7 @@ sepBy, sequence, string, + takeWhile, zeroOrMore}; function nodes(): Parser @@ -276,33 +277,23 @@ function rawString(): Parser { return memo( __FUNCTION__, - fn() => keepSecond(char('r'), rawStringHash()) - ->label('raw-string') - ); -} - -function rawStringHash(): Parser -{ - return memo( - __FUNCTION__, - function () { - $hashParser = recursive(); - $hashParser->recurse( - either(between(char('#'), char('#'), $hashParser), rawStringQuotes()) - ); + fn () => sequence( + char('r'), + keepFirst(zeroOrMore(char('#')), char('"')) + ->bind(static function (?string $hashes) { + $end = '"' . ($hashes ?? ''); + $endLen = strlen($end); - return $hashParser - ->label('raw-string-hash'); - } - ); -} - -function rawStringQuotes(): Parser -{ - return memo( - __FUNCTION__, - fn() => between(char('"'), char('"'), zeroOrMore(anySingleBut('"'))) - ->label('raw-string-quotes') + $tail = ''; + return takeWhile(static function (string $c) use (&$tail, $end, $endLen) { + $result = $tail !== $end; + $tail = substr($tail . $c, -$endLen); + return $result; + }) + ->map(static fn (string $chunk) => substr($chunk, 0, -$endLen)); + }) + ) + ->label('raw-string') ); }