diff --git a/src/main/java/org/prlprg/parseprint/Scanner.java b/src/main/java/org/prlprg/parseprint/Scanner.java index 78cbf7175..778b76d37 100644 --- a/src/main/java/org/prlprg/parseprint/Scanner.java +++ b/src/main/java/org/prlprg/parseprint/Scanner.java @@ -309,9 +309,9 @@ public String readQuoted(char quote) { case 'r' -> sb.append('\r'); case 't' -> sb.append('\t'); case '"' -> sb.append('"'); - case '\\' -> sb.append('\\'); case '\'' -> sb.append('\''); case '`' -> sb.append('`'); + case '\\' -> sb.append('\\'); case 'x' -> { var hex = readFixedLength(2); try { @@ -362,7 +362,13 @@ public String readQuotedLiterally(char quote) { return sb.toString(); } else if (c == '\\') { switch (readChar()) { - case 'n', 'r', 't', '"', '\\', '\'', '`' -> {} + case 'n' -> sb.append('n'); + case 'r' -> sb.append('r'); + case 't' -> sb.append('t'); + case '"' -> sb.append('"'); + case '\'' -> sb.append('\''); + case '`' -> sb.append('`'); + case '\\' -> sb.append('\\'); case 'x' -> { var hex = readFixedLength(2); try { diff --git a/src/main/java/org/prlprg/primitive/Names.java b/src/main/java/org/prlprg/primitive/Names.java index 5b5e917d6..c6ff28a4e 100644 --- a/src/main/java/org/prlprg/primitive/Names.java +++ b/src/main/java/org/prlprg/primitive/Names.java @@ -1,6 +1,7 @@ package org.prlprg.primitive; import com.google.common.collect.ImmutableList; +import java.util.regex.Pattern; import org.prlprg.parseprint.ParseException; import org.prlprg.parseprint.PrettyPrintWriter; import org.prlprg.parseprint.Scanner; @@ -27,7 +28,7 @@ public static String quoteIfNecessary(String s) { if (s.isEmpty()) { throw new IllegalArgumentException("empty string is reserved for special symbols"); } - return isValidUnquoted(s) ? s : PrettyPrintWriter.use(w -> w.writeQuoted('`', s)); + return isValid(s) ? s : PrettyPrintWriter.use(w -> w.writeQuoted('`', s)); } /** @@ -41,6 +42,8 @@ public static String unquoteIfNecessary(String s) { : s; } + private static final Pattern UNESCAPED_NOT_END_BACKTICK = Pattern.compile("(? 2 - && !s.substring(1, s.length() - 1).replaceAll("\\`", "").contains("`")); + && !UNESCAPED_NOT_END_BACKTICK.matcher(s).find(1)); } /** diff --git a/src/test/java/org/prlprg/parseprint/ScannerTests.java b/src/test/java/org/prlprg/parseprint/ScannerTests.java index ba3417be9..25e540250 100644 --- a/src/test/java/org/prlprg/parseprint/ScannerTests.java +++ b/src/test/java/org/prlprg/parseprint/ScannerTests.java @@ -18,4 +18,12 @@ public void testReadPastEndOfLine() { assertEquals("\n", scanner2.readPastEndOfLine()); assertEquals("3", scanner2.readPastEndOfLine()); } + + @Test + public void testReadQuoted() { + var scanner = new Scanner("\"\\\"Hello\\\", \\\"world!\\\"\""); + assertEquals("\"Hello\", \"world!\"", scanner.readQuoted('"')); + scanner = new Scanner("\"\\\"Hello\\\", \\\"world!\\\"\""); + assertEquals("\"\\\"Hello\\\", \\\"world!\\\"\"", scanner.readQuotedLiterally('"')); + } }