File tree Expand file tree Collapse file tree 4 files changed +78
-9
lines changed
src/dotty/tools/dotc/parsing Expand file tree Collapse file tree 4 files changed +78
-9
lines changed Original file line number Diff line number Diff line change @@ -773,19 +773,25 @@ object Scanners {
773
773
}
774
774
fetchDoubleQuote()
775
775
case '\' ' =>
776
- def fetchSingleQuote () = {
776
+ def fetchSingleQuote (): Unit = {
777
777
nextChar()
778
- if ( isIdentifierStart(ch))
778
+ if isIdentifierStart(ch) then
779
779
charLitOr { getIdentRest(); QUOTEID }
780
- else if ( isOperatorPart(ch) && ( ch != '\\ ' ))
780
+ else if isOperatorPart(ch) && ch != '\\ ' then
781
781
charLitOr { getOperatorRest(); QUOTEID }
782
782
else ch match {
783
783
case '{' | '[' | ' ' | '\t ' if lookaheadChar() != '\' ' =>
784
784
token = QUOTE
785
- case _ =>
785
+ case _ if ! isAtEnd && (ch != SU && ch != CR && ch != LF || isUnicodeEscape) =>
786
+ val isEmptyCharLit = (ch == '\' ' )
786
787
getLitChar()
787
- if (ch == '\' ' ) finishCharLit()
788
+ if ch == '\' ' then
789
+ if isEmptyCharLit then error(" empty character literal (use '\\ '' for single quote)" )
790
+ else finishCharLit()
791
+ else if isEmptyCharLit then error(" empty character literal" )
788
792
else error(" unclosed character literal" )
793
+ case _ =>
794
+ error(" unclosed character literal" )
789
795
}
790
796
}
791
797
fetchSingleQuote()
Original file line number Diff line number Diff line change @@ -694,15 +694,21 @@ trait ParallelTesting extends RunnerOrchestration { self =>
694
694
695
695
val errors = errorMap.get(key)
696
696
697
+ def missing = { echo(s " Error reported in ${pos1.source}, but no annotation found " ) ; false }
698
+
697
699
if (errors ne null ) {
698
700
if (errors == 1 ) errorMap.remove(key)
699
701
else errorMap.put(key, errors - 1 )
700
702
true
701
703
}
702
- else {
703
- echo(s " Error reported in ${pos1.source}, but no annotation found " )
704
- false
705
- }
704
+ else if key == " nopos" then
705
+ missing
706
+ else
707
+ errorMap.get(" nopos" ) match
708
+ case null => missing
709
+ case 1 => errorMap.remove(" nopos" ) ; true
710
+ case slack => if slack < 1 then missing
711
+ else errorMap.put(" nopos" , slack - 1 ) ; true
706
712
}
707
713
}
708
714
Original file line number Diff line number Diff line change
1
+ -- Error: tests/neg/t6810.scala:5:10 -----------------------------------------------------------------------------------
2
+ 5 | val y = '
3
+ | ^
4
+ | unclosed character literal
5
+ -- Error: tests/neg/t6810.scala:12:10 ----------------------------------------------------------------------------------
6
+ 12 | val Y = "
7
+ | ^
8
+ | unclosed string literal
9
+ -- Error: tests/neg/t6810.scala:13:0 -----------------------------------------------------------------------------------
10
+ 13 |" // error obviously not
11
+ |^
12
+ |unclosed string literal
13
+ -- Error: tests/neg/t6810.scala:24:6 -----------------------------------------------------------------------------------
14
+ 24 | val `
15
+ | ^
16
+ | unclosed quoted identifier
17
+ -- Error: tests/neg/t6810.scala:25:0 -----------------------------------------------------------------------------------
18
+ 25 |` = EOL // error not raw string literals aka triple-quoted, multiline strings
19
+ |^
20
+ |unclosed quoted identifier
21
+ -- Error: tests/neg/t6810.scala:30:10 ----------------------------------------------------------------------------------
22
+ 30 | val b = '
23
+ | ^
24
+ | unclosed character literal
Original file line number Diff line number Diff line change
1
+
2
+ trait t6810 {
3
+ val x = '\u000A ' // char literals accept arbitrary unicode escapes
4
+ // nopos-error so as not to interfere with the following bad syntax
5
+ val y = '
6
+ ' // but not embedded EOL sequences not represented as escapes
7
+ println(); // scanner firewall
8
+ val z = '\n ' // normally, expect this escape
9
+
10
+ val X = " \u000A " // it's the same as ordinary string literals
11
+ // nopos-error so as not to interfere with the following bad syntax
12
+ val Y = "
13
+ " // error obviously not
14
+ val Z = " \n " // normally, expect this escape
15
+
16
+ val A = """
17
+ """ // which is what these are for
18
+ val B = s """
19
+ """ // or the same for interpolated strings
20
+
21
+ import System .{lineSeparator => EOL }
22
+ val `\u000A` = EOL // backquoted identifiers are arbitrary string literals
23
+ // nopos-error so as not to interfere with the following bad syntax
24
+ val `
25
+ ` = EOL // error not raw string literals aka triple-quoted, multiline strings
26
+
27
+ val firebreak = 42 // help parser recovery, could also use rbrace
28
+
29
+ val a = '\u000D ' // similar treatment of CR
30
+ val b = ' ' // nopos-error CR seen as EOL by scanner; FSR, error only on open quote, unlike `y`
31
+ println(); // scanner firewall
32
+ val c = '\r ' // traditionally
33
+ }
You can’t perform that action at this time.
0 commit comments