From 0af5efbb104d87f7ff4080d2b7218cc5cf8b0c30 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 12 Feb 2021 11:51:44 +0100 Subject: [PATCH] Refine condition of leading infix operator --- .../dotty/tools/dotc/parsing/Scanners.scala | 22 +++++++++++++++++-- tests/pos/i11371.scala | 19 ++++++++++++++++ tests/run/i7031.scala | 3 +-- 3 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 tests/pos/i11371.scala diff --git a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala index 2c9c0cabf1e9..4051d1c8db97 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala @@ -77,6 +77,9 @@ object Scanners { /** Is current token first one after a newline? */ def isAfterLineEnd: Boolean = lineOffset >= 0 + + def isOperator = + token == IDENTIFIER && isOperatorPart(name(name.length - 1)) } abstract class ScannerCommon(source: SourceFile)(using Context) extends CharArrayReader with TokenData { @@ -348,12 +351,27 @@ object Scanners { && (isWhitespace(ch) || ch == LF) && !pastBlankLine && { + // Is current lexeme assumed to start an expression? + // This is the case if the lexime is one of the tokens that + // starts an expression. Furthermore, if the previous token is + // in backticks, the lexeme may not be a binary operator. + // I.e. in + // + // a + // `x` += 1 + // + // `+=` is not assumed to start an expression since it follows an identifier + // in backticks and is a binary operator. Hence, `x` is not classified as a + // leading infix operator. + def assumeStartsExpr(lexeme: TokenData) = + canStartExprTokens.contains(lexeme.token) + && (token != BACKQUOTED_IDENT || !lexeme.isOperator || nme.raw.isUnary(lexeme.name)) val lookahead = LookaheadScanner() lookahead.allowLeadingInfixOperators = false // force a NEWLINE a after current token if it is on its own line lookahead.nextToken() - canStartExprTokens.contains(lookahead.token) - || lookahead.token == NEWLINE && canStartExprTokens.contains(lookahead.next.token) + assumeStartsExpr(lookahead) + || lookahead.token == NEWLINE && assumeStartsExpr(lookahead.next) } && { if migrateTo3 then diff --git a/tests/pos/i11371.scala b/tests/pos/i11371.scala new file mode 100644 index 000000000000..a55d463fce14 --- /dev/null +++ b/tests/pos/i11371.scala @@ -0,0 +1,19 @@ +object HelloWorld { + def whileLoop: Int = { + var i = 0 + var acc = 0 + while (i < 3) { + var `i'` = 0 + while (`i'` < 4) { + acc += (i * `i'`) + `i'` += 1 + } + i += 1 + } + acc + } + + def main(args: Array[String]): Unit = { + println(s"hello world: ${whileLoop}") + } +} \ No newline at end of file diff --git a/tests/run/i7031.scala b/tests/run/i7031.scala index 0bc3fe81f9e6..6e141968a19c 100644 --- a/tests/run/i7031.scala +++ b/tests/run/i7031.scala @@ -2,8 +2,7 @@ val a = 5 val x = 1 - + // - `a` * 6 + + `a` * 6 assert(x == 1, x) }