diff options
Diffstat (limited to 'src/compiler/scala/tools/nsc/ast/parser/Scanners.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/parser/Scanners.scala | 32 |
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 { |