Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 24 additions & 35 deletions compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -183,11 +183,12 @@ object Parsers {
def isIdent = in.isIdent
def isIdent(name: Name) = in.isIdent(name)
def isErased = isIdent(nme.erased) && in.erasedEnabled
def isSimpleLiteral =
simpleLiteralTokens.contains(in.token)
|| isIdent(nme.raw.MINUS) && numericLitTokens.contains(in.lookahead.token)
def isLiteral = literalTokens contains in.token
def isNumericLit = numericLitTokens contains in.token
def isNegatedNumber =
isIdent(nme.raw.MINUS)
&& numericLitTokens.contains(in.lookahead.token)
&& in.lookahead.offset == in.offset + 1
def isSimpleLiteral = simpleLiteralTokens.contains(in.token) || isNegatedNumber
def isLiteral = literalTokens.contains(in.token) || isNegatedNumber
def isTemplateIntro = templateIntroTokens contains in.token
def isDclIntro = dclIntroTokens contains in.token
def isStatSeqEnd = in.isNestedEnd || in.token == EOF || in.token == RPAREN
Expand Down Expand Up @@ -1074,34 +1075,24 @@ object Parsers {
* -- not yet | Singleton ‘[’ Types ‘]’
*/
def singleton(): Tree =
if isSimpleLiteral then simpleLiteral()
if isSimpleLiteral then literal(inTypeOrSingleton = true)
else dotSelectors(simpleRef())

/** SimpleLiteral ::= [‘-’] integerLiteral
* | [‘-’] floatingPointLiteral
* | booleanLiteral
* | characterLiteral
* | stringLiteral
*/
def simpleLiteral(): Tree =
if isIdent(nme.raw.MINUS) then
val start = in.offset
in.nextToken()
literal(negOffset = start, inTypeOrSingleton = true)
else
literal(inTypeOrSingleton = true)

/** Literal ::= SimpleLiteral
* Literal ::= SimpleLiteral
* | processedStringLiteral
* | symbolLiteral
* | ‘null’
*
* @param negOffset The offset of a preceding `-' sign, if any.
* If the literal is not negated, negOffset == in.offset.
*/
def literal(negOffset: Int = in.offset, inPattern: Boolean = false, inTypeOrSingleton: Boolean = false, inStringInterpolation: Boolean = false): Tree = {
def literalOf(token: Token): Tree = {
val isNegated = negOffset < in.offset
def literal(start: Offset = in.offset, inPattern: Boolean = false, inTypeOrSingleton: Boolean = false, inStringInterpolation: Boolean = false): Tree = {
def literalOf(token: Token, isNegated: Boolean = false): Tree = {
def digits0 = in.removeNumberSeparators(in.strVal)
def digits = if (isNegated) "-" + digits0 else digits0
if !inTypeOrSingleton then
Expand Down Expand Up @@ -1137,15 +1128,15 @@ object Parsers {
val t = in.token match {
case STRINGLIT | STRINGPART =>
val value = in.strVal
atSpan(negOffset, negOffset, negOffset + value.length) { Literal(Constant(value)) }
atSpan(start, start, start + value.length) { Literal(Constant(value)) }
case _ =>
syntaxErrorOrIncomplete(IllegalLiteral())
atSpan(negOffset) { Literal(Constant(null)) }
atSpan(start) { Literal(Constant(null)) }
}
in.nextToken()
t
}
else atSpan(negOffset) {
else atSpan(start) {
if (in.token == QUOTEID)
if ((staged & StageKind.Spliced) != 0 && Chars.isIdentifierStart(in.name(0))) {
val t = atSpan(in.offset + 1) {
Expand Down Expand Up @@ -1173,11 +1164,12 @@ object Parsers {
patch(source, Span(in.charOffset - 1), "\")")
atSpan(in.skipToken()) { SymbolLit(in.strVal) }
else if (in.token == INTERPOLATIONID) interpolatedString(inPattern)
else {
val t = literalOf(in.token)
else
val isNegated = isIdent(nme.raw.MINUS)
if isNegated then in.nextToken()
val t = literalOf(in.token, isNegated)
in.nextToken()
t
}
}
}

Expand Down Expand Up @@ -1217,7 +1209,7 @@ object Parsers {
nextSegment(in.offset + offsetCorrection)
offsetCorrection = 0
if (in.token == STRINGLIT)
segmentBuf += literal(inPattern = inPattern, negOffset = in.offset + offsetCorrection, inStringInterpolation = true)
segmentBuf += literal(inPattern = inPattern, start = in.offset + offsetCorrection, inStringInterpolation = true)

InterpolatedString(interpolator, segmentBuf.toList)
}
Expand Down Expand Up @@ -1576,7 +1568,7 @@ object Parsers {
*/
def simpleType(): Tree =
if isSimpleLiteral then
SingletonTypeTree(simpleLiteral())
SingletonTypeTree(literal(inTypeOrSingleton = true))
else if in.token == USCORE then
if ctx.settings.YkindProjector.value == "underscores" then
val start = in.skipToken()
Expand Down Expand Up @@ -2202,12 +2194,10 @@ object Parsers {
if isIdent && nme.raw.isUnary(in.name)
&& in.canStartExprTokens.contains(in.lookahead.token)
then
val start = in.offset
val op = termIdent()
if (op.name == nme.raw.MINUS && isNumericLit)
simpleExprRest(literal(start), location, canApply = true)
if isNegatedNumber then
simpleExprRest(literal(), location, canApply = true)
else
atSpan(start) { PrefixOp(op, simpleExpr(location)) }
atSpan(in.offset) { PrefixOp(termIdent(), simpleExpr(location)) }
else simpleExpr(location)

/** SimpleExpr ::= ‘new’ ConstrApp {`with` ConstrApp} [TemplateBody]
Expand Down Expand Up @@ -2689,9 +2679,8 @@ object Parsers {
*/
def simplePattern(): Tree = in.token match {
case IDENTIFIER | BACKQUOTED_IDENT | THIS | SUPER =>
simpleRef() match
case id @ Ident(nme.raw.MINUS) if isNumericLit => literal(startOffset(id))
case t => simplePatternRest(t)
if isNegatedNumber then literal()
else simplePatternRest(simpleRef())
case USCORE =>
wildcardIdent()
case LPAREN =>
Expand Down
31 changes: 14 additions & 17 deletions compiler/src/dotty/tools/dotc/parsing/Scanners.scala
Original file line number Diff line number Diff line change
Expand Up @@ -759,21 +759,7 @@ object Scanners {
putChar('/')
getOperatorRest()
}
case '0' =>
def fetchLeadingZero(): Unit = {
nextChar()
ch match {
case 'x' | 'X' => base = 16 ; nextChar()
//case 'b' | 'B' => base = 2 ; nextChar()
case _ => base = 10 ; putChar('0')
}
if (base != 10 && !isNumberSeparator(ch) && digit2int(ch, base) < 0)
error("invalid literal number")
}
fetchLeadingZero()
getNumber()
case '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' =>
base = 10
case '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' =>
getNumber()
case '`' =>
getBackquotedIdent()
Expand Down Expand Up @@ -1332,9 +1318,20 @@ object Scanners {
if (isIdentifierPart(ch) && ch >= ' ')
error("Invalid literal number")

/** Read a number into strVal and set base
*/
/** Read a number into strVal and set base.
* @pre ch in '0'..'9'.
*/
protected def getNumber(): Unit = {
if ch == '0' then
nextChar()
ch match
case 'x' | 'X' => base = 16 ; nextChar()
//case 'b' | 'B' => base = 2 ; nextChar()
case _ => base = 10 ; putChar('0')
if base != 10 && !isNumberSeparator(ch) && digit2int(ch, base) < 0 then
error("invalid literal number")
else base = 10

while (isNumberSeparator(ch) || digit2int(ch, base) >= 0) {
putChar(ch)
nextChar()
Expand Down
3 changes: 3 additions & 0 deletions tests/run/neglit.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@main def Test =
assert(-2.abs == 2)
assert(- 2.abs == -2)