Skip to content

Commit e59ed69

Browse files
Merge pull request #11751 from lrytz/escape-quote
Allow \" in single-quoted interpolated string literals
2 parents ed386f0 + e757f26 commit e59ed69

File tree

8 files changed

+71
-3
lines changed

8 files changed

+71
-3
lines changed

compiler/src/dotty/tools/dotc/parsing/Scanners.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,6 +1065,7 @@ object Scanners {
10651065
getRawStringLit()
10661066
}
10671067

1068+
// for interpolated strings
10681069
@annotation.tailrec private def getStringPart(multiLine: Boolean): Unit =
10691070
if (ch == '"')
10701071
if (multiLine) {
@@ -1081,6 +1082,14 @@ object Scanners {
10811082
setStrVal()
10821083
token = STRINGLIT
10831084
}
1085+
else if (ch == '\\' && !multiLine) {
1086+
putChar(ch)
1087+
nextRawChar()
1088+
if (ch == '"' || ch == '\\')
1089+
putChar(ch)
1090+
nextRawChar()
1091+
getStringPart(multiLine)
1092+
}
10841093
else if (ch == '$') {
10851094
nextRawChar()
10861095
if (ch == '$' || ch == '"') {

docs/docs/internals/syntax-3.1.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,10 @@ stringElement ::= printableChar \ (‘"’ | ‘\’)
7070
| charEscapeSeq
7171
multiLineChars ::= {[‘"’] [‘"’] char \ ‘"’} {‘"’}
7272
processedStringLiteral
73-
::= alphaid ‘"’ {printableChar \ (‘"’ | ‘$’) | escape} ‘"’
73+
::= alphaid ‘"’ {[‘\’] processedStringPart | ‘\\’ | ‘\"’} ‘"’
7474
| alphaid ‘"""’ {[‘"’] [‘"’] char \ (‘"’ | ‘$’) | escape} {‘"’} ‘"""’
75+
processedStringPart
76+
::= printableChar \ (‘"’ | ‘$’ | ‘\’) | escape
7577
escape ::= ‘$$’
7678
| ‘$’ letter { letter | digit }
7779
| ‘{’ Block [‘;’ whiteSpace stringFormat whiteSpace] ‘}’

docs/docs/internals/syntax.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,10 @@ stringElement ::= printableChar \ (‘"’ | ‘\’)
6969
| charEscapeSeq
7070
multiLineChars ::= {[‘"’] [‘"’] char \ ‘"’} {‘"’}
7171
processedStringLiteral
72-
::= alphaid ‘"’ {printableChar \ (‘"’ | ‘$’) | escape} ‘"’
72+
::= alphaid ‘"’ {[‘\’] processedStringPart | ‘\\’ | ‘\"’} ‘"’
7373
| alphaid ‘"""’ {[‘"’] [‘"’] char \ (‘"’ | ‘$’) | escape} {‘"’} ‘"""’
74+
processedStringPart
75+
::= printableChar \ (‘"’ | ‘$’ | ‘\’) | escape
7476
escape ::= ‘$$’
7577
| ‘$’ letter { letter | digit }
7678
| ‘{’ Block [‘;’ whiteSpace stringFormat whiteSpace] ‘}’

docs/docs/reference/syntax.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,10 @@ stringElement ::= printableChar \ (‘"’ | ‘\’)
6969
| charEscapeSeq
7070
multiLineChars ::= {[‘"’] [‘"’] char \ ‘"’} {‘"’}
7171
processedStringLiteral
72-
::= alphaid ‘"’ {printableChar \ (‘"’ | ‘$’) | escape} ‘"’
72+
::= alphaid ‘"’ {[‘\’] processedStringPart | ‘\\’ | ‘\"’} ‘"’
7373
| alphaid ‘"""’ {[‘"’] [‘"’] char \ (‘"’ | ‘$’) | escape} {‘"’} ‘"""’
74+
processedStringPart
75+
::= printableChar \ (‘"’ | ‘$’ | ‘\’) | escape
7476
escape ::= ‘$$’
7577
| ‘$’ letter { letter | digit }
7678
| ‘{’ Block [‘;’ whiteSpace stringFormat whiteSpace] ‘}’

tests/neg/t6476.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// only the last one doesn't parse
2+
class C {
3+
s"""\ """
4+
s"""\\"""
5+
s"""\"""
6+
s"\ "
7+
s"\\"
8+
s"\" // error
9+
} // error (should not be one)

tests/neg/t6476b.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class C {
2+
val sa = s"""\""" // error: invalid escape
3+
val sb = s"""\\"""
4+
val sc = s"""\ """ // error: invalid escape
5+
val ra = raw"""\"""
6+
val rb = raw"""\\"""
7+
val rc = raw"""\ """
8+
}

tests/run/t6476.check

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"Hello", Alice
2+
"Hello", Alice
3+
\"Hello\", Alice
4+
\"Hello\", Alice
5+
\"Hello\", Alice
6+
\"Hello\", Alice
7+
\TILT\
8+
\\TILT\\
9+
\\TILT\\
10+
\TILT\
11+
\\TILT\\
12+
\\TILT\\
13+
\TILT\

tests/run/t6476.scala

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
object Test {
2+
def main(args: Array[String]): Unit = {
3+
val person = "Alice"
4+
println(s"\"Hello\", $person")
5+
println(s"""\"Hello\", $person""")
6+
7+
println(f"\"Hello\", $person")
8+
println(f"""\"Hello\", $person""")
9+
10+
println(raw"\"Hello\", $person")
11+
println(raw"""\"Hello\", $person""")
12+
13+
println(s"\\TILT\\")
14+
println(f"\\TILT\\")
15+
println(raw"\\TILT\\")
16+
17+
println(s"""\\TILT\\""")
18+
println(f"""\\TILT\\""")
19+
println(raw"""\\TILT\\""")
20+
21+
println(raw"""\TILT\""")
22+
}
23+
}

0 commit comments

Comments
 (0)