@@ -502,7 +502,8 @@ object Parsers {
502
502
recur(top)
503
503
}
504
504
505
- /** operand { infixop operand} [postfixop],
505
+ /** operand { infixop operand | ‘with’ (operand | ParArgumentExprs) } [postfixop],
506
+ *
506
507
* respecting rules of associativity and precedence.
507
508
* @param notAnOperator a token that does not count as operator.
508
509
* @param maybePostfix postfix operators are allowed.
@@ -513,23 +514,37 @@ object Parsers {
513
514
isOperator : => Boolean = true ,
514
515
maybePostfix : Boolean = false ): Tree = {
515
516
val base = opStack
516
- var top = first
517
- while (isIdent && isOperator) {
518
- val op = if (isType) typeIdent() else termIdent()
519
- top = reduceStack(base, top, precedence(op.name), isLeftAssoc(op.name), op.name, isType)
520
- opStack = OpInfo (top, op, in.offset) :: opStack
521
- newLineOptWhenFollowing(canStartOperand)
522
- if (maybePostfix && ! canStartOperand(in.token)) {
523
- val topInfo = opStack.head
524
- opStack = opStack.tail
525
- val od = reduceStack(base, topInfo.operand, 0 , true , in.name, isType)
526
- return atPos(startOffset(od), topInfo.offset) {
527
- PostfixOp (od, topInfo.operator)
517
+
518
+ def recur (top : Tree ): Tree =
519
+ if (isIdent && isOperator) {
520
+ val op = if (isType) typeIdent() else termIdent()
521
+ val top1 = reduceStack(base, top, precedence(op.name), isLeftAssoc(op.name), op.name, isType)
522
+ opStack = OpInfo (top1, op, in.offset) :: opStack
523
+ newLineOptWhenFollowing(canStartOperand)
524
+ if (maybePostfix && ! canStartOperand(in.token)) {
525
+ val topInfo = opStack.head
526
+ opStack = opStack.tail
527
+ val od = reduceStack(base, topInfo.operand, 0 , true , in.name, isType)
528
+ atPos(startOffset(od), topInfo.offset) {
529
+ PostfixOp (od, topInfo.operator)
530
+ }
528
531
}
532
+ else recur(operand())
529
533
}
530
- top = operand()
531
- }
532
- reduceStack(base, top, 0 , true , in.name, isType)
534
+ else if (in.token == WITH ) {
535
+ val top1 = reduceStack(base, top, minInfixPrec, leftAssoc = true , nme.WITHkw , isType)
536
+ assert(opStack `eq` base)
537
+ val app = atPos(startOffset(top1), in.offset) {
538
+ in.nextToken()
539
+ val args = if (in.token == LPAREN ) parArgumentExprs() else operand() :: Nil
540
+ Apply (top, args)
541
+ }
542
+ app.pushAttachment(WithApply , ())
543
+ recur(app)
544
+ }
545
+ else reduceStack(base, top, minPrec, leftAssoc = true , in.name, isType)
546
+
547
+ recur(first)
533
548
}
534
549
535
550
/* -------- IDENTIFIERS AND LITERALS ------------------------------------------- */
@@ -1340,6 +1355,7 @@ object Parsers {
1340
1355
/** PostfixExpr ::= InfixExpr [id [nl]]
1341
1356
* InfixExpr ::= PrefixExpr
1342
1357
* | InfixExpr id [nl] InfixExpr
1358
+ * | InfixExpr ‘with’ (InfixExpr | ParArgumentExprs)
1343
1359
*/
1344
1360
def postfixExpr (): Tree =
1345
1361
infixOps(prefixExpr(), canStartExpressionTokens, prefixExpr, maybePostfix = true )
@@ -1917,27 +1933,27 @@ object Parsers {
1917
1933
def typeParamClauseOpt (ownerKind : ParamOwner .Value ): List [TypeDef ] =
1918
1934
if (in.token == LBRACKET ) typeParamClause(ownerKind) else Nil
1919
1935
1920
- /** ClsParamClauses ::= {ClsParamClause} [[nl] `(' [FunArgMods] ClsParams `)']
1921
- * ClsParamClause ::= [nl] `(' [`erased'] [ClsParams] ')'
1936
+ /** ClsParamClause ::= [nl | ‘with’] `(' [FunArgMods] [ClsParams] ')'
1922
1937
* ClsParams ::= ClsParam {`' ClsParam}
1923
1938
* ClsParam ::= {Annotation} [{Modifier} (`val' | `var') | `inline'] Param
1924
- * DefParamClauses ::= {DefParamClause} [[nl] `(' [FunArgMods] DefParams `)']
1925
- * DefParamClause ::= [nl] `(' [DefParams] ')'
1939
+ * DefParamClause ::= [nl | ‘with’] `(' [FunArgMods] [DefParams] ')'
1926
1940
* ExtParamClause ::= [nl] ‘(’ ‘this’ DefParam ‘)’
1927
1941
* DefParams ::= DefParam {`,' DefParam}
1928
1942
* DefParam ::= {Annotation} [`inline'] Param
1929
1943
* Param ::= id `:' ParamType [`=' Expr]
1930
1944
*
1931
- * @return The parameter definitions, and whether leading parameter is tagged `this`
1945
+ * @return the list of parameter definitions, and whether this is an extension clause
1932
1946
*/
1933
- def paramClauses (ofClass : Boolean = false , ofCaseClass : Boolean = false , ofRegularMethod : Boolean = false ): (List [List [ValDef ]], Boolean ) = {
1934
- var imods : Modifiers = EmptyModifiers
1947
+ def paramClause (ofClass : Boolean ,
1948
+ ofCaseClass : Boolean ,
1949
+ ofRegularMethod : Boolean ,
1950
+ firstClause : Boolean ,
1951
+ impliedMods : Modifiers ): (List [ValDef ], Boolean ) = {
1935
1952
var implicitOffset = - 1 // use once
1936
- var firstClause = true
1937
- var isExtension = false
1938
- def param (): ValDef = {
1953
+
1954
+ def param (impliedMods : Modifiers ): ValDef = {
1939
1955
val start = in.offset
1940
- var mods = annotsAsMods( )
1956
+ var mods = impliedMods.withAnnotations(annotations() )
1941
1957
if (ofClass) {
1942
1958
mods = addFlag(modifiers(start = mods), ParamAccessor )
1943
1959
mods =
@@ -1951,7 +1967,7 @@ object Parsers {
1951
1967
addMod(mods, mod)
1952
1968
}
1953
1969
else {
1954
- if (! (mods.flags &~ (ParamAccessor | Inline )).isEmpty)
1970
+ if (! (mods.flags &~ (ParamAccessor | Inline | impliedMods.flags )).isEmpty)
1955
1971
syntaxError(" `val' or `var' expected" )
1956
1972
if (firstClause && ofCaseClass) mods
1957
1973
else mods | PrivateLocal
@@ -1975,46 +1991,64 @@ object Parsers {
1975
1991
mods = mods.withPos(mods.pos.union(Position (implicitOffset, implicitOffset)))
1976
1992
implicitOffset = - 1
1977
1993
}
1978
- for (imod <- imods.mods) mods = addMod(mods, imod)
1979
1994
ValDef (name, tpt, default).withMods(mods)
1980
1995
}
1981
1996
}
1982
- def paramClause (): List [ValDef ] = inParens {
1983
- if (in.token == RPAREN ) Nil
1997
+
1998
+ // begin paramClause
1999
+ inParens {
2000
+ if (in.token == RPAREN )
2001
+ (Nil , false )
1984
2002
else if (in.token == THIS && firstClause && ofRegularMethod) {
1985
2003
in.nextToken()
1986
- isExtension = true
1987
- param() :: Nil
2004
+ (param(impliedMods) :: Nil , true )
1988
2005
}
1989
2006
else {
1990
- def funArgMods (): Unit = {
1991
- if (in.token == IMPLICIT ) {
2007
+ def funArgMods (mods : Modifiers ): Modifiers =
2008
+ if (in.token == IMPLICIT && ! impliedMods.is( Contextual ) ) {
1992
2009
implicitOffset = in.offset
1993
- imods = addMod(imods, atPos(accept(IMPLICIT )) { Mod .Implicit () })
1994
- funArgMods()
1995
- } else if (in.token == ERASED ) {
1996
- imods = addMod(imods, atPos(accept(ERASED )) { Mod .Erased () })
1997
- funArgMods()
2010
+ funArgMods(addMod(mods, atPos(accept(IMPLICIT )) { Mod .Implicit () }))
1998
2011
}
1999
- }
2000
- funArgMods()
2012
+ else if (in.token == ERASED )
2013
+ funArgMods(addMod(mods, atPos(accept(ERASED )) { Mod .Erased () }))
2014
+ else mods
2001
2015
2002
- val clause = commaSeparated(() => param())
2016
+ val impliedMods1 = funArgMods(impliedMods)
2017
+ val clause = commaSeparated(() => param(impliedMods1))
2003
2018
checkVarArgsRules(clause)
2004
- clause
2019
+ ( clause, false )
2005
2020
}
2006
2021
}
2007
- def clauses (): List [List [ValDef ]] = {
2008
- newLineOptWhenFollowedBy(LPAREN )
2009
- if (in.token == LPAREN ) {
2010
- imods = EmptyModifiers
2011
- paramClause() :: {
2012
- firstClause = false
2013
- if (imods is Implicit ) Nil else clauses()
2022
+ }
2023
+
2024
+ /** ClsParamClauses ::= {ClsParamClause}
2025
+ * DefParamClauses ::= {DefParamClause}
2026
+ *
2027
+ * @return The parameter definitions, and whether leading parameter is tagged `this`
2028
+ */
2029
+ def paramClauses (ofClass : Boolean = false ,
2030
+ ofCaseClass : Boolean = false ,
2031
+ ofRegularMethod : Boolean = false ,
2032
+ ofWitness : Boolean = false ): (List [List [ValDef ]], Boolean ) = {
2033
+ def recur (firstClause : Boolean ): (List [List [ValDef ]], Boolean ) = {
2034
+ val impliedMods =
2035
+ if (in.token == WITH ) {
2036
+ in.nextToken()
2037
+ Modifiers (Contextual | Implicit )
2014
2038
}
2015
- } else Nil
2039
+ else EmptyModifiers
2040
+ newLineOptWhenFollowedBy(LPAREN )
2041
+ if (impliedMods.is(Contextual ) || in.token == LPAREN && ! ofWitness) {
2042
+ val (params, isExtension) =
2043
+ paramClause(ofClass, ofCaseClass, ofRegularMethod, firstClause, impliedMods)
2044
+ val lastClause =
2045
+ params.nonEmpty && params.head.mods.flags.is(Implicit , butNot = Contextual )
2046
+ val paramss = if (lastClause) Nil else recur(firstClause = false )._1
2047
+ (params :: paramss, isExtension)
2048
+ }
2049
+ else (Nil , false )
2016
2050
}
2017
- (clauses(), isExtension )
2051
+ recur(firstClause = true )
2018
2052
}
2019
2053
2020
2054
/* -------- DEFS ------------------------------------------- */
@@ -2403,15 +2437,15 @@ object Parsers {
2403
2437
Template (constr, parents, EmptyValDef , Nil )
2404
2438
}
2405
2439
2406
- /** WitnessDef ::= [id] [DefTypeParamClause] [‘for’ [ConstrApps]] TemplateBody
2407
- * | id [DefTypeParamClause] ‘for’ Type [‘=’ Expr]
2440
+ /** WitnessDef ::= [id] WitnessParams [‘for’ ConstrApps] [TemplateBody]
2441
+ * | id WitnessParams ‘:’ Type ‘=’ Expr
2442
+ * | id ‘=’ Expr
2443
+ * WitnessParams ::= [DefTypeParamClause] {‘with’ ‘(’ [DefParams] ‘)}
2408
2444
*/
2409
2445
def witnessDef (start : Offset , mods : Modifiers , witnessMod : Mod ) = atPos(start, nameStart) {
2410
2446
val name = if (isIdent) ident() else EmptyTermName
2411
2447
val tparams = typeParamClauseOpt(ParamOwner .Def )
2412
- val (vparamss, _) = paramClauses()
2413
- for (vparams <- vparamss; vparam <- vparams)
2414
- if (! vparam.mods.is(Implicit )) syntaxError(" witness can only have implicit parameters" , vparam.pos)
2448
+ val (vparamss, _) = paramClauses(ofWitness = true )
2415
2449
val parents =
2416
2450
if (in.token == FOR ) {
2417
2451
in.nextToken()
0 commit comments