summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/tools/nsc/ast/parser/Scanners.scala')
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Scanners.scala32
1 files changed, 22 insertions, 10 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
index 226c49ec07..d72002f0a7 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
@@ -543,24 +543,36 @@ trait Scanners extends ScannersCommon {
}
fetchDoubleQuote()
case '\'' =>
+ def unclosedCharLit() = {
+ val msg = "unclosed character literal"
+ // previous token was Symbol contiguous with the orphan single quote at offset
+ if (token == SYMBOLLIT && offset == lastOffset) {
+ syntaxError(s"""$msg (or use " for string literal "$strVal")""")
+ } else {
+ syntaxError(msg)
+ }
+ }
def fetchSingleQuote() = {
nextChar()
if (isIdentifierStart(ch))
charLitOr(getIdentRest)
else if (isOperatorPart(ch) && (ch != '\\'))
charLitOr(getOperatorRest)
+ else if (ch == '\'') {
+ nextChar()
+ val advice = if (ch == '\'') { do nextChar() while (ch == '\''); " (use '\\'' for single quote)" } else ""
+ syntaxError(s"empty character literal${advice}")
+ }
else if (!isAtEnd && (ch != SU && ch != CR && ch != LF || isUnicodeEscape)) {
getLitChar()
- if (ch == '\'') {
+ if (ch != '\'') unclosedCharLit()
+ else {
nextChar()
token = CHARLIT
setStrVal()
- } else {
- syntaxError("unclosed character literal")
}
}
- else
- syntaxError("unclosed character literal")
+ else unclosedCharLit()
}
fetchSingleQuote()
case '.' =>
@@ -792,7 +804,7 @@ trait Scanners extends ScannersCommon {
next.token = kwArray(idx)
}
} else {
- syntaxError("invalid string interpolation: `$$', `$'ident or `$'BlockExpr expected")
+ syntaxError(s"invalid string interpolation $$$ch, expected: $$$$, $$identifier or $${expression}")
}
} else {
val isUnclosedLiteral = !isUnicodeEscape && (ch == SU || (!multiLine && (ch == CR || ch == LF)))
@@ -983,6 +995,8 @@ trait Scanners extends ScannersCommon {
def intVal: Long = intVal(negated = false)
+ private val zeroFloat = raw"[0.]+(?:[eE][+-]?[0-9]+)?[fFdD]?".r
+
/** Convert current strVal, base to float value.
*/
def floatVal(negated: Boolean): Float = {
@@ -990,8 +1004,7 @@ trait Scanners extends ScannersCommon {
val value: Float = java.lang.Float.parseFloat(strVal)
if (value > Float.MaxValue)
syntaxError("floating point number too large")
- val zeroly = "0.fF"
- if (value == 0.0f && strVal.exists(c => !zeroly.contains(c)))
+ if (value == 0.0f && !zeroFloat.pattern.matcher(strVal).matches)
syntaxError("floating point number too small")
if (negated) -value else value
} catch {
@@ -1010,8 +1023,7 @@ trait Scanners extends ScannersCommon {
val value: Double = java.lang.Double.parseDouble(strVal)
if (value > Double.MaxValue)
syntaxError("double precision floating point number too large")
- val zeroly = "0.dD"
- if (value == 0.0d && strVal.exists(c => !zeroly.contains(c)))
+ if (value == 0.0d && !zeroFloat.pattern.matcher(strVal).matches)
syntaxError("double precision floating point number too small")
if (negated) -value else value
} catch {