Skip to content

Commit 33c568c

Browse files
committed
SI-8918 Unary ids are plain ids
Allow +,-,!,~ to be used as unprefixed identifiers. As prefix operators, they must be followed by a simple expression, so otherwise, consume the id itself as the start of a simple expression.
1 parent 178e8df commit 33c568c

File tree

2 files changed

+66
-5
lines changed

2 files changed

+66
-5
lines changed

src/compiler/scala/tools/nsc/ast/parser/Parsers.scala

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,15 @@ self =>
665665
}
666666
def isLiteral = isLiteralToken(in.token)
667667

668+
def isSimpleExprIntroToken(token: Token): Boolean = isLiteralToken(token) || (token match {
669+
case IDENTIFIER | BACKQUOTED_IDENT |
670+
THIS | SUPER | NEW | USCORE |
671+
LPAREN | LBRACE | XMLSTART => true
672+
case _ => false
673+
})
674+
675+
def isSimpleExprIntro: Boolean = isExprIntroToken(in.token)
676+
668677
def isExprIntroToken(token: Token): Boolean = isLiteralToken(token) || (token match {
669678
case IDENTIFIER | BACKQUOTED_IDENT |
670679
THIS | SUPER | IF | FOR | NEW | USCORE | TRY | WHILE |
@@ -1565,11 +1574,14 @@ self =>
15651574
def prefixExpr(): Tree = {
15661575
if (isUnaryOp) {
15671576
atPos(in.offset) {
1568-
val name = nme.toUnaryName(rawIdent().toTermName)
1569-
if (name == nme.UNARY_- && isNumericLit)
1570-
simpleExprRest(literal(isNegated = true), canApply = true)
1571-
else
1572-
Select(stripParens(simpleExpr()), name)
1577+
if (lookingAhead(isSimpleExprIntro)) {
1578+
val uname = nme.toUnaryName(rawIdent().toTermName)
1579+
if (uname == nme.UNARY_- && isNumericLit)
1580+
simpleExprRest(literal(isNegated = true), canApply = true)
1581+
else
1582+
Select(stripParens(simpleExpr()), uname)
1583+
}
1584+
else simpleExpr()
15731585
}
15741586
}
15751587
else simpleExpr()

test/files/run/t8918-unary-ids.scala

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
2+
3+
import scala.tools.partest.SessionTest
4+
5+
// Taking unary ids as plain
6+
object Test extends SessionTest {
7+
def session =
8+
"""Type in expressions to have them evaluated.
9+
Type :help for more information.
10+
11+
scala> val - = 42
12+
-: Int = 42
13+
14+
scala> val i = -
15+
i: Int = 42
16+
17+
scala> - { 42 }
18+
res0: Int = -42
19+
20+
scala> - if (true) 1 else 2
21+
<console>:1: error: illegal start of simple expression
22+
- if (true) 1 else 2
23+
^
24+
25+
scala> - - 1
26+
<console>:1: error: ';' expected but integer literal found.
27+
- - 1
28+
^
29+
30+
scala> -.-(1)
31+
res1: Int = 41
32+
33+
scala> -
34+
res2: Int = 42
35+
36+
scala> - -
37+
res3: Int = -42
38+
39+
scala> + -
40+
res4: Int = 42
41+
42+
scala> object X { def -(i: Int) = 42 - i ; def f(g: Int => Int) = g(7) ; def j = f(-) }
43+
defined object X
44+
45+
scala> X.j
46+
res5: Int = 35
47+
48+
scala> :quit"""
49+
}

0 commit comments

Comments
 (0)