@@ -555,10 +555,29 @@ object Parsers {
555555 accept(tok)
556556 try body finally accept(tok + 1 )
557557
558+ /** Same as enclosed, but if closing token is missing, add `,` to the expected tokens
559+ * in the error message provided the next token could have followed a `,`.
560+ */
561+ def enclosedWithCommas [T ](tok : Token , body : => T ): T =
562+ accept(tok)
563+ val closing = tok + 1
564+ val isEmpty = in.token == closing
565+ val ts = body
566+ if in.token != closing then
567+ val followComma =
568+ if tok == LPAREN then canStartExprTokens3 else canStartTypeTokens
569+ val prefix = if ! isEmpty && followComma.contains(in.token) then " ',' or " else " "
570+ syntaxErrorOrIncomplete(ExpectedTokenButFound (closing, in.token, prefix))
571+ if in.token == closing then in.nextToken()
572+ ts
573+
558574 def inParens [T ](body : => T ): T = enclosed(LPAREN , body)
559575 def inBraces [T ](body : => T ): T = enclosed(LBRACE , body)
560576 def inBrackets [T ](body : => T ): T = enclosed(LBRACKET , body)
561577
578+ def inParensWithCommas [T ](body : => T ): T = enclosedWithCommas(LPAREN , body)
579+ def inBracketsWithCommas [T ](body : => T ): T = enclosedWithCommas(LBRACKET , body)
580+
562581 def inBracesOrIndented [T ](body : => T , rewriteWithColon : Boolean = false ): T =
563582 if in.token == INDENT then
564583 val rewriteToBraces = in.rewriteNoIndent
@@ -1672,7 +1691,7 @@ object Parsers {
16721691 /** FunParamClause ::= ‘(’ TypedFunParam {‘,’ TypedFunParam } ‘)’
16731692 */
16741693 def funParamClause (): List [ValDef ] =
1675- inParens (commaSeparated(() => typedFunParam(in.offset, ident())))
1694+ inParensWithCommas (commaSeparated(() => typedFunParam(in.offset, ident())))
16761695
16771696 def funParamClauses (): List [List [ValDef ]] =
16781697 if in.token == LPAREN then funParamClause() :: funParamClauses() else Nil
@@ -1853,7 +1872,7 @@ object Parsers {
18531872 else
18541873 def singletonArgs (t : Tree ): Tree =
18551874 if in.token == LPAREN && in.featureEnabled(Feature .dependent)
1856- then singletonArgs(AppliedTypeTree (t, inParens (commaSeparated(singleton))))
1875+ then singletonArgs(AppliedTypeTree (t, inParensWithCommas (commaSeparated(singleton))))
18571876 else t
18581877 singletonArgs(simpleType1())
18591878
@@ -1869,7 +1888,7 @@ object Parsers {
18691888 def simpleType1 () = simpleTypeRest {
18701889 if in.token == LPAREN then
18711890 atSpan(in.offset) {
1872- makeTupleOrParens(inParens (argTypes(namedOK = false , wildOK = true )))
1891+ makeTupleOrParens(inParensWithCommas (argTypes(namedOK = false , wildOK = true )))
18731892 }
18741893 else if in.token == LBRACE then
18751894 atSpan(in.offset) { RefinedTypeTree (EmptyTree , refinement(indentOK = false )) }
@@ -2022,7 +2041,8 @@ object Parsers {
20222041 /** TypeArgs ::= `[' Type {`,' Type} `]'
20232042 * NamedTypeArgs ::= `[' NamedTypeArg {`,' NamedTypeArg} `]'
20242043 */
2025- def typeArgs (namedOK : Boolean , wildOK : Boolean ): List [Tree ] = inBrackets(argTypes(namedOK, wildOK))
2044+ def typeArgs (namedOK : Boolean , wildOK : Boolean ): List [Tree ] =
2045+ inBracketsWithCommas(argTypes(namedOK, wildOK))
20262046
20272047 /** Refinement ::= `{' RefineStatSeq `}'
20282048 */
@@ -2518,7 +2538,7 @@ object Parsers {
25182538 placeholderParams = param :: placeholderParams
25192539 atSpan(start) { Ident (pname) }
25202540 case LPAREN =>
2521- atSpan(in.offset) { makeTupleOrParens(inParens (exprsInParensOrBindings())) }
2541+ atSpan(in.offset) { makeTupleOrParens(inParensWithCommas (exprsInParensOrBindings())) }
25222542 case LBRACE | INDENT =>
25232543 canApply = false
25242544 blockExpr()
@@ -2616,15 +2636,15 @@ object Parsers {
26162636 /** ParArgumentExprs ::= `(' [‘using’] [ExprsInParens] `)'
26172637 * | `(' [ExprsInParens `,'] PostfixExpr `*' ')'
26182638 */
2619- def parArgumentExprs (): (List [Tree ], Boolean ) = inParens {
2620- if in.token == RPAREN then
2621- ( Nil , false )
2622- else if isIdent(nme.using) then
2623- in.nextToken()
2624- (commaSeparated(argumentExpr), true )
2625- else
2626- (commaSeparated(argumentExpr), false )
2627- }
2639+ def parArgumentExprs (): (List [Tree ], Boolean ) =
2640+ inParensWithCommas :
2641+ if in.token == RPAREN then
2642+ ( Nil , false )
2643+ else if isIdent(nme.using) then
2644+ in.nextToken( )
2645+ (commaSeparated(argumentExpr), true )
2646+ else
2647+ (commaSeparated(argumentExpr), false )
26282648
26292649 /** ArgumentExprs ::= ParArgumentExprs
26302650 * | [nl] BlockExpr
@@ -2985,7 +3005,7 @@ object Parsers {
29853005 case USCORE =>
29863006 wildcardIdent()
29873007 case LPAREN =>
2988- atSpan(in.offset) { makeTupleOrParens(inParens (patternsOpt())) }
3008+ atSpan(in.offset) { makeTupleOrParens(inParensWithCommas (patternsOpt())) }
29893009 case QUOTE =>
29903010 simpleExpr(Location .InPattern )
29913011 case XMLSTART =>
@@ -3031,7 +3051,7 @@ object Parsers {
30313051 * | ‘(’ [Patterns ‘,’] PatVar ‘*’ ‘)’
30323052 */
30333053 def argumentPatterns (): List [Tree ] =
3034- inParens (patternsOpt(Location .InPatternArgs ))
3054+ inParensWithCommas (patternsOpt(Location .InPatternArgs ))
30353055
30363056/* -------- MODIFIERS and ANNOTATIONS ------------------------------------------- */
30373057
@@ -3220,7 +3240,7 @@ object Parsers {
32203240 * HkTypeParamClause ::= ‘[’ HkTypeParam {‘,’ HkTypeParam} ‘]’
32213241 * HkTypeParam ::= {Annotation} [‘+’ | ‘-’] (id [HkTypePamClause] | ‘_’) TypeBounds
32223242 */
3223- def typeParamClause (ownerKind : ParamOwner ): List [TypeDef ] = inBrackets {
3243+ def typeParamClause (ownerKind : ParamOwner ): List [TypeDef ] = inBracketsWithCommas {
32243244
32253245 def checkVarianceOK (): Boolean =
32263246 val ok = ownerKind != ParamOwner .Def && ownerKind != ParamOwner .TypeParam
@@ -3360,7 +3380,7 @@ object Parsers {
33603380 }
33613381
33623382 // begin termParamClause
3363- inParens {
3383+ inParensWithCommas {
33643384 if in.token == RPAREN && ! prefix && ! impliedMods.is(Given ) then Nil
33653385 else
33663386 val clause =
0 commit comments