summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-03-16 00:46:21 -0700
committerPaul Phillips <paulp@improving.org>2012-03-16 02:01:25 -0700
commitf987afe55e6d4f71c7e9ad10d1ca9f6120dc1132 (patch)
tree64eec0878753d404b9289cd1d1d44ed6259c6910 /src
parentacb2c851720141982514b11b4b34ba68dc868bf2 (diff)
downloadscala-f987afe55e6d4f71c7e9ad10d1ca9f6120dc1132.tar.gz
scala-f987afe55e6d4f71c7e9ad10d1ca9f6120dc1132.tar.bz2
scala-f987afe55e6d4f71c7e9ad10d1ca9f6120dc1132.zip
More uniformity for the parser.
Type application and operator notation could not formerly be mixed. Now they can, as the grammar has always suggested.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala33
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala20
2 files changed, 39 insertions, 14 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index ccebcfa54d..cd64c49b47 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -126,7 +126,7 @@ self =>
val global: Global
import global._
- case class OpInfo(operand: Tree, operator: Name, offset: Offset)
+ case class OpInfo(operand: Tree, operator: Name, targs: List[Tree], offset: Offset)
class SourceFileParser(val source: SourceFile) extends Parser {
@@ -789,7 +789,7 @@ self =>
val rPos = top.pos
val end = if (rPos.isDefined) rPos.endOrPoint else opPos.endOrPoint
top = atPos(start, opinfo.offset, end) {
- makeBinop(isExpr, opinfo.operand, opinfo.operator, top, opPos)
+ makeBinop(isExpr, opinfo.operand, opinfo.operator, top, opPos, opinfo.targs)
}
}
top
@@ -1440,6 +1440,17 @@ self =>
}
}
+ def advanceStack(base: List[OpInfo], top: Tree): Tree = {
+ val newTop = reduceStack(true, base, top, precedence(in.name), treeInfo.isLeftAssoc(in.name))
+ val op = in.name
+ val pos = in.offset
+ ident()
+ val targs = if (in.token == LBRACKET) exprTypeArgs() else Nil
+ opstack ::= OpInfo(newTop, op, targs, pos)
+
+ newTop
+ }
+
/** {{{
* PostfixExpr ::= InfixExpr [Id [nl]]
* InfixExpr ::= PrefixExpr
@@ -1451,22 +1462,21 @@ self =>
var top = prefixExpr()
while (isIdent) {
- top = reduceStack(true, base, top, precedence(in.name), treeInfo.isLeftAssoc(in.name))
- val op = in.name
- opstack = OpInfo(top, op, in.offset) :: opstack
- ident()
+ top = advanceStack(base, top)
newLineOptWhenFollowing(isExprIntroToken)
+
if (isExprIntro) {
val next = prefixExpr()
if (next == EmptyTree)
return reduceStack(true, base, top, 0, true)
top = next
- } else {
+ }
+ else {
val topinfo = opstack.head
opstack = opstack.tail
val od = stripParens(reduceStack(true, base, topinfo.operand, 0, true))
return atPos(od.pos.startOrPoint, topinfo.offset) {
- Select(od, topinfo.operator.encode)
+ applyTypeArgs(Select(od, topinfo.operator.encode), topinfo.targs)
}
}
}
@@ -1806,7 +1816,7 @@ self =>
top = reduceStack(
false, base, top, precedence(in.name), treeInfo.isLeftAssoc(in.name))
val op = in.name
- opstack = OpInfo(top, op, in.offset) :: opstack
+ opstack = OpInfo(top, op, Nil, in.offset) :: opstack
ident()
top = simplePattern()
}
@@ -1896,6 +1906,11 @@ self =>
def exprTypeArgs() = outPattern.typeArgs()
def exprSimpleType() = outPattern.simpleType()
+ def applyTypeArgs(sel: Tree, targs: List[Tree]): Tree = (
+ if (targs.isEmpty) sel
+ else atPos(sel.pos)(TypeApply(sel, targs))
+ )
+
/** Default entry points into some pattern contexts. */
def pattern(): Tree = noSeq.pattern()
def patterns(): List[Tree] = noSeq.patterns()
diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
index 661f893c59..87251b4cc9 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -174,7 +174,14 @@ abstract class TreeBuilder {
}
/** Create tree representing (unencoded) binary operation expression or pattern. */
- def makeBinop(isExpr: Boolean, left: Tree, op: TermName, right: Tree, opPos: Position): Tree = {
+ def makeBinop(isExpr: Boolean, left: Tree, op: TermName, right: Tree, opPos: Position, targs: List[Tree] = Nil): Tree = {
+ require(isExpr || targs.isEmpty, ((left, op, targs, right)))
+
+ def mkSel(t: Tree) = {
+ val sel = atPos(opPos union t.pos)(Select(stripParens(t), op.encode))
+ if (targs.isEmpty) sel else atPos(left.pos)(TypeApply(sel, targs))
+ }
+
def mkNamed(args: List[Tree]) =
if (isExpr) args map {
case a @ Assign(id @ Ident(name), rhs) =>
@@ -187,14 +194,17 @@ abstract class TreeBuilder {
}
if (isExpr) {
if (treeInfo.isLeftAssoc(op)) {
- Apply(atPos(opPos union left.pos) { Select(stripParens(left), op.encode) }, arguments)
- } else {
+ Apply(mkSel(left), arguments)
+ }
+ else {
val x = freshTermName()
Block(
List(ValDef(Modifiers(SYNTHETIC), x, TypeTree(), stripParens(left))),
- Apply(atPos(opPos union right.pos) { Select(stripParens(right), op.encode) }, List(Ident(x))))
+ Apply(mkSel(right), List(Ident(x)))
+ )
}
- } else {
+ }
+ else {
Apply(Ident(op.encode), stripParens(left) :: arguments)
}
}