Skip to content

Commit

Permalink
Allow \" in single-quoted interpolated string literals
Browse files Browse the repository at this point in the history
`\"` no longer closes single-quoted interpolated string literals.
The escape sequence is not processed by the scanner.
  • Loading branch information
lrytz committed Mar 15, 2021
1 parent 77b0ae0 commit e757f26
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 3 deletions.
9 changes: 9 additions & 0 deletions compiler/src/dotty/tools/dotc/parsing/Scanners.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1053,6 +1053,7 @@ object Scanners {
getRawStringLit()
}

// for interpolated strings
@annotation.tailrec private def getStringPart(multiLine: Boolean): Unit =
if (ch == '"')
if (multiLine) {
Expand All @@ -1069,6 +1070,14 @@ object Scanners {
setStrVal()
token = STRINGLIT
}
else if (ch == '\\' && !multiLine) {
putChar(ch)
nextRawChar()
if (ch == '"' || ch == '\\')
putChar(ch)
nextRawChar()
getStringPart(multiLine)
}
else if (ch == '$') {
nextRawChar()
if (ch == '$' || ch == '"') {
Expand Down
4 changes: 3 additions & 1 deletion docs/docs/internals/syntax-3.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,10 @@ stringElement ::= printableChar \ (‘"’ | ‘\’)
| charEscapeSeq
multiLineChars ::= {[‘"’] [‘"’] char \ ‘"’} {‘"’}
processedStringLiteral
::= alphaid ‘"’ {printableChar \ (‘"’ | ‘$’) | escape} ‘"’
::= alphaid ‘"’ {[‘\’] processedStringPart | ‘\\’ | ‘\"’} ‘"’
| alphaid ‘"""’ {[‘"’] [‘"’] char \ (‘"’ | ‘$’) | escape} {‘"’} ‘"""’
processedStringPart
::= printableChar \ (‘"’ | ‘$’ | ‘\’) | escape
escape ::= ‘$$’
| ‘$’ letter { letter | digit }
| ‘{’ Block [‘;’ whiteSpace stringFormat whiteSpace] ‘}’
Expand Down
4 changes: 3 additions & 1 deletion docs/docs/internals/syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,10 @@ stringElement ::= printableChar \ (‘"’ | ‘\’)
| charEscapeSeq
multiLineChars ::= {[‘"’] [‘"’] char \ ‘"’} {‘"’}
processedStringLiteral
::= alphaid ‘"’ {printableChar \ (‘"’ | ‘$’) | escape} ‘"’
::= alphaid ‘"’ {[‘\’] processedStringPart | ‘\\’ | ‘\"’} ‘"’
| alphaid ‘"""’ {[‘"’] [‘"’] char \ (‘"’ | ‘$’) | escape} {‘"’} ‘"""’
processedStringPart
::= printableChar \ (‘"’ | ‘$’ | ‘\’) | escape
escape ::= ‘$$’
| ‘$’ letter { letter | digit }
| ‘{’ Block [‘;’ whiteSpace stringFormat whiteSpace] ‘}’
Expand Down
4 changes: 3 additions & 1 deletion docs/docs/reference/syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,10 @@ stringElement ::= printableChar \ (‘"’ | ‘\’)
| charEscapeSeq
multiLineChars ::= {[‘"’] [‘"’] char \ ‘"’} {‘"’}
processedStringLiteral
::= alphaid ‘"’ {printableChar \ (‘"’ | ‘$’) | escape} ‘"’
::= alphaid ‘"’ {[‘\’] processedStringPart | ‘\\’ | ‘\"’} ‘"’
| alphaid ‘"""’ {[‘"’] [‘"’] char \ (‘"’ | ‘$’) | escape} {‘"’} ‘"""’
processedStringPart
::= printableChar \ (‘"’ | ‘$’ | ‘\’) | escape
escape ::= ‘$$’
| ‘$’ letter { letter | digit }
| ‘{’ Block [‘;’ whiteSpace stringFormat whiteSpace] ‘}’
Expand Down
9 changes: 9 additions & 0 deletions tests/neg/t6476.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// only the last one doesn't parse
class C {
s"""\ """
s"""\\"""
s"""\"""
s"\ "
s"\\"
s"\" // error
} // error (should not be one)
8 changes: 8 additions & 0 deletions tests/neg/t6476b.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class C {
val sa = s"""\""" // error: invalid escape
val sb = s"""\\"""
val sc = s"""\ """ // error: invalid escape
val ra = raw"""\"""
val rb = raw"""\\"""
val rc = raw"""\ """
}
13 changes: 13 additions & 0 deletions tests/run/t6476.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"Hello", Alice
"Hello", Alice
\"Hello\", Alice
\"Hello\", Alice
\"Hello\", Alice
\"Hello\", Alice
\TILT\
\\TILT\\
\\TILT\\
\TILT\
\\TILT\\
\\TILT\\
\TILT\
23 changes: 23 additions & 0 deletions tests/run/t6476.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
object Test {
def main(args: Array[String]): Unit = {
val person = "Alice"
println(s"\"Hello\", $person")
println(s"""\"Hello\", $person""")

println(f"\"Hello\", $person")
println(f"""\"Hello\", $person""")

println(raw"\"Hello\", $person")
println(raw"""\"Hello\", $person""")

println(s"\\TILT\\")
println(f"\\TILT\\")
println(raw"\\TILT\\")

println(s"""\\TILT\\""")
println(f"""\\TILT\\""")
println(raw"""\\TILT\\""")

println(raw"""\TILT\""")
}
}

0 comments on commit e757f26

Please sign in to comment.