@@ -306,39 +306,16 @@ object Parsers {
306306 } finally inFunReturnType = saved
307307 }
308308
309- /** A placeholder for dummy arguments that should be re-parsed as parameters */
310- val ParamNotArg = EmptyTree
311-
312309 /** A flag indicating we are parsing in the annotations of a primary
313310 * class constructor
314311 */
315312 private [this ] var inClassConstrAnnots = false
316313
317314 private def fromWithinClassConstr [T ](body : => T ): T = {
318315 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
342319 }
343320
344321 def migrationWarningOrError (msg : String , offset : Int = in.offset) =
@@ -1371,80 +1348,22 @@ object Parsers {
13711348
13721349 /** ParArgumentExprs ::= `(' [ExprsInParens] `)'
13731350 * | `(' [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))
14121354
14131355 /** ArgumentExprs ::= ParArgumentExprs
14141356 * | [nl] BlockExpr
14151357 */
14161358 def argumentExprs (): List [Tree ] =
14171359 if (in.token == LBRACE ) blockExpr() :: Nil else parArgumentExprs()
14181360
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
14461364 }
14471365
1366+
14481367 /** ArgumentExprss ::= {ArgumentExprs}
14491368 */
14501369 def argumentExprss (fn : Tree ): Tree = {
@@ -1455,17 +1374,29 @@ object Parsers {
14551374
14561375 /** ParArgumentExprss ::= {ParArgumentExprs}
14571376 *
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+ }
14671395 }
1396+ if (in.token == LPAREN && (! inClassConstrAnnots || isLegalAnnotArg))
1397+ parArgumentExprss(Apply (fn, parArgumentExprs()))
14681398 else fn
1399+ }
14691400
14701401 /** BlockExpr ::= `{' BlockExprContents `}'
14711402 * BlockExprContents ::= CaseClauses | Block
0 commit comments