@@ -553,19 +553,27 @@ object Parsers {
553
553
def inDefScopeBraces [T ](body : => T , rewriteWithColon : Boolean = false ): T =
554
554
inBracesOrIndented(body, rewriteWithColon)
555
555
556
- /** part { `separator` part }
557
- */
558
- def tokenSeparated [T ](separator : Int , part : () => T ): List [T ] = {
556
+ /** part { `,` part }
557
+ * @param expectedEnd If set to something other than [[EMPTY ]],
558
+ * assume this comma separated list must be followed by this token.
559
+ * If the parser consumes a `part` that is not followed by a comma or this expected
560
+ * token, issue a syntax error and try to recover at the next safe point.
561
+ */
562
+ def commaSeparated [T ](part : () => T , expectedEnd : Token = EMPTY ): List [T ] = {
559
563
val ts = new ListBuffer [T ] += part()
560
- while (in.token == separator ) {
564
+ while (in.token == COMMA ) {
561
565
in.nextToken()
562
566
ts += part()
563
567
}
568
+ if (expectedEnd != EMPTY && in.token != expectedEnd) {
569
+ syntaxErrorOrIncomplete(ExpectedTokenButFound (expectedEnd, in.token))
570
+ if (in.token == COMMA ) {
571
+ ts ++= commaSeparated(part, expectedEnd)
572
+ }
573
+ }
564
574
ts.toList
565
575
}
566
576
567
- def commaSeparated [T ](part : () => T ): List [T ] = tokenSeparated(COMMA , part)
568
-
569
577
def inSepRegion [T ](f : Region => Region )(op : => T ): T =
570
578
val cur = in.currentRegion
571
579
in.currentRegion = f(cur)
@@ -1509,7 +1517,7 @@ object Parsers {
1509
1517
/** FunParamClause ::= ‘(’ TypedFunParam {‘,’ TypedFunParam } ‘)’
1510
1518
*/
1511
1519
def funParamClause (): List [ValDef ] =
1512
- inParens(commaSeparated(() => typedFunParam(in.offset, ident())))
1520
+ inParens(commaSeparated(() => typedFunParam(in.offset, ident()), RPAREN ))
1513
1521
1514
1522
def funParamClauses (): List [List [ValDef ]] =
1515
1523
if in.token == LPAREN then funParamClause() :: funParamClauses() else Nil
@@ -1622,7 +1630,7 @@ object Parsers {
1622
1630
else
1623
1631
def singletonArgs (t : Tree ): Tree =
1624
1632
if in.token == LPAREN && in.featureEnabled(Feature .dependent)
1625
- then singletonArgs(AppliedTypeTree (t, inParens(commaSeparated(singleton))))
1633
+ then singletonArgs(AppliedTypeTree (t, inParens(commaSeparated(singleton, RPAREN ))))
1626
1634
else t
1627
1635
singletonArgs(simpleType1())
1628
1636
@@ -1638,7 +1646,7 @@ object Parsers {
1638
1646
def simpleType1 () = simpleTypeRest {
1639
1647
if in.token == LPAREN then
1640
1648
atSpan(in.offset) {
1641
- makeTupleOrParens(inParens(argTypes(namedOK = false , wildOK = true )))
1649
+ makeTupleOrParens(inParens(argTypes(namedOK = false , wildOK = true , RPAREN )))
1642
1650
}
1643
1651
else if in.token == LBRACE then
1644
1652
atSpan(in.offset) { RefinedTypeTree (EmptyTree , refinement(indentOK = false )) }
@@ -1722,7 +1730,7 @@ object Parsers {
1722
1730
* | NamedTypeArg {`,' NamedTypeArg}
1723
1731
* NamedTypeArg ::= id `=' Type
1724
1732
*/
1725
- def argTypes (namedOK : Boolean , wildOK : Boolean ): List [Tree ] = {
1733
+ def argTypes (namedOK : Boolean , wildOK : Boolean , expectedEnd : Token ): List [Tree ] = {
1726
1734
1727
1735
def argType () = {
1728
1736
val t = typ()
@@ -1739,7 +1747,7 @@ object Parsers {
1739
1747
val rest =
1740
1748
if (in.token == COMMA ) {
1741
1749
in.nextToken()
1742
- commaSeparated(arg)
1750
+ commaSeparated(arg, expectedEnd )
1743
1751
}
1744
1752
else Nil
1745
1753
first :: rest
@@ -1752,7 +1760,7 @@ object Parsers {
1752
1760
case firstArg =>
1753
1761
otherArgs(firstArg, () => argType())
1754
1762
}
1755
- else commaSeparated(() => argType())
1763
+ else commaSeparated(() => argType(), expectedEnd )
1756
1764
}
1757
1765
1758
1766
/** FunArgType ::= Type | `=>' Type
@@ -1781,7 +1789,7 @@ object Parsers {
1781
1789
/** TypeArgs ::= `[' Type {`,' Type} `]'
1782
1790
* NamedTypeArgs ::= `[' NamedTypeArg {`,' NamedTypeArg} `]'
1783
1791
*/
1784
- def typeArgs (namedOK : Boolean , wildOK : Boolean ): List [Tree ] = inBrackets(argTypes(namedOK, wildOK))
1792
+ def typeArgs (namedOK : Boolean , wildOK : Boolean ): List [Tree ] = inBrackets(argTypes(namedOK, wildOK, RBRACKET ))
1785
1793
1786
1794
/** Refinement ::= `{' RefineStatSeq `}'
1787
1795
*/
@@ -2145,7 +2153,7 @@ object Parsers {
2145
2153
var mods1 = mods
2146
2154
if isErased then mods1 = addModifier(mods1)
2147
2155
try
2148
- commaSeparated(() => binding(mods1))
2156
+ commaSeparated(() => binding(mods1), RPAREN )
2149
2157
finally
2150
2158
accept(RPAREN )
2151
2159
else {
@@ -2376,7 +2384,7 @@ object Parsers {
2376
2384
/** ExprsInParens ::= ExprInParens {`,' ExprInParens}
2377
2385
*/
2378
2386
def exprsInParensOpt (): List [Tree ] =
2379
- if (in.token == RPAREN ) Nil else commaSeparated(exprInParens)
2387
+ if (in.token == RPAREN ) Nil else commaSeparated(exprInParens, RPAREN )
2380
2388
2381
2389
/** ParArgumentExprs ::= `(' [‘using’] [ExprsInParens] `)'
2382
2390
* | `(' [ExprsInParens `,'] PostfixExpr `*' ')'
@@ -2386,9 +2394,9 @@ object Parsers {
2386
2394
(Nil , false )
2387
2395
else if isIdent(nme.using) then
2388
2396
in.nextToken()
2389
- (commaSeparated(argumentExpr), true )
2397
+ (commaSeparated(argumentExpr, RPAREN ), true )
2390
2398
else
2391
- (commaSeparated(argumentExpr), false )
2399
+ (commaSeparated(argumentExpr, RPAREN ), false )
2392
2400
}
2393
2401
2394
2402
/** ArgumentExprs ::= ParArgumentExprs
@@ -2532,7 +2540,7 @@ object Parsers {
2532
2540
if (leading == LBRACE || in.token == CASE )
2533
2541
enumerators()
2534
2542
else {
2535
- val pats = patternsOpt()
2543
+ val pats = patternsOpt(EMPTY )
2536
2544
val pat =
2537
2545
if (in.token == RPAREN || pats.length > 1 ) {
2538
2546
wrappedEnums = false
@@ -2724,7 +2732,7 @@ object Parsers {
2724
2732
case USCORE =>
2725
2733
wildcardIdent()
2726
2734
case LPAREN =>
2727
- atSpan(in.offset) { makeTupleOrParens(inParens(patternsOpt())) }
2735
+ atSpan(in.offset) { makeTupleOrParens(inParens(patternsOpt(RPAREN ))) }
2728
2736
case QUOTE =>
2729
2737
simpleExpr(Location .InPattern )
2730
2738
case XMLSTART =>
@@ -2759,17 +2767,17 @@ object Parsers {
2759
2767
2760
2768
/** Patterns ::= Pattern [`,' Pattern]
2761
2769
*/
2762
- def patterns (location : Location = Location .InPattern ): List [Tree ] =
2763
- commaSeparated(() => pattern(location))
2770
+ def patterns (expectedEnd : Token , location : Location = Location .InPattern ): List [Tree ] =
2771
+ commaSeparated(() => pattern(location), expectedEnd )
2764
2772
2765
- def patternsOpt (location : Location = Location .InPattern ): List [Tree ] =
2766
- if (in.token == RPAREN ) Nil else patterns(location)
2773
+ def patternsOpt (expectedEnd : Token , location : Location = Location .InPattern ): List [Tree ] =
2774
+ if (in.token == RPAREN ) Nil else patterns(expectedEnd, location)
2767
2775
2768
2776
/** ArgumentPatterns ::= ‘(’ [Patterns] ‘)’
2769
2777
* | ‘(’ [Patterns ‘,’] PatVar ‘*’ ‘)’
2770
2778
*/
2771
2779
def argumentPatterns (): List [Tree ] =
2772
- inParens(patternsOpt(Location .InPatternArgs ))
2780
+ inParens(patternsOpt(RPAREN , Location .InPatternArgs ))
2773
2781
2774
2782
/* -------- MODIFIERS and ANNOTATIONS ------------------------------------------- */
2775
2783
@@ -2950,7 +2958,7 @@ object Parsers {
2950
2958
TypeDef (name, lambdaAbstract(hkparams, bounds)).withMods(mods)
2951
2959
}
2952
2960
}
2953
- commaSeparated(() => typeParam())
2961
+ commaSeparated(() => typeParam(), RBRACKET )
2954
2962
}
2955
2963
2956
2964
def typeParamClauseOpt (ownerKind : ParamOwner .Value ): List [TypeDef ] =
@@ -2959,7 +2967,7 @@ object Parsers {
2959
2967
/** ContextTypes ::= FunArgType {‘,’ FunArgType}
2960
2968
*/
2961
2969
def contextTypes (ofClass : Boolean , nparams : Int , impliedMods : Modifiers ): List [ValDef ] =
2962
- val tps = commaSeparated(funArgType)
2970
+ val tps = commaSeparated(funArgType, RPAREN )
2963
2971
var counter = nparams
2964
2972
def nextIdx = { counter += 1 ; counter }
2965
2973
val paramFlags = if ofClass then Private | Local | ParamAccessor else Param
@@ -3063,7 +3071,7 @@ object Parsers {
3063
3071
! impliedMods.is(Given )
3064
3072
|| startParamTokens.contains(in.token)
3065
3073
|| isIdent && (in.name == nme.inline || in.lookahead.isColon())
3066
- if isParams then commaSeparated(() => param())
3074
+ if isParams then commaSeparated(() => param(), RPAREN )
3067
3075
else contextTypes(ofClass, nparams, impliedMods)
3068
3076
checkVarArgsRules(clause)
3069
3077
clause
@@ -3755,7 +3763,7 @@ object Parsers {
3755
3763
val derived =
3756
3764
if (isIdent(nme.derives )) {
3757
3765
in.nextToken()
3758
- tokenSeparated( COMMA , () => convertToTypeId(qualId()))
3766
+ commaSeparated( () => convertToTypeId(qualId()))
3759
3767
}
3760
3768
else Nil
3761
3769
possibleTemplateStart()
0 commit comments