@@ -306,39 +306,16 @@ object Parsers {
306
306
} finally inFunReturnType = saved
307
307
}
308
308
309
- /** A placeholder for dummy arguments that should be re-parsed as parameters */
310
- val ParamNotArg = EmptyTree
311
-
312
309
/** A flag indicating we are parsing in the annotations of a primary
313
310
* class constructor
314
311
*/
315
312
private [this ] var inClassConstrAnnots = false
316
313
317
314
private def fromWithinClassConstr [T ](body : => T ): T = {
318
315
val saved = inClassConstrAnnots
319
- try {
320
- inClassConstrAnnots = true
321
- body
322
- } finally {
323
- inClassConstrAnnots = saved
324
- if (lookaheadTokens.nonEmpty) {
325
- in.insertTokens(lookaheadTokens.toList)
326
- lookaheadTokens.clear()
327
- }
328
- }
329
- }
330
-
331
- /** Lookahead tokens for the case of annotations in class constructors.
332
- * We store tokens in lookahead as long as they can form a valid prefix
333
- * of a class parameter clause.
334
- */
335
- private [this ] var lookaheadTokens = new ListBuffer [TokenData ]
336
-
337
- /** Copy current token to end of lookahead */
338
- private def saveLookahead () = {
339
- val lookahead = new TokenData {}
340
- lookahead.copyFrom(in)
341
- lookaheadTokens += lookahead
316
+ inClassConstrAnnots = true
317
+ try body
318
+ finally inClassConstrAnnots = saved
342
319
}
343
320
344
321
def migrationWarningOrError (msg : String , offset : Int = in.offset) =
@@ -1371,80 +1348,22 @@ object Parsers {
1371
1348
1372
1349
/** ParArgumentExprs ::= `(' [ExprsInParens] `)'
1373
1350
* | `(' [ExprsInParens `,'] PostfixExpr `:' `_' `*' ')'
1374
- *
1375
- * Special treatment for arguments of primary class constructor
1376
- * annotations. All empty argument lists `(` `)` following the first
1377
- * get represented as `List(ParamNotArg)` instead of `Nil`, indicating that
1378
- * the token sequence should be interpreted as an empty parameter clause
1379
- * instead. `ParamNotArg` can also be produced when parsing the first
1380
- * argument (see `classConstrAnnotExpr`).
1381
- *
1382
- * The method affects `lookaheadTokens` as a side effect.
1383
- * If the argument list parses as `List(ParamNotArg)`, `lookaheadTokens`
1384
- * contains the tokens that need to be replayed to parse the parameter clause.
1385
- * Otherwise, `lookaheadTokens` is empty.
1386
- */
1387
- def parArgumentExprs (first : Boolean = false ): List [Tree ] = {
1388
- if (inClassConstrAnnots) {
1389
- assert(lookaheadTokens.isEmpty)
1390
- saveLookahead()
1391
- accept(LPAREN )
1392
- val args =
1393
- if (in.token == RPAREN )
1394
- if (first) Nil // first () counts as annotation argument
1395
- else ParamNotArg :: Nil
1396
- else {
1397
- openParens.change(LPAREN , + 1 )
1398
- try commaSeparated(argumentExpr)
1399
- finally openParens.change(LPAREN , - 1 )
1400
- }
1401
- if (args == ParamNotArg :: Nil )
1402
- in.adjustSepRegions(RPAREN ) // simulate `)` without requiring it
1403
- else {
1404
- lookaheadTokens.clear()
1405
- accept(RPAREN )
1406
- }
1407
- args
1408
- }
1409
- else
1410
- inParens(if (in.token == RPAREN ) Nil else commaSeparated(argumentExpr))
1411
- }
1351
+ */
1352
+ def parArgumentExprs (): List [Tree ] =
1353
+ inParens(if (in.token == RPAREN ) Nil else commaSeparated(argumentExpr))
1412
1354
1413
1355
/** ArgumentExprs ::= ParArgumentExprs
1414
1356
* | [nl] BlockExpr
1415
1357
*/
1416
1358
def argumentExprs (): List [Tree ] =
1417
1359
if (in.token == LBRACE ) blockExpr() :: Nil else parArgumentExprs()
1418
1360
1419
- val argumentExpr = () => {
1420
- val arg =
1421
- if (inClassConstrAnnots && lookaheadTokens.nonEmpty) classConstrAnnotExpr()
1422
- else exprInParens()
1423
- arg match {
1424
- case arg @ Assign (Ident (id), rhs) => cpy.NamedArg (arg)(id, rhs)
1425
- case arg => arg
1426
- }
1427
- }
1428
-
1429
- /** Handle first argument of an argument list to an annotation of
1430
- * a primary class constructor. If the current token either cannot
1431
- * start an expression or is an identifier and is followed by `:`,
1432
- * stop parsing the rest of the expression and return `EmptyTree`,
1433
- * indicating that we should re-parse the expression as a parameter clause.
1434
- * Otherwise parse as normal.
1435
- */
1436
- def classConstrAnnotExpr () = {
1437
- if (in.token == IDENTIFIER ) {
1438
- saveLookahead()
1439
- postfixExpr() match {
1440
- case Ident (_) if in.token == COLON => ParamNotArg
1441
- case t => expr1Rest(t, Location .InParens )
1442
- }
1443
- }
1444
- else if (isExprIntro) exprInParens()
1445
- else ParamNotArg
1361
+ val argumentExpr = () => exprInParens() match {
1362
+ case arg @ Assign (Ident (id), rhs) => cpy.NamedArg (arg)(id, rhs)
1363
+ case arg => arg
1446
1364
}
1447
1365
1366
+
1448
1367
/** ArgumentExprss ::= {ArgumentExprs}
1449
1368
*/
1450
1369
def argumentExprss (fn : Tree ): Tree = {
@@ -1455,17 +1374,29 @@ object Parsers {
1455
1374
1456
1375
/** ParArgumentExprss ::= {ParArgumentExprs}
1457
1376
*
1458
- * Special treatment for arguments of primary class constructor
1459
- * annotations. If an argument list returns `List(ParamNotArg)`
1460
- * ignore it, and return prefix parsed before that list instead.
1461
- */
1462
- def parArgumentExprss (fn : Tree ): Tree =
1463
- if (in.token == LPAREN ) {
1464
- val args = parArgumentExprs(first = ! fn.isInstanceOf [Trees .Apply [_]])
1465
- if (inClassConstrAnnots && args == ParamNotArg :: Nil ) fn
1466
- else parArgumentExprss(Apply (fn, args))
1377
+ * Special treatment for arguments to primary constructor annotations.
1378
+ * (...) is considered an argument only if it does not look like a formal
1379
+ * parameter list, i.e. does not start with `( <annot>* <mod>* ident : `
1380
+ * Furthermore, `()` is considered a annotation argument only if it comes first.
1381
+ */
1382
+ def parArgumentExprss (fn : Tree ): Tree = {
1383
+ def isLegalAnnotArg : Boolean = {
1384
+ val lookahead = in.lookaheadScanner
1385
+ (lookahead.token == LPAREN ) && {
1386
+ lookahead.nextToken()
1387
+ if (lookahead.token == RPAREN )
1388
+ ! fn.isInstanceOf [Trees .Apply [_]] // allow one () as annotation argument
1389
+ else if (lookahead.token == IDENTIFIER ) {
1390
+ lookahead.nextToken()
1391
+ lookahead.token != COLON
1392
+ }
1393
+ else canStartExpressionTokens.contains(lookahead.token)
1394
+ }
1467
1395
}
1396
+ if (in.token == LPAREN && (! inClassConstrAnnots || isLegalAnnotArg))
1397
+ parArgumentExprss(Apply (fn, parArgumentExprs()))
1468
1398
else fn
1399
+ }
1469
1400
1470
1401
/** BlockExpr ::= `{' BlockExprContents `}'
1471
1402
* BlockExprContents ::= CaseClauses | Block
0 commit comments