Skip to content

Commit

Permalink
More uniformity for the parser.
Browse files Browse the repository at this point in the history
Type application and operator notation could not formerly be
mixed.  Now they can, as the grammar has always suggested.
  • Loading branch information
paulp committed Mar 16, 2012
1 parent acb2c85 commit f987afe
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 14 deletions.
33 changes: 24 additions & 9 deletions src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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)
}
}
}
Expand Down Expand Up @@ -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()
}
Expand Down Expand Up @@ -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()
Expand Down
20 changes: 15 additions & 5 deletions src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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) =>
Expand All @@ -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)
}
}
Expand Down
12 changes: 12 additions & 0 deletions test/files/pos/dotless-targs.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class A {
def fn1 = List apply 1
def fn2 = List apply[Int] 2

def f1 = "f1" isInstanceOf[String]

def g1 = "g1" toList
def g2 = "g2" toList 2
def g3 = "g3" apply 3

def h1 = List apply[List[Int]] (List(1), List(2)) mapConserve[List[Any]] (x => x)
}

0 comments on commit f987afe

Please sign in to comment.