diff options
Diffstat (limited to 'src/compiler/scala/tools/nsc/ast/parser/Parsers.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/parser/Parsers.scala | 148 |
1 files changed, 93 insertions, 55 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index f40a759dc3..454eed1755 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -74,6 +74,8 @@ trait Parsers requires SyntaxAnalyzer { def freshName(prefix: String): Name = unit.fresh.newName(prefix) } + var implicitClassViews: List[Tree] = Nil + /** this is the general parse method */ def parse(): Tree = { @@ -928,7 +930,7 @@ trait Parsers requires SyntaxAnalyzer { /** PostfixExpr ::= [`.'] InfixExpr [Id [NewLine]] * InfixExpr ::= PrefixExpr - * | InfixExpr Id [NewLine] InfixExpr + * | InfixExpr Id [NewLine] (InfixExpr | ArgumentExprs) */ def postfixExpr(): Tree = { val base = opstack @@ -936,11 +938,12 @@ trait Parsers requires SyntaxAnalyzer { while (isIdent) { top = reduceStack( true, base, top, precedence(in.name), treeInfo.isLeftAssoc(in.name)) - opstack = OpInfo(top, in.name, in.currentPos) :: opstack + val op = in.name + opstack = OpInfo(top, op, in.currentPos) :: opstack ident() newLineOptWhenFollowing(isExprIntroToken) if (isExprIntro) { - top = prefixExpr() + top = secondInfixOperandExpr(op) } else { val topinfo = opstack.head opstack = opstack.tail @@ -952,6 +955,17 @@ trait Parsers requires SyntaxAnalyzer { reduceStack(true, base, top, 0, true) } + def secondInfixOperandExpr(op: Name): Tree = + if (in.token == LPAREN && treeInfo.isLeftAssoc(op)) { + val pos = in.currentPos + val args = argumentExprs() + if (args.isEmpty) simpleExprRest(Literal(()) setPos pos, false) + else if (args.tail.isEmpty) simpleExprRest(args.head, false) + else ArgumentExprs(args) + } else { + prefixExpr() + } + /** PrefixExpr ::= [`-' | `+' | `~' | `!' | `&' | `/'] SimpleExpr */ def prefixExpr(): Tree = @@ -1052,25 +1066,23 @@ trait Parsers requires SyntaxAnalyzer { syntaxError("illegal start of simple expression", true) t = errorTermTree } - while (true) { - in.token match { - case DOT => - t = atPos(in.skipToken()) { selector(t) } - case LBRACKET => - t match { - case Ident(_) | Select(_, _) => - t = atPos(in.currentPos) { TypeApply(t, typeArgs(false)) } - case _ => - return t - } - case LPAREN | LBRACE if (!isNew) => - t = atPos(in.currentPos) { Apply(t, argumentExprs()) } + simpleExprRest(t, isNew) + } + + def simpleExprRest(t: Tree, isNew: boolean): Tree = in.token match { + case DOT => + simpleExprRest(atPos(in.skipToken()) { selector(t) }, false) + case LBRACKET => + t match { + case Ident(_) | Select(_, _) => + simpleExprRest(atPos(in.currentPos) { TypeApply(t, typeArgs(false)) }, false) case _ => - return t + t } - isNew = false - } - null;//dummy + case LPAREN | LBRACE if (!isNew) => + simpleExprRest(atPos(in.currentPos) { Apply(t, argumentExprs()) }, false) + case _ => + t } /** ArgumentExprs ::= `(' [Exprs] `)' @@ -1244,13 +1256,25 @@ trait Parsers requires SyntaxAnalyzer { while (isIdent && in.name != BAR) { top = reduceStack( false, base, top, precedence(in.name), treeInfo.isLeftAssoc(in.name)) - opstack = OpInfo(top, in.name, in.currentPos) :: opstack + val op = in.name + opstack = OpInfo(top, op, in.currentPos) :: opstack ident() - top = simplePattern(seqOK) + top = secondInfixOperandPattern(op, seqOK) } reduceStack(false, base, top, 0, true) } + def secondInfixOperandPattern(op: Name, seqOK: boolean): Tree = + if (in.token == LPAREN && treeInfo.isLeftAssoc(op)) { + val pos = in.currentPos + val args = argumentPatterns() + if (args.isEmpty) Literal(()) setPos pos + else if (args.tail.isEmpty) args.head + else ArgumentExprs(args) + } else { + simplePattern(seqOK) + } + /** SimplePattern ::= varid * | `_' * | literal @@ -1289,22 +1313,9 @@ trait Parsers requires SyntaxAnalyzer { } else */ if (in.token == LPAREN) { - atPos(in.skipToken()) { - val ps = if (in.token == RPAREN) List() else patterns(true, false) - accept(RPAREN) - Apply(convertToTypeId(t), ps) - } + atPos(in.currentPos) { Apply(convertToTypeId(t), argumentPatterns()) } } else if (in.token == LBRACE) { - in.nextToken() - val ts = if (in.token == RBRACE) List() - else { - val p1 = pattern() - accept(COMMA) - p1 :: (if (in.token == RBRACE) List() else patterns(false, true)) - } - checkSize("tuple elements", ts.length, definitions.MaxTupleArity) - accept(RBRACE) - makeTupleTerm(ts, false) + atPos(in.currentPos) { Apply(convertToTypeId(t), List(tuplePattern())) } } else t case USCORE => atPos(in.skipToken()) { Ident(nme.WILDCARD) } @@ -1319,6 +1330,8 @@ trait Parsers requires SyntaxAnalyzer { else Literal(()).setPos(pos) accept(RPAREN) p + case LBRACE => + tuplePattern() case XMLSTART => xmlp.xLiteralPattern case _ => @@ -1329,6 +1342,26 @@ trait Parsers requires SyntaxAnalyzer { errorPatternTree } + def argumentPatterns(): List[Tree] = { + accept(LPAREN) + val ps = if (in.token == RPAREN) List() else patterns(true, false) + accept(RPAREN) + ps + } + + def tuplePattern(): Tree = { + in.nextToken() + val ts = if (in.token == RBRACE) List() + else { + val p1 = pattern() + accept(COMMA) + p1 :: (if (in.token == RBRACE) List() else patterns(false, true)) + } + checkSize("tuple elements", ts.length, definitions.MaxTupleArity) + accept(RBRACE) + makeTuplePattern(ts) + } + ////////// MODIFIERS //////////////////////////////////////////////////////////// /** Modifiers ::= {Modifier} @@ -1511,7 +1544,7 @@ trait Parsers requires SyntaxAnalyzer { * FunTypeParamClauseOpt ::= [[NewLine] `[' TypeParam {`,' TypeParam} `]'] * TypeParam ::= Id TypeBounds [<% Type] */ - def typeParamClauseOpt(owner: Name, implicitViews: ListBuffer[Tree]): List[AbsTypeDef] = { + def typeParamClauseOpt(owner: Name, implicitViewBuf: ListBuffer[Tree]): List[AbsTypeDef] = { def typeParam(): AbsTypeDef = { var mods = Modifiers(Flags.PARAM) if (owner.isTypeName && isIdent) { @@ -1525,8 +1558,8 @@ trait Parsers requires SyntaxAnalyzer { } val pname = ident() val param = atPos(in.currentPos) { typeBounds(mods, pname) } - if (in.token == VIEWBOUND && (implicitViews ne null)) - implicitViews += atPos(in.skipToken()) { + if (in.token == VIEWBOUND && (implicitViewBuf ne null)) + implicitViewBuf += atPos(in.skipToken()) { makeFunctionTypeTree(List(Ident(pname.toTypeName)), typ()) } param @@ -1743,16 +1776,16 @@ trait Parsers requires SyntaxAnalyzer { atPos(in.skipToken()) { if (in.token == THIS) { in.nextToken() - val vparamss = paramClauses(nme.CONSTRUCTOR, List(), false) - val rhs = if (in.token == LBRACE) constrBlock() - else { accept(EQUALS); constrExpr() } + val vparamss = paramClauses(nme.CONSTRUCTOR, implicitClassViews map (.duplicate), false) + val rhs = if (in.token == LBRACE) constrBlock(vparamss) + else { accept(EQUALS); constrExpr(vparamss) } DefDef(mods, nme.CONSTRUCTOR, List(), vparamss, TypeTree(), rhs) } else { var newmods = mods val name = ident() - val implicitViews = new ListBuffer[Tree] - val tparams = typeParamClauseOpt(name, implicitViews) - val vparamss = paramClauses(name, implicitViews.toList, false) + val implicitViewBuf = new ListBuffer[Tree] + val tparams = typeParamClauseOpt(name, implicitViewBuf) + val vparamss = paramClauses(name, implicitViewBuf.toList, false) var restype = typedOpt() val rhs = if (in.token == SEMI || in.token == NEWLINE || in.token == RBRACE) { @@ -1770,24 +1803,25 @@ trait Parsers requires SyntaxAnalyzer { /** ConstrExpr ::= SelfInvocation * | ConstrBlock */ - def constrExpr(): Tree = - if (in.token == LBRACE) constrBlock() else selfInvocation() + def constrExpr(vparamss: List[List[ValDef]]): Tree = + if (in.token == LBRACE) constrBlock(vparamss) else selfInvocation(vparamss) /** SelfInvocation ::= this ArgumentExprs {ArgumentExprs} */ - def selfInvocation(): Tree = + def selfInvocation(vparamss: List[List[ValDef]]): Tree = atPos(accept(THIS)) { var t = Apply(Ident(nme.CONSTRUCTOR), argumentExprs()) while (in.token == LPAREN) t = Apply(t, argumentExprs()) + if (!implicitClassViews.isEmpty) t = Apply(t, vparamss.last.map(vd => Ident(vd.name))) t } /** ConstrBlock ::= `{' SelfInvocation {StatementSeparator BlockStat} `}' */ - def constrBlock(): Tree = + def constrBlock(vparamss: List[List[ValDef]]): Tree = atPos(in.skipToken()) { val statlist = new ListBuffer[Tree] - statlist += selfInvocation() + statlist += selfInvocation(vparamss) val stats = if (in.token == SEMI || in.token == NEWLINE) { in.nextToken(); blockStatSeq(statlist) @@ -1844,17 +1878,21 @@ trait Parsers requires SyntaxAnalyzer { def classDef(mods: Modifiers): ClassDef = atPos(in.skipToken()) { val name = ident().toTypeName - val implicitViews = new ListBuffer[Tree] - val tparams = typeParamClauseOpt(name, implicitViews) + val savedViews = implicitClassViews + val implicitViewBuf = new ListBuffer[Tree] + val tparams = typeParamClauseOpt(name, implicitViewBuf) + implicitClassViews = implicitViewBuf.toList //if (mods.hasFlag(Flags.CASE) && in.token != LPAREN) accept(LPAREN) val vparamss = if (mods.hasFlag(Flags.TRAIT)) List() - else paramClauses(name, implicitViews.toList, mods.hasFlag(Flags.CASE)) + else paramClauses(name, implicitClassViews, mods.hasFlag(Flags.CASE)) val thistpe = requiresTypeOpt() val template = classTemplate(mods, name, vparamss) val mods1 = if (mods.hasFlag(Flags.TRAIT) && (template.body forall treeInfo.isInterfaceMember)) mods | Flags.INTERFACE else mods - ClassDef(mods1, name, tparams, thistpe, template) + val result = ClassDef(mods1, name, tparams, thistpe, template) + implicitClassViews = savedViews + result } /** ObjectDef ::= Id ClassTemplate |