summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2009-05-19 16:25:32 +0000
committerMartin Odersky <odersky@gmail.com>2009-05-19 16:25:32 +0000
commitb3ce4c4f7d2e2016d7b71bea2df7aa6dc75bc3d5 (patch)
tree6920117580b355522f14bc168de0463f8677a3aa /src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
parent14fb2dfadd8ef9b433fed2599c1b32049d4c90e2 (diff)
downloadscala-b3ce4c4f7d2e2016d7b71bea2df7aa6dc75bc3d5.tar.gz
scala-b3ce4c4f7d2e2016d7b71bea2df7aa6dc75bc3d5.tar.bz2
scala-b3ce4c4f7d2e2016d7b71bea2df7aa6dc75bc3d5.zip
small modifications to collections.
Diffstat (limited to 'src/compiler/scala/tools/nsc/ast/parser/Parsers.scala')
-rwxr-xr-xsrc/compiler/scala/tools/nsc/ast/parser/Parsers.scala1978
1 files changed, 948 insertions, 1030 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 1fc1382ee8..6c795b66d0 100755
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -52,13 +52,12 @@ import Tokens._
*/
trait Parsers extends Scanners with MarkupParsers {
self =>
- val global : Global
+ val global: Global
import global._
private val glob: global.type = global
- import global.posAssigner.atPos
- case class OpInfo(operand: Tree, operator: Name, pos: Int)
+ case class OpInfo(operand: Tree, operator: Name, offset: Offset)
class UnitParser(val unit: global.CompilationUnit) extends Parser {
val in = new UnitScanner(unit)
@@ -67,17 +66,20 @@ self =>
def freshName(pos: Position, prefix: String): Name =
unit.fresh.newName(pos, prefix)
- implicit def i2p(offset: Int): Position = new OffsetPosition(unit.source,offset)
+ def o2p(offset: Int): Position = new OffsetPosition(unit.source,offset)
+ def r2p(start: Int, mid: Int, end: Int): Position = rangePos(unit.source, start, mid, end)
- def warning(pos: Int, msg: String) { unit.warning(pos, msg) }
+ def warning(offset: Int, msg: String) { unit.warning(o2p(offset), msg) }
def incompleteInputError(msg: String) {
- unit.incompleteInputError(unit.source.asInstanceOf[BatchSourceFile].content.length - 1, msg)
+ unit.incompleteInputError(o2p(unit.source.asInstanceOf[BatchSourceFile].content.length - 1), msg)
}
- def deprecationWarning(pos: Int, msg: String) {
- unit.deprecationWarning(pos, msg)
+
+ def deprecationWarning(offset: Int, msg: String) {
+ unit.deprecationWarning(o2p(offset), msg)
}
- def syntaxError(pos: Int, msg: String) { unit.error(pos, msg) }
+
+ def syntaxError(offset: Int, msg: String) { unit.error(o2p(offset), msg) }
/** the markup parser */
lazy val xmlp = new MarkupParser(this, true)
@@ -86,61 +88,38 @@ self =>
val global: self.global.type = self.global
def freshName(prefix: String): Name = UnitParser.this.freshName(NoPosition, prefix)
}
+
def xmlLiteral : Tree = xmlp.xLiteral
- def xmlLiteralPattern : Tree = xmlp.xLiteralPattern
- }
- class ScanOnly(unit: global.CompilationUnit) extends UnitParser(unit) {
- override def parse(): Tree = {
- while (in.token != EOF) in.nextToken
- null
- }
+ def xmlLiteralPattern : Tree = xmlp.xLiteralPattern
}
- // parser constants, here so they don't pollute parser debug listing
- private object ParserConfiguration {
- final val Local = 0
- final val InBlock = 1
- final val InTemplate = 2
- final val MINUS: Name = "-"
- final val PLUS : Name = "+"
- final val BANG : Name = "!"
- final val TILDE: Name = "~"
- final val AMP : Name = "&"
- final val SLASH: Name = "/"
- final val STAR : Name = "*"
- final val BAR : Name = "|"
- final val LT : Name = "<"
- }
+ final val Local = 0
+ final val InBlock = 1
+ final val InTemplate = 2
+ final val MINUS: Name = "-"
+ final val PLUS : Name = "+"
+ final val BANG : Name = "!"
+ final val TILDE: Name = "~"
+ final val AMP : Name = "&"
+ final val SLASH: Name = "/"
+ final val STAR : Name = "*"
+ final val BAR : Name = "|"
+ final val LT : Name = "<"
abstract class Parser {
- ParserConfiguration.hashCode
- import ParserConfiguration._
val in: Scanner
//val unit : CompilationUnit
//import in.ScanPosition
- protected def freshName(pos: Position, prefix: String): Name
- protected def posToReport: Int = in.offset
-
- protected implicit def i2p(offset: Int): Position
+ def freshName(pos: Position, prefix: String): Name
+ def o2p(offset: Int): Position
+ def r2p(start: Int, mid: Int, end: Int): Position
//private implicit def p2i(pos: Position) = pos.offset.get
- private def inToken = in.token
- private def inSkipToken = in.skipToken()
- private def inNextToken = in.nextToken()
- private def inCurrentPos = in.offset
- private def inNextTokenCode : Int = in.next.token
- private def inName = in.name
- private def charVal = in.charVal
- private def intVal(isNegated: Boolean) = in.intVal(isNegated).asInstanceOf[Int]
- private def longVal(isNegated: Boolean) = in.intVal(isNegated)
- private def floatVal(isNegated: Boolean) = in.floatVal(isNegated).asInstanceOf[Float]
- private def doubleVal(isNegated: Boolean) = in.floatVal(isNegated)
- private def stringVal = in.strVal
-
/** whether a non-continuable syntax error has been seen */
//private var syntaxErrorSeen = false
- private var lastErrorPos : Int = -1
+
+ private var lastErrorOffset : Int = -1
object treeBuilder extends TreeBuilder {
val global: self.global.type = self.global
@@ -203,20 +182,27 @@ self =>
placeholderTypes = List()
var t = op
if (!placeholderTypes.isEmpty && t.isInstanceOf[AppliedTypeTree]) {
- t = ExistentialTypeTree(t, placeholderTypes.reverse)
+ t = atPos(t.pos) { ExistentialTypeTree(t, placeholderTypes.reverse) }
placeholderTypes = List()
}
placeholderTypes = placeholderTypes ::: savedPlaceholderTypes
t
}
+ def isWildcard(t: Tree): Boolean = t match {
+ case Ident(name1) => !placeholderParams.isEmpty && name1 == placeholderParams.head.name
+ case Typed(t1, _) => isWildcard(t1)
+ case Annotated(t1, _) => isWildcard(t1)
+ case _ => false
+ }
+
/* ------------- ERROR HANDLING ------------------------------------------- */
protected def skip() {
var nparens = 0
var nbraces = 0
while (true) {
- inToken match {
+ in.token match {
case EOF =>
return
case SEMI =>
@@ -236,82 +222,59 @@ self =>
nbraces += 1
case _ =>
}
- inNextToken
+ in.nextToken()
}
}
- def warning(pos: Int, msg: String): Unit
+ def warning(offset: Int, msg: String): Unit
def incompleteInputError(msg: String): Unit
- def deprecationWarning(pos: Int, msg: String): Unit
+ def deprecationWarning(offset: Int, msg: String): Unit
private def syntaxError(pos: Position, msg: String, skipIt: Boolean) {
pos.offset match {
case None => syntaxError(msg,skipIt)
case Some(offset) => syntaxError(offset, msg, skipIt)
}
}
- def syntaxError(pos: Int, msg: String): Unit
+ def syntaxError(offset: Int, msg: String): Unit
def syntaxError(msg: String, skipIt: Boolean) {
- syntaxError(inCurrentPos, msg, skipIt)
+ syntaxError(in.offset, msg, skipIt)
}
- def syntaxError(pos: Int, msg: String, skipIt: Boolean) {
- if (pos > lastErrorPos) {
- syntaxError(pos, msg)
+ def syntaxError(offset: Int, msg: String, skipIt: Boolean) {
+ if (offset > lastErrorOffset) {
+ syntaxError(offset, msg)
// no more errors on this token.
- lastErrorPos = inCurrentPos
+ lastErrorOffset = in.offset
}
if (skipIt)
skip()
}
- def warning(msg: String) { warning(inCurrentPos, msg) }
+ def warning(msg: String) { warning(in.offset, msg) }
def syntaxErrorOrIncomplete(msg: String, skipIt: Boolean) {
- val inToken = this.inToken
- if (inToken == EOF)
+ if (in.token == EOF)
incompleteInputError(msg)
else
- syntaxError(inCurrentPos, msg, skipIt)
- }
- // unused.
- /* Commented out because the comment says it is unused.
- Probably eliminate eventually. GAW 2008.05.01
- def mismatch(expected: Int, found: Int) {
- val posToReport = this.posToReport
- val msg =
- ScannerConfiguration.token2string(expected) + " expected but " +
- ScannerConfiguration.token2string(found) + " found."
-
- if (found == EOF)
- incompleteInputError(msg)
- else
- syntaxError(posToReport, msg, true)
+ syntaxError(in.offset, msg, skipIt)
}
- */
/** Consume one token of the specified type, or
* signal an error if it is not there.
*/
def accept(token: Int): Int = {
- val pos = inCurrentPos
- if (inToken != token) {
- val posToReport =
- //if (inCurrentPos.line(unit.source).get(0) > in.lastPos.line(unit.source).get(0))
- // in.lastPos
- //else
- inCurrentPos
+ val offset = in.offset
+ if (in.token != token) {
val msg =
- token2string(token) + " expected but " +token2string(inToken) + " found."
+ token2string(token) + " expected but " +token2string(in.token) + " found."
- if (inToken == EOF)
- incompleteInputError(msg)
- else
- syntaxError(posToReport, msg, true)
+ if (in.token == EOF) incompleteInputError(msg)
+ else syntaxError(in.offset, msg, true)
}
- if (inToken == token) inNextToken
- pos
+ if (in.token == token) in.nextToken()
+ offset
}
def surround[T](open: Int, close: Int)(f: => T, orElse: T): T = {
- val wasOpened = inToken == open
+ val wasOpened = in.token == open
accept(open)
if (wasOpened) {
val ret = f
@@ -324,42 +287,58 @@ self =>
* nl = `\n' // where allowed
*/
def acceptStatSep(): Boolean =
- if (inToken == NEWLINE || inToken == NEWLINES) { inNextToken; true }
+ if (in.token == NEWLINE || in.token == NEWLINES) { in.nextToken(); true }
else {
- val ret = inToken == SEMI
+ val ret = in.token == SEMI
accept(SEMI)
ret
}
- def errorTypeTree = TypeTree().setType(ErrorType).setPos((inCurrentPos))
- def errorTermTree = Literal(Constant(null)).setPos((inCurrentPos))
- def errorPatternTree = Ident(nme.WILDCARD).setPos((inCurrentPos))
+ def errorTypeTree = TypeTree().setType(ErrorType).setPos(o2p(in.offset))
+ def errorTermTree = Literal(Constant(null)).setPos(o2p(in.offset))
+ def errorPatternTree = Ident(nme.WILDCARD).setPos(o2p(in.offset))
+
+ /** Check that type parameter is not by name T* */
+ def checkNotByName(t: Tree) = t match {
+ case AppliedTypeTree(Select(_, n), _) if (n == nme.BYNAME_PARAM_CLASS_NAME.toTypeName) =>
+ syntaxError(t.pos, "no by-name parameter type allowed here", false)
+ case _ =>
+ }
+
+ /** Check that tree is a legal clause of a forSome */
+ def checkLegalExistential(t: Tree) = t match {
+ case TypeDef(_, _, _, TypeBoundsTree(_, _)) |
+ ValDef(_, _, _, EmptyTree) | EmptyTree =>
+ ;
+ case _ =>
+ syntaxError(t.pos, "not a legal existential clause", false)
+ }
/* -------------- TOKEN CLASSES ------------------------------------------- */
- def isModifier: Boolean = inToken match {
+ def isModifier: Boolean = in.token match {
case ABSTRACT | FINAL | SEALED | PRIVATE |
PROTECTED | OVERRIDE | IMPLICIT | LAZY => true
case _ => false
}
- def isLocalModifier: Boolean = inToken match {
+ def isLocalModifier: Boolean = in.token match {
case ABSTRACT | FINAL | SEALED | IMPLICIT | LAZY => true
case _ => false
}
- def isDefIntro: Boolean = inToken match {
+ def isDefIntro: Boolean = in.token match {
case VAL | VAR | DEF | TYPE | OBJECT |
CASEOBJECT | CLASS | CASECLASS | TRAIT => true
case _ => false
}
- def isDclIntro: Boolean = inToken match {
+ def isDclIntro: Boolean = in.token match {
case VAL | VAR | DEF | TYPE => true
case _ => false
}
- def isIdent = inToken == IDENTIFIER || inToken == BACKQUOTED_IDENT
+ def isIdent = in.token == IDENTIFIER || in.token == BACKQUOTED_IDENT
def isExprIntroToken(token: Int): Boolean = token match {
case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT |
@@ -369,7 +348,7 @@ self =>
case _ => false
}
- def isExprIntro: Boolean = isExprIntroToken(inToken)
+ def isExprIntro: Boolean = isExprIntroToken(in.token)
def isTypeIntroToken(token: Int): Boolean = token match {
case IDENTIFIER | BACKQUOTED_IDENT | THIS |
@@ -377,12 +356,12 @@ self =>
case _ => false
}
- def isTypeIntro: Boolean = isTypeIntroToken(inToken)
+ def isTypeIntro: Boolean = isTypeIntroToken(in.token)
def isStatSep(token: Int): Boolean =
token == NEWLINE || token == NEWLINES || token == SEMI
- def isStatSep: Boolean = isStatSep(inToken)
+ def isStatSep: Boolean = isStatSep(in.token)
/* --------- COMMENT AND ATTRIBUTE COLLECTION ----------------------------- */
@@ -397,6 +376,15 @@ self =>
/* ---------- TREE CONSTRUCTION ------------------------------------------- */
+ def atPos[T <: Tree](offset: Int)(t: T): T =
+ posAssigner.atPos(r2p(offset, offset, in.lastOffset))(t)
+ def atPos[T <: Tree](start: Int, mid: Int)(t: T): T =
+ posAssigner.atPos(r2p(start, mid, in.lastOffset))(t)
+ def atPos[T <: Tree](start: Int, mid: Int, end: Int)(t: T): T =
+ posAssigner.atPos(r2p(start, mid, end))(t)
+ def atPos[T <: Tree](pos: Position)(t: T): T =
+ posAssigner.atPos(pos)(t)
+
/** Convert tree to formal parameter list
*/
def convertToParams(tree: Tree): List[ValDef] = tree match {
@@ -408,59 +396,44 @@ self =>
/** Convert tree to formal parameter
*/
- def convertToParam(tree: Tree): ValDef =
- atPos(tree.pos) {
- def removeAsPlaceholder(name: Name) {
- placeholderParams = placeholderParams filter (_.name != name)
- }
- tree match {
- case Ident(name) =>
- removeAsPlaceholder(name)
- ValDef(Modifiers(Flags.PARAM), name, TypeTree(), EmptyTree)
- case Typed(tree @ Ident(name), tpe) if (tpe.isType) => // get the ident!
- removeAsPlaceholder(name)
- ValDef(Modifiers(Flags.PARAM), name, tpe, EmptyTree).setPos(tree.pos)
- case _ =>
- syntaxError(tree.pos, "not a legal formal parameter", false)
- ValDef(Modifiers(Flags.PARAM), nme.ERROR, errorTypeTree, EmptyTree)
- }
+ def convertToParam(tree: Tree): ValDef = atPos(tree.pos) {
+ def removeAsPlaceholder(name: Name) {
+ placeholderParams = placeholderParams filter (_.name != name)
+ }
+ tree match {
+ case Ident(name) =>
+ removeAsPlaceholder(name)
+ ValDef(Modifiers(Flags.PARAM), name, TypeTree(), EmptyTree)
+ case Typed(tree @ Ident(name), tpe) if (tpe.isType) => // get the ident!
+ removeAsPlaceholder(name)
+ ValDef(Modifiers(Flags.PARAM), name, tpe, EmptyTree)
+ case _ =>
+ syntaxError(tree.pos, "not a legal formal parameter", false)
+ ValDef(Modifiers(Flags.PARAM), nme.ERROR, errorTypeTree, EmptyTree)
}
+ }
/** Convert (qual)ident to type identifier
*/
- def convertToTypeId(tree: Tree): Tree = tree match {
- case Ident(name) =>
- Ident(name.toTypeName).setPos(tree.pos)
- case Select(qual, name) =>
- Select(qual, name.toTypeName).setPos(tree.pos)
- case _ =>
- syntaxError(tree.pos, "identifier expected", false)
- errorTypeTree
- }
-
- /** make closure from tree staring with a `.' */
- def makeDotClosure(tree: Tree): Tree = {
- val pname = freshName(tree.pos, "x$")
- def insertParam(tree: Tree): Tree = atPos(tree.pos) {
- tree match {
- case Ident(name) =>
- Select(Ident(pname), name)
- case Select(qual, name) =>
- Select(insertParam(qual), name)
- case Apply(fn, args) =>
- Apply(insertParam(fn), args)
- case TypeApply(fn, args) =>
- TypeApply(insertParam(fn), args)
- case _ =>
- syntaxError(tree.pos, "cannot convert to closure", false)
- errorTermTree
- }
+ def convertToTypeId(tree: Tree): Tree = atPos(tree.pos) {
+ tree match {
+ case Ident(name) =>
+ Ident(name.toTypeName)
+ case Select(qual, name) =>
+ Select(qual, name.toTypeName)
+ case _ =>
+ syntaxError(tree.pos, "identifier expected", false)
+ errorTypeTree
}
- Function(List(makeSyntheticParam(pname)), insertParam(tree))
}
/* --------- OPERAND/OPERATOR STACK --------------------------------------- */
+ /** modes for infix types */
+ object InfixMode extends Enumeration {
+ val FirstOp, LeftOp, RightOp = Value
+ }
+
var opstack: List[OpInfo] = Nil
def precedence(operator: Name): Int =
@@ -490,23 +463,24 @@ self =>
if (size > max) syntaxError("too many "+kind+", maximum = "+max, false)
}
- def checkAssoc(pos: Int, op: Name, leftAssoc: Boolean) =
+ def checkAssoc(offset: Int, op: Name, leftAssoc: Boolean) =
if (treeInfo.isLeftAssoc(op) != leftAssoc)
syntaxError(
- pos, "left- and right-associative operators with same precedence may not be mixed", false)
+ offset, "left- and right-associative operators with same precedence may not be mixed", false)
def reduceStack(isExpr: Boolean, base: List[OpInfo], top0: Tree,
prec: Int, leftAssoc: Boolean): Tree = {
var top = top0
if (opstack != base && precedence(opstack.head.operator) == prec)
- checkAssoc(opstack.head.pos, opstack.head.operator, leftAssoc)
+ checkAssoc(opstack.head.offset, opstack.head.operator, leftAssoc)
while (opstack != base &&
(prec < precedence(opstack.head.operator) ||
- (leftAssoc && prec == precedence(opstack.head.operator)))) {
- top = atPos(opstack.head.pos) {
- makeBinop(isExpr, opstack.head.operand, opstack.head.operator, top)
- }
+ leftAssoc && prec == precedence(opstack.head.operator))) {
+ val opinfo = opstack.head
opstack = opstack.tail
+ top = atPos(opinfo.operand.pos.start, opinfo.offset) {
+ makeBinop(isExpr, opinfo.operand, opinfo.operator, top)
+ }
}
top
}
@@ -514,88 +488,87 @@ self =>
/* -------- IDENTIFIERS AND LITERALS ------------------------------------------- */
def ident(): Name =
- if (inToken == IDENTIFIER || inToken == BACKQUOTED_IDENT) {
- val name = inName.encode
- inNextToken
+ if (in.token == IDENTIFIER || in.token == BACKQUOTED_IDENT) {
+ val name = in.name.encode
+ in.nextToken()
name
} else {
accept(IDENTIFIER)
nme.ERROR
}
- def selector(t: Tree): Tree =
- atPos(inCurrentPos)(Select(t, ident()))
+ def selector(t: Tree): Tree = {
+ val mid = in.offset
+ Select(t, ident()) setPos r2p(t.pos.start, mid, in.lastOffset)
+ }
/** Path ::= StableId
* | [Ident `.'] this
* AnnotType ::= Path [`.' type]
*/
def path(thisOK: Boolean, typeOK: Boolean): Tree = {
+ val start = in.offset
var t: Tree = null
- if (inToken == THIS) {
- t = atPos(inSkipToken) { This(nme.EMPTY.toTypeName) }
- if (!thisOK || inToken == DOT) {
- t = selectors(t, typeOK, accept(DOT))
+ if (in.token == THIS) {
+ in.nextToken()
+ t = atPos(start) { This(nme.EMPTY.toTypeName) }
+ if (!thisOK || in.token == DOT) {
+ t = selectors(t, typeOK, accept(DOT))
}
- } else if (inToken == SUPER) {
- // val pos = inCurrentPos
- val pos = inSkipToken
- val (mix,usePos) = mixinQualifierOpt(pos)
- t = atPos(usePos) {
- Super(nme.EMPTY.toTypeName, mix)
- }
- t = atPos(accept(DOT)) { selector(t) }
- if (inToken == DOT)
- t = selectors(t, typeOK, inSkipToken)
+ } else if (in.token == SUPER) {
+ in.nextToken()
+ t = atPos(start) { Super(nme.EMPTY.toTypeName, mixinQualifierOpt()) }
+ accept(DOT)
+ t = selector(t)
+ if (in.token == DOT) t = selectors(t, typeOK, in.skipToken())
} else {
- val i = atPos(inCurrentPos) {
- if (inToken == BACKQUOTED_IDENT) new BackQuotedIdent(ident())
- else Ident(ident())
+ val tok = in.token
+ val name = ident()
+ t = atPos(start) {
+ if (tok == BACKQUOTED_IDENT) new BackQuotedIdent(name)
+ else Ident(name)
}
- t = i
- if (inToken == DOT) {
- val pos = inSkipToken
- if (inToken == THIS) {
- inNextToken
- t = atPos(i.pos) { This(i.name.toTypeName) }
- if (!thisOK || inToken == DOT)
+ if (in.token == DOT) {
+ val dotOffset = in.skipToken()
+ if (in.token == THIS) {
+ in.nextToken()
+ t = atPos(start) { This(name.toTypeName) }
+ if (!thisOK || in.token == DOT)
t = selectors(t, typeOK, accept(DOT))
- } else if (inToken == SUPER) {
- inNextToken
- val (mix,pos) = mixinQualifierOpt(i.pos)
- t = atPos(pos) { Super(i.name.toTypeName, mix) }
- t = atPos(accept(DOT)) {selector(t)}
- if (inToken == DOT)
- t = selectors(t, typeOK, inSkipToken)
+ } else if (in.token == SUPER) {
+ in.nextToken()
+ t = atPos(start) { Super(name.toTypeName, mixinQualifierOpt()) }
+ accept(DOT)
+ t = selector(t)
+ if (in.token == DOT) t = selectors(t, typeOK, in.skipToken())
} else {
- t = selectors(t, typeOK, pos)
+ t = selectors(t, typeOK, dotOffset)
}
}
}
t
}
- def selectors(t: Tree, typeOK: Boolean, pos : Int): Tree =
- if (typeOK && inToken == TYPE) {
- inNextToken
- atPos(pos) { SingletonTypeTree(t) }
+ def selectors(t: Tree, typeOK: Boolean, dotOffset: Int): Tree =
+ if (typeOK && in.token == TYPE) {
+ in.nextToken()
+ atPos(t.pos.start, dotOffset) { SingletonTypeTree(t) }
} else {
- val t1 = atPos(pos) { selector(t); }
- if (inToken == DOT) { selectors(t1, typeOK, inSkipToken) }
+ val t1 = selector(t)
+ if (in.token == DOT) { selectors(t1, typeOK, in.skipToken()) }
else t1
}
/** MixinQualifier ::= `[' Id `]'
*/
- def mixinQualifierOpt(pos: Position): (Name, Position) =
- if (inToken == LBRACKET) {
- inNextToken
- val pos = inCurrentPos
+ def mixinQualifierOpt(): Name =
+ if (in.token == LBRACKET) {
+ in.nextToken()
val name = ident().toTypeName
accept(RBRACKET)
- (name, pos)
+ name
} else {
- (nme.EMPTY.toTypeName, pos)
+ nme.EMPTY.toTypeName
}
/** StableId ::= Id
@@ -608,106 +581,79 @@ self =>
/** QualId ::= Id {`.' Id}
*/
def qualId(): Tree = {
- val id = atPos(inCurrentPos) { Ident(ident()) }
- if (inToken == DOT) { selectors(id, false, inSkipToken) }
+ val start = in.offset
+ val id = atPos(start) { Ident(ident()) }
+ if (in.token == DOT) { selectors(id, false, in.skipToken()) }
else id
}
/** SimpleExpr ::= literal
- * | symbol
- * | null
- */
-
- def literal(isPattern: Boolean, isNegated: Boolean): Tree = {
- def litToTree() = atPos(inCurrentPos) {
- Literal(
- inToken match {
- case CHARLIT => Constant(charVal)
- case INTLIT => Constant(intVal(isNegated))
- case LONGLIT => Constant(longVal(isNegated))
- case FLOATLIT => Constant(floatVal(isNegated))
- case DOUBLELIT => Constant(doubleVal(isNegated))
- case STRINGLIT | SYMBOLLIT => Constant(stringVal)
- case TRUE => Constant(true)
- case FALSE => Constant(false)
- case NULL => Constant(null)
- case _ =>
- syntaxErrorOrIncomplete("illegal literal", true)
- null
- })
- }
-
- val isSymLit = inToken == SYMBOLLIT
- val t = litToTree()
- val pos = inSkipToken
- if (isSymLit) {
- atPos(pos) {
- var symid = scalaDot(nme.Symbol)
- Apply(symid, List(t))
+ * | symbol
+ * | null
+ * @note The returned tree does not yet have a position
+ */
+ def literal(isNegated: Boolean): Tree = {
+ val isSymLit = in.token == SYMBOLLIT
+ val t = Literal {
+ in.token match {
+ case CHARLIT => Constant(in.charVal)
+ case INTLIT => Constant(in.intVal(isNegated).toInt)
+ case LONGLIT => Constant(in.intVal(isNegated))
+ case FLOATLIT => Constant(in.floatVal(isNegated).toFloat)
+ case DOUBLELIT => Constant(in.floatVal(isNegated))
+ case STRINGLIT | SYMBOLLIT => Constant(in.strVal)
+ case TRUE => Constant(true)
+ case FALSE => Constant(false)
+ case NULL => Constant(null)
+ case _ =>
+ syntaxErrorOrIncomplete("illegal literal", true)
+ Constant(null)
}
- } else {
- t
}
+ in.nextToken()
+ if (isSymLit) Apply(scalaDot(nme.Symbol), List(t)) else t
}
+/* ------------- NEW LINES ------------------------------------------------- */
+
def newLineOpt() {
- if (inToken == NEWLINE) inNextToken
+ if (in.token == NEWLINE) in.nextToken()
}
def newLinesOpt() {
- if (inToken == NEWLINE || inToken == NEWLINES)
- inNextToken
+ if (in.token == NEWLINE || in.token == NEWLINES)
+ in.nextToken()
}
def newLineOptWhenFollowedBy(token: Int) {
// note: next is defined here because current == NEWLINE
- if (inToken == NEWLINE && inNextTokenCode == token) newLineOpt()
+ if (in.token == NEWLINE && in.next.token == token) newLineOpt()
}
def newLineOptWhenFollowing(p: Int => Boolean) {
// note: next is defined here because current == NEWLINE
- if (inToken == NEWLINE && p(inNextTokenCode)) newLineOpt()
+ if (in.token == NEWLINE && p(in.next.token)) newLineOpt()
}
/* ------------- TYPES ---------------------------------------------------- */
/** TypedOpt ::= [`:' Type]
- */
+ */
def typedOpt(): Tree =
- if (inToken == COLON) { inNextToken; typ() }
+ if (in.token == COLON) { in.nextToken(); typ() }
else TypeTree()
- /** RequiresTypedOpt ::= [requires AnnotType]
- */
- def requiresTypeOpt(): Tree =
- if (inToken == REQUIRES) {
- deprecationWarning(inCurrentPos, "`requires T' has been deprecated; use `{ self: T => ...' instead")
- inNextToken; annotType(false)
- } else TypeTree()
-
/** Types ::= Type {`,' Type}
- * (also eats trailing comma if it finds one)
*/
def types(isPattern: Boolean, isTypeApply: Boolean, isFuncArg: Boolean): List[Tree] = {
- val ts = new ListBuffer[Tree] + argType(isPattern, isTypeApply, isFuncArg)
- while (inToken == COMMA) {
- val pos = inCurrentPos
- inNextToken
- if (inToken == RPAREN) {
- deprecationWarning(pos, "Trailing commas have been deprecated")
- return ts.toList
- } else {
- ts += argType(isPattern, isTypeApply, isFuncArg)
- }
+ val ts = new ListBuffer[Tree] += argType(isPattern, isTypeApply, isFuncArg)
+ while (in.token == COMMA) {
+ in.nextToken()
+ ts += argType(isPattern, isTypeApply, isFuncArg)
}
ts.toList
}
- /** modes for infix types */
- object InfixMode extends Enumeration {
- val FirstOp, LeftOp, RightOp = Value
- }
-
/** Type ::= InfixType `=>' Type
* | `(' [`=>' Type] `)' `=>' Type
* | InfixType [ExistentialClause]
@@ -717,47 +663,43 @@ self =>
def typ(): Tree = typ(false)
def typ(isPattern: Boolean): Tree = placeholderTypeBoundary {
+ val start = in.offset
val t =
- if (inToken == LPAREN) {
- val pos = inSkipToken
- if (inToken == RPAREN) {
- inNextToken
- atPos(accept(ARROW)) { makeFunctionTypeTree(List(), typ(isPattern)) }
+ if (in.token == LPAREN) {
+ in.nextToken()
+ if (in.token == RPAREN) {
+ in.nextToken()
+ atPos(start, accept(ARROW)) {
+ makeFunctionTypeTree(List(), typ(isPattern))
+ }
} else {
val ts = types(isPattern, false, true)
accept(RPAREN)
- if (inToken == ARROW) atPos(inSkipToken) {
- makeFunctionTypeTree(ts, typ(isPattern))
- }
- else {
- for (t <- ts) t match {
- case AppliedTypeTree(Select(_, n), _)
- if (n == nme.BYNAME_PARAM_CLASS_NAME.toTypeName) =>
- syntaxError(t.pos, "no by-name parameter type allowed here", false)
- case _ =>
+ if (in.token == ARROW)
+ atPos(start, in.skipToken()) {
+ makeFunctionTypeTree(ts, typ(isPattern))
}
- infixTypeRest(pos, annotTypeRest(pos, isPattern, makeTupleType(ts, true)), false, InfixMode.FirstOp)
+ else {
+ ts foreach checkNotByName
+ val tuple = atPos(start) { makeTupleType(ts, true) }
+ infixTypeRest(
+ compoundTypeRest(
+ annotTypeRest(simpleTypeRest(tuple, isPattern)),
+ isPattern),
+ isPattern, InfixMode.FirstOp)
}
}
} else {
infixType(isPattern, InfixMode.FirstOp)
}
- if (inToken == ARROW)
- atPos(inSkipToken) {
+ if (in.token == ARROW)
+ atPos(start, in.skipToken()) {
makeFunctionTypeTree(List(t), typ(isPattern))
}
- else if (inToken == FORSOME)
- atPos(inSkipToken) {
+ else if (in.token == FORSOME)
+ atPos(start, in.skipToken()) {
val whereClauses = refinement()
- for (wc <- whereClauses) {
- wc match {
- case TypeDef(_, _, _, TypeBoundsTree(_, _)) |
- ValDef(_, _, _, EmptyTree) | EmptyTree =>
- ;
- case _ =>
- syntaxError(wc.pos, "not a legal existential clause", false)
- }
- }
+ whereClauses foreach checkLegalExistential
ExistentialTypeTree(t, whereClauses)
}
else t
@@ -766,24 +708,19 @@ self =>
/** InfixType ::= CompoundType {id [nl] CompoundType}
*/
def infixType(isPattern: Boolean, mode: InfixMode.Value): Tree = placeholderTypeBoundary {
- infixTypeRest(inCurrentPos, infixTypeFirst(isPattern), isPattern, mode)
+ infixTypeRest(compoundType(isPattern), isPattern, mode)
}
- def infixTypeFirst(isPattern: Boolean): Tree =
- if (inToken == LBRACE) scalaAnyRefConstr else annotType(isPattern)
-
- def infixTypeRest(pos: Int, t0: Tree, isPattern: Boolean, mode: InfixMode.Value): Tree = {
- val t = compoundTypeRest(pos, t0, isPattern)
- if (isIdent && inName != nme.STAR) {
- val opPos = inCurrentPos
- val leftAssoc = treeInfo.isLeftAssoc(inName)
- if (mode == InfixMode.LeftOp) checkAssoc(opPos, inName, true)
- else if (mode == InfixMode.RightOp) checkAssoc(opPos, inName, false)
+ def infixTypeRest(t: Tree, isPattern: Boolean, mode: InfixMode.Value): Tree = {
+ if (isIdent && in.name != nme.STAR) {
+ val opOffset = in.offset
+ val leftAssoc = treeInfo.isLeftAssoc(in.name)
+ if (mode != InfixMode.FirstOp) checkAssoc(opOffset, in.name, mode == InfixMode.LeftOp)
val op = ident()
newLineOptWhenFollowing(isTypeIntroToken)
- def mkOp(t1: Tree) = atPos(opPos) { AppliedTypeTree(Ident(op.toTypeName), List(t, t1)) }
+ def mkOp(t1: Tree) = atPos(t.pos.start, opOffset) { AppliedTypeTree(Ident(op.toTypeName), List(t, t1)) }
if (leftAssoc)
- infixTypeRest(inCurrentPos, mkOp(compoundType(isPattern)), isPattern, InfixMode.LeftOp)
+ infixTypeRest(mkOp(compoundType(isPattern)), isPattern, InfixMode.LeftOp)
else
mkOp(infixType(isPattern, InfixMode.RightOp))
} else t
@@ -792,17 +729,20 @@ self =>
/** CompoundType ::= AnnotType {with AnnotType} [Refinement]
* | Refinement
*/
- def compoundType(isPattern: Boolean): Tree =
- compoundTypeRest(inCurrentPos, infixTypeFirst(isPattern), isPattern)
+ def compoundType(isPattern: Boolean): Tree = {
+ val t = if (in.token == LBRACE) atPos(o2p(in.offset)) (scalaAnyRefConstr)
+ else annotType(isPattern)
+ compoundTypeRest(t, isPattern)
+ }
- def compoundTypeRest(pos: Int, t: Tree, isPattern: Boolean): Tree = {
- var ts = new ListBuffer[Tree] + t
- while (inToken == WITH) {
- inNextToken; ts += annotType(isPattern)
+ def compoundTypeRest(t: Tree, isPattern: Boolean): Tree = {
+ var ts = new ListBuffer[Tree] += t
+ while (in.token == WITH) {
+ in.nextToken(); ts += annotType(isPattern)
}
newLineOptWhenFollowedBy(LBRACE)
- atPos(pos) {
- if (inToken == LBRACE) {
+ atPos(t.pos.start) {
+ if (in.token == LBRACE) {
// Warn if they are attempting to refine Unit; we can't be certain it's
// scala.Unit they're refining because at this point all we have is an
// identifier, but at a later stage we lose the ability to tell an empty
@@ -820,54 +760,61 @@ self =>
}
/** AnnotType ::= SimpleType {Annotation}
- * SimpleType ::= SimpleType TypeArgs
+ */
+ def annotType(isPattern: Boolean): Tree = placeholderTypeBoundary {
+ annotTypeRest(simpleType(isPattern))
+ }
+
+ def annotTypeRest(t: Tree): Tree =
+ (t /: annotations(false)) (makeAnnotated)
+
+ /** SimpleType ::= SimpleType TypeArgs
* | SimpleType `#' Id
* | StableId
* | Path `.' type
* | `(' Types [`,'] `)'
* | WildcardType
*/
- def annotType(isPattern: Boolean): Tree = placeholderTypeBoundary {
- val pos = inCurrentPos
-
- val t: Tree = annotTypeRest(pos, isPattern,
- if (inToken == LPAREN) {
- inNextToken
+ def simpleType(isPattern: Boolean): Tree = {
+ val start = in.offset
+ val t =
+ if (in.token == LPAREN) {
+ in.nextToken()
val ts = types(isPattern, false, false)
accept(RPAREN)
- atPos(pos) { makeTupleType(ts, true) }
- } else if (inToken == USCORE) {
- wildcardType(inSkipToken)
- } else {
- val r = path(false, true)
- r match {
- case SingletonTypeTree(_) => r
- case _ => convertToTypeId(r)
- }
- })
- (t /: annotations(false)) (makeAnnotated)
+ atPos(start) { makeTupleType(ts, true) }
+ } else if (in.token == USCORE) {
+ wildcardType(in.skipToken())
+ } else path(false, true) match {
+ case r @ SingletonTypeTree(_) => r
+ case r => convertToTypeId(r)
+ }
+ simpleTypeRest(t, isPattern)
}
- def annotTypeRest(pos: Int, isPattern: Boolean, t: Tree): Tree =
- if (inToken == HASH) {
- inSkipToken
- val posId = inCurrentPos
- val id = ident
- annotTypeRest(pos, isPattern, atPos(posId) { SelectFromTypeTree(t, id.toTypeName) })
- } else if (inToken == LBRACKET) {
- val usePos = if (t.pos != NoPosition) t.pos else i2p(pos)
- annotTypeRest(pos, isPattern, atPos(usePos) { AppliedTypeTree(t, typeArgs(isPattern, false)) })
- }
- else
+ def simpleTypeRest(t: Tree, isPattern: Boolean): Tree =
+ if (in.token == HASH) {
+ val hashOffset = in.skipToken()
+ val nameOffset = in.offset
+ val name = ident()
+ val sel = atPos(t.pos.start, if (name == nme.ERROR) hashOffset else nameOffset) {
+ SelectFromTypeTree(t, name.toTypeName)
+ }
+ simpleTypeRest(sel, isPattern)
+ } else if (in.token == LBRACKET) {
+ simpleTypeRest(atPos(t.pos.start) { AppliedTypeTree(t, typeArgs(isPattern, false)) }, isPattern)
+ } else {
t
+ }
/** WildcardType ::= `_' TypeBounds
*/
- def wildcardType(pos: Int) = {
- val pname = freshName(pos, "_$").toTypeName
- val param = atPos(pos) { makeSyntheticTypeParam(pname, typeBounds()) }
+ def wildcardType(start: Int) = {
+ val pname = freshName(o2p(start), "_$").toTypeName
+ val t = atPos(start) { Ident(pname) }
+ val param = atPos(start) { makeSyntheticTypeParam(pname, typeBounds()) }
placeholderTypes = param :: placeholderTypes
- Ident(pname) setPos pos
+ t
}
/** TypeArgs ::= `[' ArgType {`,' ArgType} `]'
@@ -881,40 +828,38 @@ self =>
/** ArgType ::= Type
*/
- def argType(isPattern: Boolean, isTypeApply: Boolean, isFuncArg: Boolean): Tree =
+ def argType(isPattern: Boolean, isTypeApply: Boolean, isFuncArg: Boolean): Tree = {
+ val start = in.offset
if (isPattern) {
- if (inToken == USCORE)
- if (inToken == SUBTYPE || inToken == SUPERTYPE) wildcardType(inSkipToken)
- else atPos(inSkipToken) { Bind(nme.WILDCARD.toTypeName, EmptyTree) }
- else if (inToken == IDENTIFIER && treeInfo.isVariableName(inName.toTypeName))
- atPos(inCurrentPos) {
- Bind(ident().toTypeName, EmptyTree)
- }
- else {
+ if (in.token == USCORE) {
+ in.nextToken()
+ if (in.token == SUBTYPE || in.token == SUPERTYPE) wildcardType(start)
+ else atPos(start) { Bind(nme.WILDCARD.toTypeName, EmptyTree) }
+ } else if (in.token == IDENTIFIER && treeInfo.isVariableName(in.name.toTypeName)) {
+ atPos(start) { Bind(ident().toTypeName, EmptyTree) }
+ } else {
typ(true)
}
} else if (isFuncArg) {
// copy-paste (with change) from def paramType
- if (inToken == ARROW)
- atPos(inSkipToken) {
- AppliedTypeTree(
- rootScalaDot(nme.BYNAME_PARAM_CLASS_NAME.toTypeName), List(typ()))
+ if (in.token == ARROW) {
+ in.nextToken()
+ atPos(start) {
+ AppliedTypeTree(rootScalaDot(nme.BYNAME_PARAM_CLASS_NAME.toTypeName), List(typ()))
}
- else {
+ } else {
val t = typ()
- if (isIdent && inName == STAR) {
- inNextToken
- atPos(t.pos) {
- AppliedTypeTree(
- rootScalaDot(nme.REPEATED_PARAM_CLASS_NAME.toTypeName), List(t))
+ if (isIdent && in.name == STAR) {
+ in.nextToken()
+ atPos(start) {
+ AppliedTypeTree(rootScalaDot(nme.REPEATED_PARAM_CLASS_NAME.toTypeName), List(t))
}
} else t
}
- } else if (isTypeApply) {
- typ()
} else {
typ()
}
+ }
/* ----------- EXPRESSIONS ------------------------------------------------ */
@@ -926,24 +871,32 @@ self =>
}
/** Exprs ::= Expr {`,' Expr}
- *
- * (also eats trailing comma if it finds one)
*/
def exprs(): List[Tree] = {
- val ts = new ListBuffer[Tree] + expr()
- while (inToken == COMMA) {
- val pos = inCurrentPos
- inNextToken
- if (inToken == RPAREN) {
- deprecationWarning(pos, "Trailing commas have been deprecated")
- return ts.toList
- } else {
- ts += expr()
- }
+ val ts = new ListBuffer[Tree] += expr()
+ while (in.token == COMMA) {
+ in.nextToken()
+ ts += expr()
}
ts.toList
}
+ def condExpr(): Tree = {
+ if (in.token == LPAREN) {
+ in.nextToken()
+ val r = expr()
+ accept(RPAREN)
+ r
+ } else {
+ accept(LPAREN)
+ Literal(true)
+ }
+ }
+
+ /* hook for IDE, unlike expression can be stubbed
+ * don't use for any tree that can be inspected in the parser!
+ */
+ def statement(location: Int): Tree = expr(location) // !!! still needed?
/** Expr ::= (Bindings | Id | `_') `=>' Expr
* | Expr1
@@ -967,154 +920,141 @@ self =>
* | `:' `_' `*'
*/
def expr(): Tree = expr(Local)
- /* hook for IDE, unlike expression can be stubbed
- * don't use for any tree that can be inspected in the parser!
- */
- def statement(location: Int): Tree = expr(location)
+
def expr(location: Int): Tree = {
- def isWildcard(t: Tree): Boolean = t match {
- case Ident(name1) if !placeholderParams.isEmpty && name1 == placeholderParams.head.name => true
- case Typed(t1, _) => isWildcard(t1)
- case Annotated(t1, _) => isWildcard(t1)
- case _ => false
- }
var savedPlaceholderParams = placeholderParams
placeholderParams = List()
- var res = inToken match {
- case IF =>
- val pos = inSkipToken
- val cond = surround(LPAREN,RPAREN)(expr(),Literal(true))
+ var res = expr0(location)
+ if (!placeholderParams.isEmpty && !isWildcard(res)) {
+ res = atPos(res.pos){ Function(placeholderParams.reverse, res) }
+ placeholderParams = List()
+ }
+ placeholderParams = placeholderParams ::: savedPlaceholderParams
+ res
+ }
+
+ def expr0(location: Int): Tree = in.token match {
+ case IF =>
+ atPos(in.skipToken()) {
+ val cond = condExpr()
newLinesOpt()
val thenp = expr()
- val elsep = if (inToken == ELSE) { inNextToken; expr() }
- else Literal(())
- atPos(pos) { If(cond, thenp, elsep) }
- case TRY =>
- atPos(inSkipToken) {
- val body =
- if (inToken == LBRACE) surround(LBRACE, RBRACE)(block(), Literal(()))
- else if (inToken == LPAREN) surround(LPAREN, RPAREN)(expr(), Literal(()))
- else expr()
- val catches =
- if (inToken == CATCH) {
- inNextToken
- val cases = surround(LBRACE,RBRACE)(caseClauses(), Nil)
- cases
- } else Nil
- val finalizer =
- if (inToken == FINALLY) { inNextToken; expr() }
- else EmptyTree
- Try(body, catches, finalizer)
- }
- case WHILE =>
- val pos = inSkipToken
- val lname: Name = freshName(pos, "while$")
- val cond = surround(LPAREN,RPAREN)(expr(),Literal(true))
+ val elsep = if (in.token == ELSE) { in.nextToken(); expr() }
+ else Literal(())
+ If(cond, thenp, elsep)
+ }
+ case TRY =>
+ atPos(in.skipToken()) {
+ val body =
+ if (in.token == LBRACE) surround(LBRACE, RBRACE)(block(), Literal(()))
+ else if (in.token == LPAREN) surround(LPAREN, RPAREN)(expr(), Literal(()))
+ else expr()
+ val catches =
+ if (in.token == CATCH) {
+ in.nextToken()
+ surround(LBRACE, RBRACE)(caseClauses(), Nil)
+ } else Nil
+ val finalizer =
+ if (in.token == FINALLY) { in.nextToken(); expr() }
+ else EmptyTree
+ Try(body, catches, finalizer)
+ }
+ case WHILE =>
+ val start = in.offset
+ atPos(in.skipToken()) {
+ val lname: Name = freshName(o2p(start), "while$")
+ val cond = condExpr()
newLinesOpt()
val body = expr()
- atPos(pos) { makeWhile(lname, cond, body) }
- case DO =>
- val pos = inSkipToken
- val lname: Name = freshName(pos, "doWhile$")
+ makeWhile(lname, cond, body)
+ }
+ case DO =>
+ val start = in.offset
+ atPos(in.skipToken()) {
+ val lname: Name = freshName(o2p(start), "doWhile$")
val body = expr()
- if (isStatSep) inNextToken
+ if (isStatSep) in.nextToken()
accept(WHILE)
- val cond = surround(LPAREN,RPAREN)(expr(), Literal(true))
- atPos(pos) { makeDoWhile(lname, body, cond) }
- case FOR =>
- atPos(inSkipToken) {
- val startToken = inToken
- val (open,close) = if (startToken == LBRACE) (LBRACE,RBRACE) else (LPAREN,RPAREN)
- val enums = surround(open,close)(enumerators(), Nil)
- newLinesOpt()
- if (inToken == YIELD) {
- inNextToken; makeForYield(enums, expr())
- } else makeFor(enums, expr())
- }
- case RETURN =>
- atPos(inSkipToken) {
- Return(if (isExprIntro) expr() else Literal(()))
- }
- case THROW =>
- atPos(inSkipToken) {
- Throw(expr())
+ val cond = condExpr()
+ makeDoWhile(lname, body, cond)
+ }
+ case FOR =>
+ atPos(in.skipToken()) {
+ val (open, close) = if (in.token == LBRACE) (LBRACE, RBRACE) else (LPAREN, RPAREN)
+ val enums = surround(open, close)(enumerators(), Nil)
+ newLinesOpt()
+ if (in.token == YIELD) {
+ in.nextToken()
+ makeForYield(enums, expr())
+ } else {
+ makeFor(enums, expr())
}
- case DOT =>
- deprecationWarning(inCurrentPos, "`.f' has been deprecated; use `_.f' instead")
- atPos(inSkipToken) {
- if (isIdent) {
- makeDotClosure(stripParens(simpleExpr()))
- } else {
- syntaxErrorOrIncomplete("identifier expected", true)
- errorTermTree
- }
+ }
+ case RETURN =>
+ atPos(in.skipToken()) {
+ Return(if (isExprIntro) expr() else Literal(()))
+ }
+ case THROW =>
+ atPos(in.skipToken()) {
+ Throw(expr())
+ }
+ case _ =>
+ var t = postfixExpr()
+ if (in.token == EQUALS) {
+ t match {
+ case Ident(_) | Select(_, _) | Apply(_, _) =>
+ t = atPos(t.pos.start, in.skipToken()) { makeAssign(t, expr()) }
+ case _ =>
}
- case _ =>
- var t = postfixExpr()
- if (inToken == EQUALS) {
- t match {
- case Ident(_) | Select(_, _) | Apply(_, _) =>
- t = atPos(inSkipToken) { makeAssign(t, expr()) }
- case _ =>
- }
- } else if (inToken == COLON) {
- t = stripParens(t)
- val pos = inSkipToken
- if (inToken == USCORE) {
- //todo: need to handle case where USCORE is a wildcard in a type
- val pos1 = inSkipToken
- if (isIdent && inName == nme.STAR) {
- inNextToken
- t = atPos(pos) {
- Typed(t, atPos(pos1) { Ident(nme.WILDCARD_STAR.toTypeName) })
- }
- } else {
- syntaxErrorOrIncomplete("`*' expected", true)
+ } else if (in.token == COLON) {
+ t = stripParens(t)
+ val colonPos = in.skipToken()
+ if (in.token == USCORE) {
+ //todo: need to handle case where USCORE is a wildcard in a type
+ val uscorePos = in.skipToken()
+ if (isIdent && in.name == nme.STAR) {
+ in.nextToken()
+ t = atPos(t.pos.start, colonPos) {
+ Typed(t, atPos(uscorePos) { Ident(nme.WILDCARD_STAR.toTypeName) })
}
- } else if (in.token == AT) {
- t = (t /: annotations(false)) (makeAnnotated)
} else {
- t = atPos(pos) {
- val tpt =
- if (location != Local) infixType(false, InfixMode.FirstOp)
- else typ()
- if (isWildcard(t))
- (placeholderParams: @unchecked) match {
- case (vd @ ValDef(mods, name, _, _)) :: rest =>
- placeholderParams = copy.ValDef(vd, mods, name, tpt.duplicate, EmptyTree) :: rest
- }
- // this does not correspond to syntax, but is necessary to
- // accept closures. We might restrict closures to be between {...} only!
- Typed(t, tpt)
- }
+ syntaxErrorOrIncomplete("`*' expected", true)
}
- } else if (inToken == MATCH) {
- t = atPos(inSkipToken) {
- val cases = surround(LBRACE,RBRACE)(caseClauses(), Nil)
- Match(stripParens(t), cases)
+ } else if (in.token == AT) {
+ t = (t /: annotations(false)) (makeAnnotated)
+ } else {
+ t = atPos(t.pos.start, colonPos) {
+ val tpt =
+ if (location == Local) typ() else infixType(false, InfixMode.FirstOp)
+ if (isWildcard(t))
+ (placeholderParams: @unchecked) match {
+ case (vd @ ValDef(mods, name, _, _)) :: rest =>
+ placeholderParams = copy.ValDef(vd, mods, name, tpt.duplicate, EmptyTree) :: rest
+ }
+ // this does not correspond to syntax, but is necessary to
+ // accept closures. We might restrict closures to be between {...} only.
+ Typed(t, tpt)
}
}
- // in order to allow anonymous functions as statements (as opposed to expressions) inside
- // templates, we have to disambiguate them from self type declarations - bug #1565
- // The case still missed is unparenthesized single argument, like "x: Int => x + 1", which
- // may be impossible to distinguish from a self-type and so remains an error. (See #1564)
- def lhsIsTypedParamList() = t match {
- case Parens(xs) if xs forall (_.isInstanceOf[Typed]) => true
- case _ => false
+ } else if (in.token == MATCH) {
+ t = atPos(t.pos.start, in.skipToken()) {
+ Match(stripParens(t), surround(LBRACE, RBRACE)(caseClauses(), Nil))
}
- if (inToken == ARROW && (location != InTemplate || lhsIsTypedParamList)) {
- t = atPos(inSkipToken) {
- Function(convertToParams(t), if (location != InBlock) expr() else block())
- }
+ }
+ // in order to allow anonymous functions as statements (as opposed to expressions) inside
+ // templates, we have to disambiguate them from self type declarations - bug #1565
+ // The case still missed is unparenthesized single argument, like "x: Int => x + 1", which
+ // may be impossible to distinguish from a self-type and so remains an error. (See #1564)
+ def lhsIsTypedParamList() = t match {
+ case Parens(xs) if xs forall (_.isInstanceOf[Typed]) => true
+ case _ => false
+ }
+ if (in.token == ARROW && (location != InTemplate || lhsIsTypedParamList)) {
+ t = atPos(t.pos.start, in.skipToken()) {
+ Function(convertToParams(t), if (location != InBlock) expr() else block())
}
- stripParens(t)
- }
- if (!placeholderParams.isEmpty && !isWildcard(res)) {
- res = atPos(res.pos){ Function(placeholderParams.reverse, res) }
- placeholderParams = List()
- }
- placeholderParams = placeholderParams ::: savedPlaceholderParams
- res
+ }
+ stripParens(t)
}
/** PostfixExpr ::= InfixExpr [Id [nl]]
@@ -1125,10 +1065,9 @@ self =>
val base = opstack
var top = prefixExpr()
while (isIdent) {
- top = reduceStack(
- true, base, top, precedence(inName), treeInfo.isLeftAssoc(inName))
- val op = inName
- opstack = OpInfo(top, op, inCurrentPos) :: opstack
+ top = reduceStack(true, base, top, precedence(in.name), treeInfo.isLeftAssoc(in.name))
+ val op = in.name
+ opstack = OpInfo(top, op, in.offset) :: opstack
ident()
newLineOptWhenFollowing(isExprIntroToken)
if (isExprIntro) {
@@ -1136,9 +1075,10 @@ self =>
} else {
val topinfo = opstack.head
opstack = opstack.tail
- return Select(
- stripParens(reduceStack(true, base, topinfo.operand, 0, true)),
- topinfo.operator.encode).setPos(topinfo.pos)
+ val od = stripParens(reduceStack(true, base, topinfo.operand, 0, true))
+ return atPos(od.pos.start, topinfo.offset) {
+ Select(od, topinfo.operator.encode)
+ }
}
}
reduceStack(true, base, top, 0, true)
@@ -1148,28 +1088,19 @@ self =>
*/
def prefixExpr(): Tree = {
def unaryOp(): Name = "unary_" + ident()
- if (isIdent && inName == MINUS) {
- val name = unaryOp()
- inToken match {
- case INTLIT | LONGLIT | FLOATLIT | DOUBLELIT => literal(false, true)
- case _ => atPos(inCurrentPos) { Select(stripParens(simpleExpr()), name) }
+ if (isIdent && in.name == MINUS) {
+ atPos(in.offset) {
+ val name = unaryOp()
+ in.token match {
+ case INTLIT | LONGLIT | FLOATLIT | DOUBLELIT => literal(true)
+ case _ => Select(stripParens(simpleExpr()), name)
+ }
+ }
+ } else if (isIdent && (in.name == PLUS || in.name == TILDE || in.name == BANG)) {
+ atPos(in.offset) {
+ val name = unaryOp()
+ Select(stripParens(simpleExpr()), name)
}
- } else if (isIdent && (inName == PLUS || inName == TILDE || inName == BANG)) {
- val pos = inCurrentPos
- val name = unaryOp()
- atPos(pos) { Select(stripParens(simpleExpr()), name) }
- } else if (isIdent && inName == AMP) {
- deprecationWarning(inCurrentPos, "`&f' has been deprecated; use `f _' instead")
- val pos = inCurrentPos
- val name = ident()
- atPos(pos) { Typed(stripParens(simpleExpr()), Function(List(), EmptyTree)) }
-/* XX-LIFTING
- } else if (settings.Xexperimental.value && isIdent && inName == SLASH) {
- val pos = inSkipToken
- val name = freshName()
- liftedGenerators += ValFrom(pos, Bind(name, Ident(nme.WILDCARD)), simpleExpr())
- Ident(name) setPos pos
-*/
} else {
simpleExpr()
}
@@ -1188,60 +1119,64 @@ self =>
* | SimpleExpr1 ArgumentExprs
*/
def simpleExpr(): Tree = {
- var t: Tree = null
var canApply = true
- inToken match {
+ val t = in.token match {
case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT | STRINGLIT |
SYMBOLLIT | TRUE | FALSE | NULL =>
- t = literal(false, false)
- case XMLSTART => t = xmlLiteral()
+ atPos(in.offset) { literal(false) }
+ case XMLSTART =>
+ xmlLiteral()
case IDENTIFIER | BACKQUOTED_IDENT | THIS | SUPER =>
- t = path(true, false)
+ path(true, false)
case USCORE =>
- val pos = inSkipToken
- val pname = freshName(pos, "x$")
- val param = atPos(pos){ makeSyntheticParam(pname) }
- placeholderParams = param :: placeholderParams
- t = atPos(pos) { Ident(pname) }
+ val start = in.offset
+ atPos(in.skipToken()) {
+ val pname = freshName(o2p(start), "x$")
+ val param = atPos(start){ makeSyntheticParam(pname) }
+ placeholderParams = param :: placeholderParams
+ Ident(pname)
+ }
case LPAREN =>
- val pos = inSkipToken
- val ts = if (inToken == RPAREN) List() else exprs()
- accept(RPAREN)
- t = Parens(ts) setPos (pos)
+ atPos(in.skipToken()) {
+ val ts = if (in.token == RPAREN) List() else exprs()
+ accept(RPAREN)
+ Parens(ts)
+ }
case LBRACE =>
- t = blockExpr()
canApply = false
+ blockExpr()
case NEW =>
- t = atPos(inSkipToken) {
+ canApply = false
+ atPos(in.skipToken()) {
val (parents, argss, self, stats) = template(false)
makeNew(parents, self, stats, argss)
}
- canApply = false
case _ =>
syntaxErrorOrIncomplete("illegal start of simple expression", true)
- t = errorTermTree
+ errorTermTree
}
simpleExprRest(t, canApply)
}
def simpleExprRest(t: Tree, canApply: Boolean): Tree = {
if (canApply) newLineOptWhenFollowedBy(LBRACE)
- inToken match {
+ in.token match {
case DOT =>
- simpleExprRest(atPos(inSkipToken) { selector(stripParens(t)) }, true)
+ in.nextToken()
+ simpleExprRest(selector(stripParens(t)), true)
case LBRACKET =>
val t1 = stripParens(t)
t1 match {
case Ident(_) | Select(_, _) =>
- val pos = if (t1.pos == NoPosition) i2p(inCurrentPos) else t1.pos
- simpleExprRest(atPos(pos) { TypeApply(t1, typeArgs(false, true)) }, true)
+ val tapp = atPos(t1.pos.start, in.offset) {
+ TypeApply(t1, typeArgs(false, true))
+ }
+ simpleExprRest(tapp, true)
case _ =>
t1
}
case LPAREN | LBRACE if (canApply) =>
- // again, position should be on idetifier, not (
- var pos = if (t.pos == NoPosition) i2p(inCurrentPos) else t.pos
- simpleExprRest(atPos(pos) {
+ val app = atPos(t.pos.start, in.offset) {
// look for anonymous function application like (f _)(x) and
// translate to (f _).apply(x), bug #460
val sel = t match {
@@ -1251,9 +1186,12 @@ self =>
stripParens(t)
}
Apply(sel, argumentExprs())
- }, true)
+ }
+ simpleExprRest(app, true)
case USCORE =>
- atPos(inSkipToken) { Typed(stripParens(t), Function(List(), EmptyTree)) }
+ atPos(t.pos.start, in.skipToken()) {
+ Typed(stripParens(t), Function(List(), EmptyTree))
+ }
case _ =>
t
}
@@ -1262,21 +1200,17 @@ self =>
/** ArgumentExprs ::= `(' [Exprs [`,']] `)'
* | [nl] BlockExpr
*/
- def argumentExprs(): List[Tree] = {
- if (inToken == LBRACE) {
+ def argumentExprs(): List[Tree] =
+ if (in.token == LBRACE)
List(blockExpr())
- } else {
- val ts = surround(LPAREN,RPAREN)(if (inToken == RPAREN) List() else exprs(), List())
- ts
- }
- }
+ else
+ surround(LPAREN, RPAREN)(if (in.token == RPAREN) List() else exprs(), List())
/** BlockExpr ::= `{' (CaseClauses | Block) `}'
*/
def blockExpr(): Tree = {
- assert(inToken == LBRACE)
val res = atPos(accept(LBRACE)) { // no need to surround
- if (inToken == CASE) Match(EmptyTree, caseClauses())
+ if (in.token == CASE) Match(EmptyTree, caseClauses())
else block()
}
accept(RBRACE)
@@ -1284,6 +1218,7 @@ self =>
}
/** Block ::= BlockStatSeq
+ * @note Return tree does not carry position.
*/
def block(): Tree = {
makeBlock(blockStatSeq(new ListBuffer[Tree]))
@@ -1294,7 +1229,7 @@ self =>
def caseClauses(): List[CaseDef] = {
val ts = new ListBuffer[CaseDef]
do { ts += caseClause()
- } while (inToken == CASE)
+ } while (in.token == CASE)
ts.toList
}
@@ -1306,14 +1241,14 @@ self =>
val gd = guard()
makeCaseDef(pat, gd, caseBlock())
}
- // IDE HOOK (so we can memoize case blocks)
+ // IDE HOOK (so we can memoize case blocks) // needed?
def caseBlock(): Tree =
atPos(accept(ARROW))(block())
/** Guard ::= if PostfixExpr
*/
def guard(): Tree =
- if (inToken == IF) { inNextToken; stripParens(postfixExpr()) }
+ if (in.token == IF) { in.nextToken(); stripParens(postfixExpr()) }
else EmptyTree
/** Enumerators ::= Generator {semi Enumerator}
@@ -1322,19 +1257,19 @@ self =>
* | val Pattern1 `=' Expr
*/
def enumerators(): List[Enumerator] = {
- val newStyle = inToken != VAL // todo: deprecate old style
- //if (!newStyle)
- // deprecationWarning(inCurrentPos, "for (val x <- ... ) has been deprecated; use for (x <- ... ) instead")
+ val newStyle = in.token != VAL // todo: deprecate old style
+ if (!newStyle)
+ deprecationWarning(in.offset, "for (val x <- ... ) has been deprecated; use for (x <- ... ) instead")
val enums = new ListBuffer[Enumerator]
generator(enums, false)
while (isStatSep) {
- inNextToken
+ in.nextToken()
if (newStyle) {
- if (inToken == IF) enums += Filter(guard())
+ if (in.token == IF) enums += makeFilter(in.offset, guard())
else generator(enums, true)
} else {
- if (inToken == VAL) generator(enums, true)
- else enums += Filter(expr())
+ if (in.token == VAL) generator(enums, true)
+ else enums += makeFilter(in.offset, expr())
}
}
enums.toList
@@ -1343,16 +1278,19 @@ self =>
/** Generator ::= Pattern1 (`<-' | '=') Expr [Guard]
*/
def generator(enums: ListBuffer[Enumerator], eqOK: Boolean) {
- if (inToken == VAL) inNextToken
- val pos = inCurrentPos;
+ val start = in.offset
+ if (in.token == VAL) in.nextToken()
val pat = pattern1(false)
- val tok = inToken
- if (tok == EQUALS && eqOK) inNextToken
+ val mid = in.offset
+ val tok = in.token
+ if (tok == EQUALS && eqOK) in.nextToken()
else accept(LARROW)
- enums += makeGenerator(pos, pat, tok == EQUALS, expr)
- if (inToken == IF) enums += Filter(guard())
+ val rhs = expr()
+ enums += makeGenerator(r2p(start, mid, in.lastOffset), pat, tok == EQUALS, rhs)
+ if (in.token == IF) enums += makeFilter(in.offset, guard())
}
- //def p2i(pos : ScanPosition) : Int;
+
+ def makeFilter(start: Int, tree: Tree) = Filter(r2p(start, tree.pos.mid, tree.pos.end), tree)
/* -------- PATTERNS ------------------------------------------- */
@@ -1362,16 +1300,10 @@ self =>
* (also eats trailing comma if it finds one)
*/
def patterns(seqOK: Boolean): List[Tree] = {
- val ts = new ListBuffer[Tree] + pattern(seqOK)
- while (inToken == COMMA) {
- val pos = inCurrentPos
- inNextToken
- if (inToken == RPAREN) {
- deprecationWarning(pos, "Trailing commas have been deprecated")
- return ts.toList
- } else {
- ts += pattern(seqOK)
- }
+ val ts = new ListBuffer[Tree] += pattern(seqOK)
+ while (in.token == COMMA) {
+ in.nextToken()
+ ts += pattern(seqOK)
}
ts.toList
}
@@ -1380,14 +1312,14 @@ self =>
* SeqPattern ::= SeqPattern1 { `|' SeqPattern1 }
*/
def pattern(seqOK: Boolean): Tree = {
- val pos = inCurrentPos
+ val start = in.offset
val t = pattern1(seqOK)
- if (isIdent && inName == BAR) {
- val ts = new ListBuffer[Tree] + t
- while (isIdent && inName == BAR) {
- inNextToken; ts += pattern1(seqOK)
+ if (isIdent && in.name == BAR) {
+ val ts = new ListBuffer[Tree] += t
+ while (isIdent && in.name == BAR) {
+ in.nextToken(); ts += pattern1(seqOK)
}
- atPos(pos) { makeAlternative(ts.toList) }
+ atPos(start) { makeAlternative(ts.toList) }
} else t
}
@@ -1401,17 +1333,13 @@ self =>
* | [SeqPattern2]
*/
def pattern1(seqOK: Boolean): Tree = {
- //if (false && /*disabled, no regexp matching*/ seqOK && !isExprIntro) {
- //atPos(inCurrentPos) { Sequence(List()) }
- //} else {
- val p = pattern2(seqOK)
- p match {
- case Ident(name) if (treeInfo.isVarPattern(p) && inToken == COLON) =>
- atPos(inSkipToken) { Typed(p, compoundType(true)) }
- case _ =>
- p
- }
- //}
+ val p = pattern2(seqOK)
+ p match {
+ case Ident(name) if (treeInfo.isVarPattern(p) && in.token == COLON) =>
+ atPos(p.pos.start, in.skipToken()) { Typed(p, compoundType(true)) }
+ case _ =>
+ p
+ }
}
/* Pattern2 ::= varid [ @ Pattern3 ]
@@ -1421,14 +1349,15 @@ self =>
*/
def pattern2(seqOK: Boolean): Tree = {
val p = pattern3(seqOK)
- if (inToken == AT) {
+ if (in.token == AT) {
p match {
case Ident(name) =>
if (name == nme.WILDCARD) {
- inNextToken; pattern3(seqOK)
+ in.nextToken()
+ pattern3(seqOK)
} else if (treeInfo.isVarPattern(p)) {
- inNextToken
- atPos(p.pos) { Bind(name, pattern3(seqOK)) }
+ in.nextToken()
+ atPos(p.pos.start) { Bind(name, pattern3(seqOK)) }
} else {
p
}
@@ -1446,14 +1375,14 @@ self =>
def pattern3(seqOK: Boolean): Tree = {
val base = opstack
var top = simplePattern(seqOK)
- if (seqOK && isIdent && inName == STAR)
- return atPos(inSkipToken)(Star(stripParens(top)))
+ if (seqOK && isIdent && in.name == STAR)
+ return atPos(top.pos.start, in.skipToken())(Star(stripParens(top)))
- while (isIdent && inName != BAR) {
+ while (isIdent && in.name != BAR) {
top = reduceStack(
- false, base, top, precedence(inName), treeInfo.isLeftAssoc(inName))
- val op = inName
- opstack = OpInfo(top, op, inCurrentPos) :: opstack
+ false, base, top, precedence(in.name), treeInfo.isLeftAssoc(in.name))
+ val op = in.name
+ opstack = OpInfo(top, op, in.offset) :: opstack
ident()
top = simplePattern(seqOK)
}
@@ -1478,57 +1407,66 @@ self =>
*
* XXX: Hook for IDE
*/
- def simplePattern(seqOK: Boolean): Tree = inToken match {
- case IDENTIFIER | BACKQUOTED_IDENT | THIS =>
- var t = stableId()
- inToken match {
- case INTLIT | LONGLIT | FLOATLIT | DOUBLELIT =>
- t match {
- case Ident(name) if name == nme.MINUS =>
- return literal(true, true)
- case _ =>
- }
- case _ =>
- }
-/* not yet
- if (inToken == LBRACKET)
- atPos(inCurrentPos) {
- val ts = typeArgs(true, false)
- accept(LPAREN)
- val ps = if (inToken == RPAREN) List() else patterns(true, false)
+ def simplePattern(seqOK: Boolean): Tree = {
+ val start = in.offset
+ in.token match {
+ case IDENTIFIER | BACKQUOTED_IDENT | THIS =>
+ var t = stableId()
+ in.token match {
+ case INTLIT | LONGLIT | FLOATLIT | DOUBLELIT =>
+ t match {
+ case Ident(name) if name == nme.MINUS =>
+ return atPos(start) { literal(true) }
+ case _ =>
+ }
+ case _ =>
+ }
+ /* not yet
+ if (in.token == LBRACKET)
+ atPos(in.offset) {
+ val ts = typeArgs(true, false)
+ accept(LPAREN)
+ val ps = if (in.token == RPAREN) List() else patterns(true, false)
+ accept(RPAREN)
+ Apply(TypeApply(convertToTypeId(t), ts), ps)
+ }
+ else */
+ if (in.token == LPAREN)
+ atPos(start, in.offset) { Apply(t, argumentPatterns()) }
+ else t
+ case USCORE =>
+ in.nextToken()
+ atPos(start) { Ident(nme.WILDCARD) }
+ case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT |
+ STRINGLIT | SYMBOLLIT | TRUE | FALSE | NULL =>
+ atPos(start) { literal(false) }
+ case LPAREN =>
+ in.nextToken()
+ atPos(start) {
+ val ps = if (in.token == RPAREN) List() else patterns(false)
accept(RPAREN)
- Apply(TypeApply(convertToTypeId(t), ts), ps)
+ Parens(ps)
}
- else */
- if (inToken == LPAREN) {
- atPos(t.pos) { Apply(t, argumentPatterns()) }
- } else t
- case USCORE =>
- atPos(inSkipToken) { Ident(nme.WILDCARD) }
- case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT |
- STRINGLIT | SYMBOLLIT | TRUE | FALSE | NULL =>
- literal(true, false)
- case LPAREN =>
- val pos = inSkipToken
- val ps = if (inToken == RPAREN) List() else patterns(false)
- accept(RPAREN)
- Parens(ps) setPos (pos)
- case XMLSTART =>
- xmlLiteralPattern()
- case _ =>
- syntaxErrorOrIncomplete("illegal start of simple pattern", true)
- errorPatternTree
+ case XMLSTART =>
+ xmlLiteralPattern()
+ case _ =>
+ syntaxErrorOrIncomplete("illegal start of simple pattern", true)
+ errorPatternTree
+ }
}
def argumentPatterns(): List[Tree] = {
accept(LPAREN)
- val ps = if (inToken == RPAREN) List() else patterns(true)
+ val ps = if (in.token == RPAREN) List() else patterns(true)
accept(RPAREN)
ps
}
/* -------- MODIFIERS and ANNOTATIONS ------------------------------------------- */
+ /** Drop `private' modifier when follwed by a qualifier.
+ * Conract `abstract' and `override' to ABSOVERRIDE
+ */
private def normalize(mods: Modifiers): Modifiers =
if ((mods hasFlag Flags.PRIVATE) && mods.privateWithin != nme.EMPTY.toTypeName)
mods &~ Flags.PRIVATE
@@ -1538,8 +1476,8 @@ self =>
mods
private def addMod(mods: Modifiers, mod: Long): Modifiers = {
- if (mods hasFlag mod) syntaxError(inCurrentPos, "repeated modifier", false)
- inNextToken
+ if (mods hasFlag mod) syntaxError(in.offset, "repeated modifier", false)
+ in.nextToken()
mods | mod
}
@@ -1547,11 +1485,11 @@ self =>
*/
def accessQualifierOpt(mods: Modifiers): Modifiers = {
var result = mods
- if (inToken == LBRACKET) {
- inNextToken
+ if (in.token == LBRACKET) {
+ in.nextToken()
if (mods.privateWithin != nme.EMPTY.toTypeName)
syntaxError("duplicate private/protected qualifier", false)
- result = if (inToken == THIS) { inNextToken; mods | Flags.LOCAL }
+ result = if (in.token == THIS) { in.nextToken(); mods | Flags.LOCAL }
else Modifiers(mods.flags, ident().toTypeName)
accept(RBRACKET)
}
@@ -1561,9 +1499,9 @@ self =>
/** AccessModifier ::= (private | protected) [AccessQualifier]
*/
def accessModifierOpt(): Modifiers = normalize {
- inToken match {
- case PRIVATE => inNextToken; accessQualifierOpt(Modifiers(Flags.PRIVATE))
- case PROTECTED => inNextToken; accessQualifierOpt(Modifiers(Flags.PROTECTED))
+ in.token match {
+ case PRIVATE => in.nextToken(); accessQualifierOpt(Modifiers(Flags.PRIVATE))
+ case PROTECTED => in.nextToken(); accessQualifierOpt(Modifiers(Flags.PROTECTED))
case _ => NoMods
}
}
@@ -1574,7 +1512,7 @@ self =>
* | override
*/
def modifiers(): Modifiers = normalize {
- def loop(mods: Modifiers): Modifiers = inToken match {
+ def loop(mods: Modifiers): Modifiers = in.token match {
case ABSTRACT =>
loop(addMod(mods, Flags.ABSTRACT))
case FINAL =>
@@ -1592,7 +1530,7 @@ self =>
case LAZY =>
loop(addMod(mods, Flags.LAZY))
case NEWLINE =>
- inNextToken
+ in.nextToken()
loop(mods)
case _ =>
mods
@@ -1604,7 +1542,7 @@ self =>
* LocalModifier ::= abstract | final | sealed | implicit | lazy
*/
def localModifiers(): Modifiers = {
- def loop(mods: Modifiers): Modifiers = inToken match {
+ def loop(mods: Modifiers): Modifiers = in.token match {
case ABSTRACT =>
loop(addMod(mods, Flags.ABSTRACT))
case FINAL =>
@@ -1626,8 +1564,8 @@ self =>
*/
def annotations(skipNewLines: Boolean): List[Annotation] = {
var annots = new ListBuffer[Annotation]
- while (inToken == AT) {
- inNextToken
+ while (in.token == AT) {
+ in.nextToken()
annots += annotationExpr()
if (skipNewLines) newLineOpt()
}
@@ -1639,31 +1577,33 @@ self =>
*/
def annotationExpr(): Annotation = {
def nameValuePair(): Tree = {
- var pos = inCurrentPos
- accept(VAL)
- val aname = ident()
- accept(EQUALS)
- val rhs = stripParens(prefixExpr())
- atPos(pos) { ValDef(NoMods, aname, TypeTree(), rhs) }
- }
- val pos = inCurrentPos
- var t: Tree = convertToTypeId(stableId())
- if (inToken == LBRACKET)
- t = atPos(inCurrentPos)(AppliedTypeTree(t, typeArgs(false, false)))
- val args = if (inToken == LPAREN) argumentExprs() else List()
- newLineOptWhenFollowedBy(LBRACE)
- val nameValuePairs: List[Tree] = if (inToken == LBRACE) {
- inNextToken
- val nvps = new ListBuffer[Tree] + nameValuePair()
- while (inToken == COMMA) {
- inNextToken
- nvps += nameValuePair()
+ atPos(in.offset) {
+ accept(VAL)
+ val aname = ident()
+ accept(EQUALS)
+ val rhs = stripParens(prefixExpr())
+ ValDef(NoMods, aname, TypeTree(), rhs)
}
- accept(RBRACE)
- nvps.toList
- } else List()
- val constr = atPos(pos) { New(t, List(args)) }
- Annotation(constr, nameValuePairs) setPos pos
+ }
+ atPos(in.offset) {
+ var t: Tree = convertToTypeId(stableId())
+ if (in.token == LBRACKET)
+ t = AppliedTypeTree(t, typeArgs(false, false))
+ val args = if (in.token == LPAREN) argumentExprs() else List()
+ newLineOptWhenFollowedBy(LBRACE)
+ val nameValuePairs: List[Tree] = if (in.token == LBRACE) {
+ in.nextToken()
+ val nvps = new ListBuffer[Tree] += nameValuePair()
+ while (in.token == COMMA) {
+ in.nextToken()
+ nvps += nameValuePair()
+ }
+ accept(RBRACE)
+ nvps.toList
+ } else List()
+ val constr = New(t, List(args))
+ Annotation(constr, nameValuePairs)
+ }
}
/* -------- PARAMETERS ------------------------------------------- */
@@ -1681,73 +1621,70 @@ self =>
var implicitmod = 0
var caseParam = ofCaseClass
def param(): ValDef = {
- var pos = inCurrentPos
-
- {
- val annots = annotations(false)
- var mods = Modifiers(Flags.PARAM)
- if (owner.isTypeName) {
- mods = modifiers() | Flags.PARAMACCESSOR
- if (mods.hasFlag(Flags.LAZY)) syntaxError("lazy modifier not allowed here. Use call-by-name parameters instead", false)
- if (inToken == VAL) {
- inNextToken
- } else if (inToken == VAR) {
- mods = mods | Flags.MUTABLE
- inNextToken
- } else {
- if (mods.flags != Flags.PARAMACCESSOR) accept(VAL)
- if (!(caseParam)) mods = mods | Flags.PRIVATE | Flags.LOCAL
- }
- if (caseParam) mods = mods | Flags.CASEACCESSOR
+ val start = in.offset
+ val annots = annotations(false)
+ var mods = Modifiers(Flags.PARAM)
+ if (owner.isTypeName) {
+ mods = modifiers() | Flags.PARAMACCESSOR
+ if (mods.hasFlag(Flags.LAZY)) syntaxError("lazy modifier not allowed here. Use call-by-name parameters instead", false)
+ if (in.token == VAL) {
+ in.nextToken()
+ } else if (in.token == VAR) {
+ mods |= Flags.MUTABLE
+ in.nextToken()
+ } else if (!caseParam) {
+ mods |= Flags.PRIVATE | Flags.LOCAL
}
- val namePos = inCurrentPos
- val name = ident()
- if (name != nme.ERROR) pos = namePos
- var bynamemod = 0
- val tpt =
- if (settings.Xexperimental.value && !owner.isTypeName && inToken != COLON) {
- TypeTree()
- } else { // XX-METHOD-INFER
- accept(COLON)
- if (inToken == ARROW) {
- if (owner.isTypeName && !mods.hasFlag(Flags.LOCAL))
- syntaxError(
- inCurrentPos,
- (if (mods.hasFlag(Flags.MUTABLE)) "`var'" else "`val'") +
- " parameters may not be call-by-name", false)
- else bynamemod = Flags.BYNAMEPARAM
- }
- paramType()
+ if (caseParam) {
+ mods |= Flags.CASEACCESSOR
+ }
+ }
+ val nameOffset = in.offset
+ val name = ident()
+ var bynamemod = 0
+ val tpt =
+ if (settings.Xexperimental.value && !owner.isTypeName && in.token != COLON) {
+ TypeTree()
+ } else { // XX-METHOD-INFER
+ accept(COLON)
+ if (in.token == ARROW) {
+ if (owner.isTypeName && !mods.hasFlag(Flags.LOCAL))
+ syntaxError(
+ in.offset,
+ (if (mods.hasFlag(Flags.MUTABLE)) "`var'" else "`val'") +
+ " parameters may not be call-by-name", false)
+ else bynamemod = Flags.BYNAMEPARAM
}
- atPos(pos){
- ValDef((mods | implicitmod | bynamemod) withAnnotations annots, name, tpt, EmptyTree)
+ paramType()
}
+ atPos(start, if (name == nme.ERROR) start else nameOffset) {
+ ValDef((mods | implicitmod | bynamemod) withAnnotations annots, name, tpt, EmptyTree)
}
}
def paramClause(): List[ValDef] = {
val params = new ListBuffer[ValDef]
- if (inToken != RPAREN) {
- if (inToken == IMPLICIT) {
+ if (in.token != RPAREN) {
+ if (in.token == IMPLICIT) {
if (!implicitViews.isEmpty)
syntaxError("cannot have both view bounds `<%' and implicit parameters", false)
- inNextToken
+ in.nextToken()
implicitmod = Flags.IMPLICIT
}
params += param()
- while (inToken == COMMA) {
- inNextToken; params += param()
+ while (in.token == COMMA) {
+ in.nextToken(); params += param()
}
}
params.toList
}
val vds = new ListBuffer[List[ValDef]]
- val pos = inCurrentPos
+ val start = in.offset
newLineOptWhenFollowedBy(LPAREN)
- if (ofCaseClass && inToken != LPAREN)
- deprecationWarning(inCurrentPos, "case classes without a parameter list have been deprecated;\n"+
+ if (ofCaseClass && in.token != LPAREN)
+ deprecationWarning(in.offset, "case classes without a parameter list have been deprecated;\n"+
"use either case objects or case classes with `()' as parameter list.")
- while (implicitmod == 0 && inToken == LPAREN) {
- inNextToken
+ while (implicitmod == 0 && in.token == LPAREN) {
+ in.nextToken()
vds += paramClause()
accept(RPAREN)
caseParam = false
@@ -1757,28 +1694,28 @@ self =>
if (owner == nme.CONSTRUCTOR &&
(result.isEmpty ||
(!result.head.isEmpty && result.head.head.mods.hasFlag(Flags.IMPLICIT))))
- if (inToken == LBRACKET)
- syntaxError(pos, "no type parameters allowed here", false)
- else if(inToken == EOF)
+ if (in.token == LBRACKET)
+ syntaxError(in.offset, "no type parameters allowed here", false)
+ else if(in.token == EOF)
incompleteInputError("auxiliary constructor needs non-implicit parameter list")
else
- syntaxError(pos, "auxiliary constructor needs non-implicit parameter list", false)
+ syntaxError(start, "auxiliary constructor needs non-implicit parameter list", false)
addImplicitViews(owner, result, implicitViews)
}
/** ParamType ::= Type | `=>' Type | Type `*'
*/
def paramType(): Tree =
- if (inToken == ARROW)
- atPos(inSkipToken) {
+ if (in.token == ARROW)
+ atPos(in.skipToken()) {
AppliedTypeTree(
- rootScalaDot(nme.BYNAME_PARAM_CLASS_NAME.toTypeName), List(typ()))
+ rootScalaDot(nme.BYNAME_PARAM_CLASS_NAME.toTypeName), List(typ()))
}
else {
val t = typ()
- if (isIdent && inName == STAR) {
- inNextToken
- atPos(t.pos) {
+ if (isIdent && in.name == STAR) {
+ in.nextToken()
+ atPos(t.pos.start, t.pos.mid) {
AppliedTypeTree(
rootScalaDot(nme.REPEATED_PARAM_CLASS_NAME.toTypeName), List(t))
}
@@ -1794,38 +1731,40 @@ self =>
*/
def typeParamClauseOpt(owner: Name, implicitViewBuf: ListBuffer[Tree]): List[TypeDef] = {
def typeParam(): TypeDef = {
+ val start = in.offset
var mods = Modifiers(Flags.PARAM)
if (owner.isTypeName && isIdent) {
- if (inName == PLUS) {
- inNextToken
- mods = mods | Flags.COVARIANT
- } else if (inName == MINUS) {
- inNextToken
- mods = mods | Flags.CONTRAVARIANT
+ if (in.name == PLUS) {
+ in.nextToken()
+ mods |= Flags.COVARIANT
+ } else if (in.name == MINUS) {
+ in.nextToken()
+ mods |= Flags.CONTRAVARIANT
}
}
- val pos = inCurrentPos
+ val nameOffset = in.offset
val pname =
- (if (inToken == USCORE) { // @M! also allow underscore
- inNextToken
+ (if (in.token == USCORE) { // @M! also allow underscore
+ in.nextToken()
nme.WILDCARD
} else ident()).toTypeName
-
- val tparams = typeParamClauseOpt(pname, null) // @M TODO null --> no higher-order view bounds for now
- val param = atPos(pos) { TypeDef(mods, pname, tparams, typeBounds()) }
- if (inToken == VIEWBOUND && (implicitViewBuf ne null))
- implicitViewBuf += atPos(inSkipToken) {
+ val param = atPos(start, nameOffset) {
+ val tparams = typeParamClauseOpt(pname, null) // @M TODO null --> no higher-order view bounds for now
+ TypeDef(mods, pname, tparams, typeBounds())
+ }
+ if (in.token == VIEWBOUND && (implicitViewBuf ne null))
+ implicitViewBuf += atPos(start, in.skipToken()) {
makeFunctionTypeTree(List(Ident(pname)), typ())
}
param
}
val params = new ListBuffer[TypeDef]
newLineOptWhenFollowedBy(LBRACKET)
- if (inToken == LBRACKET) {
- inNextToken
+ if (in.token == LBRACKET) {
+ in.nextToken()
params += typeParam()
- while (inToken == COMMA) {
- inNextToken
+ while (in.token == COMMA) {
+ in.nextToken()
params += typeParam()
}
accept(RBRACKET)
@@ -1841,7 +1780,7 @@ self =>
bound(SUBTYPE, nme.Any))
def bound(tok: Int, default: Name): Tree =
- if (inToken == tok) { inNextToken; typ() }
+ if (in.token == tok) { in.nextToken(); typ() }
else rootScalaDot(default.toTypeName)
/* -------- DEFS ------------------------------------------- */
@@ -1851,9 +1790,9 @@ self =>
*/
def importClause(): List[Tree] = {
accept(IMPORT)
- val ts = new ListBuffer[Tree] + importExpr()
- while (inToken == COMMA) {
- inNextToken; ts += importExpr()
+ val ts = new ListBuffer[Tree] += importExpr()
+ while (in.token == COMMA) {
+ in.nextToken(); ts += importExpr()
}
ts.toList
}
@@ -1861,47 +1800,49 @@ self =>
/** ImportExpr ::= StableId `.' (Id | `_' | ImportSelectors)
* XXX: Hook for IDE
*/
- def importExpr(): Tree =
- atPos(inCurrentPos) {
- var t: Tree = null
- //var pos : ScanPosition = null.asInstanceOf[ScanPosition]
- var pos : Int = -1
- if (inToken == THIS) {
- t = atPos(inCurrentPos) { This(nme.EMPTY.toTypeName) }
- t = atPos(accept(DOT)) { selector(t) }
- pos = accept(DOT)
+ def importExpr(): Tree = {
+ val start = in.offset
+ var t: Tree = null
+ if (in.token == THIS) {
+ in.nextToken()
+ t = atPos(start) { This(nme.EMPTY.toTypeName) }
+ accept(DOT)
+ t = selector(t)
+ accept(DOT)
+ } else {
+ val id = atPos(start) { Ident(ident()) }
+ accept(DOT)
+ if (in.token == THIS) {
+ in.nextToken()
+ t = atPos(start) { This(id.name.toTypeName) }
+ accept(DOT)
+ t = selector(t)
+ accept(DOT)
} else {
- val i = atPos(inCurrentPos) { Ident(ident()) }
- pos = accept(DOT)
- if (inToken == THIS) {
- inNextToken
- t = atPos(i.pos) { This(i.name.toTypeName) }
- t = atPos(accept(DOT)) { selector(t) }
- pos = accept(DOT)
- } else {
- t = i
- }
+ t = id
}
- def loop: Tree =
- if (inToken == USCORE) {
- inNextToken
- Import(t, List((nme.WILDCARD, null)))
- } else if (inToken == LBRACE) {
- Import(t, importSelectors())
- } else {
- val identPos = inCurrentPos
- val name = ident() // @S: use position of identifier, not dot!
- pos = if (name == nme.ERROR) pos else identPos
- if (inToken == DOT) {
- t = atPos(pos) { Select(t, name) }
- pos = accept(DOT)
- loop
- } else {
- Import(t, List((name, name)))
+ }
+ def loop(): Tree =
+ if (in.token == USCORE) {
+ in.nextToken()
+ Import(t, List((nme.WILDCARD, null)))
+ } else if (in.token == LBRACE) {
+ Import(t, importSelectors())
+ } else {
+ val nameOffset = in.offset
+ val name = ident()
+ if (in.token == DOT) {
+ t = atPos(start, if (name == nme.ERROR) in.offset else nameOffset) {
+ Select(t, name)
}
+ in.nextToken()
+ loop()
+ } else {
+ Import(t, List((name, name)))
}
- loop
- }
+ }
+ atPos(start) { loop() }
+ }
/** ImportSelectors ::= `{' {ImportSelector `,'} (ImportSelector | `_') `}'
*/
@@ -1909,8 +1850,8 @@ self =>
val names = new ListBuffer[(Name, Name)]
accept(LBRACE)
var isLast = importSelector(names)
- while (!isLast && inToken == COMMA) {
- inNextToken
+ while (!isLast && in.token == COMMA) {
+ in.nextToken()
isLast = importSelector(names)
}
accept(RBRACE)
@@ -1920,15 +1861,15 @@ self =>
/** ImportSelector ::= Id [`=>' Id | `=>' `_']
*/
def importSelector(names: ListBuffer[(Name, Name)]): Boolean =
- if (inToken == USCORE) {
- inNextToken; names += ((nme.WILDCARD, null)); true
+ if (in.token == USCORE) {
+ in.nextToken(); names += ((nme.WILDCARD, null)); true
} else {
val name = ident()
names += ((
name,
- if (inToken == ARROW) {
- inNextToken
- if (inToken == USCORE) { inNextToken; nme.WILDCARD } else ident()
+ if (in.token == ARROW) {
+ in.nextToken()
+ if (in.token == USCORE) { in.nextToken(); nme.WILDCARD } else ident()
} else {
name
}))
@@ -1948,7 +1889,7 @@ self =>
def defOrDcl(mods: Modifiers): List[Tree] = {
if ((mods hasFlag Flags.LAZY) && in.token != VAL)
syntaxError("lazy not allowed here. Only vals can be lazy", false)
- inToken match {
+ in.token match {
case VAL =>
patDefOrDcl(mods)
case VAR =>
@@ -1956,8 +1897,6 @@ self =>
case DEF =>
List(funDefOrDcl(mods))
case TYPE =>
- inNextToken
- newLinesOpt()
List(typeDefOrDcl(mods))
case _ =>
List(tmplDef(mods))
@@ -1983,18 +1922,18 @@ self =>
var newmods = mods
val lhsBuf = new ListBuffer[Tree]
do {
- inNextToken
+ in.nextToken()
val p = pattern2(false)
lhsBuf += stripParens(p)
- } while (inToken == COMMA)
+ } while (in.token == COMMA)
val lhs = lhsBuf.toList
val tp = typedOpt()
- val rhs =
- if (tp.isEmpty || inToken == EQUALS) {
+ var rhs =
+ if (tp.isEmpty || in.token == EQUALS) {
accept(EQUALS)
if (!tp.isEmpty && newmods.hasFlag(Flags.MUTABLE) &&
- (lhs.toList forall (_.isInstanceOf[Ident])) && inToken == USCORE) {
- inNextToken
+ (lhs.toList forall (_.isInstanceOf[Ident])) && in.token == USCORE) {
+ in.nextToken()
newmods = newmods | Flags.DEFAULTINIT
EmptyTree
} else {
@@ -2004,26 +1943,16 @@ self =>
newmods = newmods | Flags.DEFERRED
EmptyTree
}
- var originalUsed = false
def mkDefs(p: Tree): List[Tree] = {
//Console.println("DEBUG: p = "+p.toString()); // DEBUG
val trees =
- makePatDef(newmods,
- if (tp.isEmpty)
- p
- else
- Typed(p, tp),
- if (inIDE && !originalUsed) {
- // because duplicates have weaker status than originals
- // need an original.
- originalUsed = true
- rhs
- } else rhs.duplicate) map atPos(p.pos)
- if (newmods.hasFlag(Flags.DEFERRED)) {
+ makePatDef(newmods, if (tp.isEmpty) p else Typed(p, tp), rhs) map
+ atPos(p.pos.start, p.pos.mid)
+ rhs = rhs.duplicate
+ if (newmods hasFlag Flags.DEFERRED) {
trees match {
case List(ValDef(_, _, _, EmptyTree)) =>
- if (mods.hasFlag(Flags.LAZY))
- syntaxError(p.pos, "lazy values may not be abstract", false)
+ if (mods.hasFlag(Flags.LAZY)) syntaxError(p.pos, "lazy values may not be abstract", false)
case _ => syntaxError(p.pos, "pattern definition may not be abstract", false)
}
}
@@ -2039,14 +1968,14 @@ self =>
var newmods = mods | Flags.MUTABLE
val lhs = new ListBuffer[(Int, Name)]
do {
- inNextToken
- lhs += (inCurrentPos, ident())
- } while (inToken == COMMA)
+ in.nextToken()
+ lhs += (in.offset, ident())
+ } while (in.token == COMMA)
val tp = typedOpt()
- val rhs = if (tp.isEmpty || inToken == EQUALS) {
+ val rhs = if (tp.isEmpty || in.token == EQUALS) {
accept(EQUALS)
- if (!tp.isEmpty && inToken == USCORE) {
- inNextToken
+ if (!tp.isEmpty && in.token == USCORE) {
+ in.nextToken()
EmptyTree
} else {
expr()
@@ -2072,22 +2001,20 @@ self =>
* FunSig ::= id [FunTypeParamClause] ParamClauses
*/
def funDefOrDcl(mods: Modifiers): Tree = {
- var pos = inSkipToken // position of `def'
- if (inToken == THIS) {
- atPos(inCurrentPos) {
- inNextToken
+ val start = in.skipToken()
+ if (in.token == THIS) {
+ atPos(start, in.skipToken()) {
val vparamss = paramClauses(nme.CONSTRUCTOR, implicitClassViews map (_.duplicate), false)
newLineOptWhenFollowedBy(LBRACE)
- val rhs = if (inToken == LBRACE) constrBlock(vparamss)
+ 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 namePos = inCurrentPos
+ val nameOffset = in.offset
val name = ident()
- if (name != nme.ERROR) pos = namePos
- atPos(pos) {
+ atPos(start, if (name == nme.ERROR) start else nameOffset) {
// implicitViewBuf is for view bounded type parameters of the form
// [T <% B]; it contains the equivalent implicit parameter, i.e. (implicit p: T => B)
val implicitViewBuf = new ListBuffer[Tree]
@@ -2096,25 +2023,26 @@ self =>
newLineOptWhenFollowedBy(LBRACE)
var restype = typedOpt()
val rhs =
- if (isStatSep || inToken == RBRACE) {
+ if (isStatSep || in.token == RBRACE) {
if (restype.isEmpty) restype = scalaUnitConstr
- newmods = newmods | Flags.DEFERRED
+ newmods |= Flags.DEFERRED
EmptyTree
- } else if (restype.isEmpty && inToken == LBRACE) {
+ } else if (restype.isEmpty && in.token == LBRACE) {
restype = scalaUnitConstr
blockExpr()
- } else equalsExpr()
+ } else {
+ equalsExpr()
+ }
DefDef(newmods, name, tparams, vparamss, restype, rhs)
}
}
}
-
/** ConstrExpr ::= SelfInvocation
* | ConstrBlock
*/
def constrExpr(vparamss: List[List[ValDef]]): Tree =
- if (inToken == LBRACE) constrBlock(vparamss)
+ if (in.token == LBRACE) constrBlock(vparamss)
else Block(List(selfInvocation(vparamss)), Literal(()))
/** SelfInvocation ::= this ArgumentExprs {ArgumentExprs}
@@ -2123,7 +2051,7 @@ self =>
atPos(accept(THIS)) {
newLineOptWhenFollowedBy(LBRACE)
var t = Apply(Ident(nme.CONSTRUCTOR), argumentExprs())
- while (inToken == LPAREN || inToken == LBRACE) {
+ while (in.token == LPAREN || in.token == LBRACE) {
t = Apply(t, argumentExprs())
newLineOptWhenFollowedBy(LBRACE)
}
@@ -2134,33 +2062,28 @@ self =>
/** ConstrBlock ::= `{' SelfInvocation {semi BlockStat} `}'
*/
def constrBlock(vparamss: List[List[ValDef]]): Tree =
- atPos(inSkipToken) {
+ atPos(in.skipToken()) {
val statlist = new ListBuffer[Tree]
statlist += selfInvocation(vparamss)
- val stats = if (isStatSep) { inNextToken; blockStatSeq(statlist) }
+ val stats = if (isStatSep) { in.nextToken(); blockStatSeq(statlist) }
else statlist.toList
accept(RBRACE)
Block(stats, Literal(()))
}
- /** TypeDef ::= Id [TypeParamClause] `=' Type
- * TypeDcl ::= Id [TypeParamClause] TypeBounds
+ /** TypeDef ::= type Id [TypeParamClause] `=' Type
+ * TypeDcl ::= type Id [TypeParamClause] TypeBounds
*/
- def typeDefOrDcl(mods: Modifiers): Tree =
- atPos(inCurrentPos) {
+ def typeDefOrDcl(mods: Modifiers): Tree = {
+ val start = in.skipToken()
+ newLinesOpt()
+ atPos(start, in.offset) {
val name = ident().toTypeName
-
// @M! a type alias as well as an abstract type may declare type parameters
- val tparams = inToken match {
- case LBRACKET =>
- typeParamClauseOpt(name, null)
- case _ =>
- Nil
- }
-
- inToken match {
+ val tparams = typeParamClauseOpt(name, null)
+ in.token match {
case EQUALS =>
- inNextToken
+ in.nextToken()
TypeDef(mods, name, tparams, typ())
case SUPERTYPE | SUBTYPE | SEMI | NEWLINE | NEWLINES | COMMA | RBRACE =>
TypeDef(mods | Flags.DEFERRED, name, tparams, typeBounds())
@@ -2169,6 +2092,7 @@ self =>
EmptyTree
}
}
+ }
/** Hook for IDE, for top-level classes/objects */
def topLevelTmplDef: Tree = {
@@ -2183,7 +2107,7 @@ self =>
*/
def tmplDef(mods: Modifiers): Tree = {
if (mods.hasFlag(Flags.LAZY)) syntaxError("classes cannot be lazy", false)
- inToken match {
+ in.token match {
case TRAIT =>
classDef(mods | Flags.TRAIT | Flags.ABSTRACT)
case CLASS =>
@@ -2205,11 +2129,10 @@ self =>
* TraitDef ::= Id [TypeParamClause] RequiresTypeOpt TraitTemplateOpt
*/
def classDef(mods: Modifiers): ClassDef = {
- var pos = inSkipToken
- var namePos = inCurrentPos
+ val start = in.skipToken()
+ val nameOffset = in.offset
val name = ident().toTypeName
- if (name != nme.ERROR) pos = namePos
- atPos(pos) {
+ atPos(start, if (name == nme.ERROR.toTypeName) start else nameOffset) {
val savedViews = implicitClassViews
val implicitViewBuf = new ListBuffer[Tree]
val tparams = typeParamClauseOpt(name, implicitViewBuf)
@@ -2222,24 +2145,13 @@ self =>
val (constrMods, vparamss) =
if (mods.hasFlag(Flags.TRAIT)) (Modifiers(Flags.TRAIT), List())
else (accessModifierOpt(), paramClauses(name, implicitClassViews, mods.hasFlag(Flags.CASE)))
- val thistpe = requiresTypeOpt()
- var mods1 =
- if (mods hasFlag Flags.TRAIT)
- if (inToken == SUBTYPE) mods | Flags.DEFERRED
- else mods
- else if (inToken == SUBTYPE) {
- syntaxError("classes are not allowed to be virtual", false)
- mods
- }
- else
- mods
- var template = templateOpt(mods1, name, constrMods withAnnotations constrAnnots, vparamss)
- if (!thistpe.isEmpty) {
- if (template.self.isEmpty) {
- template = copy.Template(
- template, template.parents, makeSelfDef(nme.WILDCARD, thistpe), template.body)
- } else syntaxError("`requires' cannot be combined with explicit self type", false)
+ var mods1 = mods
+ if (mods hasFlag Flags.TRAIT) {
+ if (settings.Xexperimental.value && in.token == SUBTYPE) mods1 |= Flags.DEFERRED
+ } else if (in.token == SUBTYPE) {
+ syntaxError("classes are not allowed to be virtual", false)
}
+ var template = templateOpt(mods1, name, constrMods withAnnotations constrAnnots, vparamss)
if (isInterface(mods1, template.body)) mods1 |= Flags.INTERFACE
val result = ClassDef(mods1, name, tparams, template)
implicitClassViews = savedViews
@@ -2250,29 +2162,27 @@ self =>
/** ObjectDef ::= Id ClassTemplateOpt
*/
def objectDef(mods: Modifiers): ModuleDef = {
- var pos = inSkipToken
- var namePos = inCurrentPos
- val name = ident().toTermName
- if (name != nme.ERROR) pos = namePos
- atPos(pos) {
- val mods1 = if (inToken == SUBTYPE) mods | Flags.DEFERRED else mods
+ val start = in.skipToken()
+ val nameOffset = in.offset
+ val name = ident()
+ atPos(start, if (name == nme.ERROR) start else nameOffset) {
+ val mods1 = if (in.token == SUBTYPE) mods | Flags.DEFERRED else mods
val template = templateOpt(mods1, name, NoMods, List())
ModuleDef(mods1, name, template)
}
}
-
/** ClassParents ::= AnnotType {`(' [Exprs [`,']] `)'} {with AnnotType}
* TraitParents ::= AnnotType {with AnnotType}
*/
def templateParents(isTrait: Boolean): (List[Tree], List[List[Tree]]) = {
- val parents = new ListBuffer[Tree] + annotType(false)
+ val parents = new ListBuffer[Tree] += annotType(false)
val argss = new ListBuffer[List[Tree]]
- if (inToken == LPAREN && !isTrait)
- do { argss += argumentExprs() } while (inToken == LPAREN)
+ if (in.token == LPAREN && !isTrait)
+ do { argss += argumentExprs() } while (in.token == LPAREN)
else argss += List()
- while (inToken == WITH) {
- inNextToken
+ while (in.token == WITH) {
+ in.nextToken()
parents += annotType(false)
}
(parents.toList, argss.toList)
@@ -2285,21 +2195,21 @@ self =>
*/
def template(isTrait: Boolean): (List[Tree], List[List[Tree]], ValDef, List[Tree]) = {
newLineOptWhenFollowedBy(LBRACE)
- if (inToken == LBRACE) {
+ if (in.token == LBRACE) {
// @S: pre template body cannot stub like post body can!
val (self, body) = templateBody(true)
- if (inToken == WITH && self.isEmpty) {
+ if (in.token == WITH && self.isEmpty) {
val earlyDefs: List[Tree] = body flatMap {
case vdef @ ValDef(mods, name, tpt, rhs) if !(mods hasFlag Flags.DEFERRED) =>
List(copy.ValDef(vdef, mods | Flags.PRESUPER, name, tpt, rhs))
case tdef @ TypeDef(mods, name, tparams, rhs) =>
List(copy.TypeDef(tdef, mods | Flags.PRESUPER, name, tparams, rhs))
case stat if !stat.isEmpty =>
- syntaxError(stat.pos, "only type definitions and concrete field definitions allowed in early object initialization section", false)
+ syntaxError(stat.pos, "only type definitions and concrete field definitions allowed in early object initialization section", false)
List()
case _ => List()
}
- inNextToken
+ in.nextToken()
val (parents, argss) = templateParents(isTrait)
val (self1, body1) = templateBodyOpt(isTrait)
(parents, argss, self1, earlyDefs ::: body1)
@@ -2319,16 +2229,16 @@ self =>
/** ClassTemplateOpt ::= 'extends' ClassTemplate | [['extends'] TemplateBody]
* TraitTemplateOpt ::= TraitExtends TraitTemplate | [['extends'] TemplateBody] | '<:' TemplateBody
* TraitExtends ::= 'extends' | `<:'
+ * @note leaves result unpositioned.
*/
def templateOpt(mods: Modifiers, name: Name, constrMods: Modifiers,
vparamss: List[List[ValDef]]): Template = {
- val pos = inCurrentPos;
val (parents0, argss, self, body) =
- if (inToken == EXTENDS || settings.Xexperimental.value && (mods hasFlag Flags.TRAIT) && inToken == SUBTYPE) {
- inNextToken
+ if (in.token == EXTENDS || settings.Xexperimental.value && (mods hasFlag Flags.TRAIT) && in.token == SUBTYPE) {
+ in.nextToken()
template(mods hasFlag Flags.TRAIT)
- } else if ((inToken == SUBTYPE) && (mods hasFlag Flags.TRAIT)) {
- inNextToken
+ } else if ((in.token == SUBTYPE) && (mods hasFlag Flags.TRAIT)) {
+ in.nextToken()
template(true)
} else {
newLineOptWhenFollowedBy(LBRACE)
@@ -2341,12 +2251,7 @@ self =>
if (parents.isEmpty)
parents = List(scalaAnyRefConstr)
if (mods.hasFlag(Flags.CASE)) parents = parents ::: List(productConstr)
- val tree = Template(parents, self, constrMods, vparamss, argss, body)
- // @S: if nothing parsed, don't use next position!
- // @S: if primary constructor does not always have the same position, then the IDE gets confused.
- // @S: since build compiler is used to generate IDE files, don't set position here!
- tree
- // if (pos == inCurrentPos || inIDE) tree else atPos(pos) {tree}
+ Template(parents, self, constrMods, vparamss, argss, body)
}
/* -------- TEMPLATES ------------------------------------------- */
@@ -2362,10 +2267,10 @@ self =>
}
def templateBodyOpt(traitParentSeen: Boolean): (ValDef, List[Tree]) = {
newLineOptWhenFollowedBy(LBRACE)
- if (inToken == LBRACE) {
+ if (in.token == LBRACE) {
templateBody(false)
} else {
- if (inToken == LPAREN)
+ if (in.token == LPAREN)
syntaxError((if (traitParentSeen) "parents of traits" else "traits or objects")+
" may not have parameters", true)
(emptyValDef, List())
@@ -2383,18 +2288,39 @@ self =>
/* -------- STATSEQS ------------------------------------------- */
+ /** Create a tree representing a packaging */
+ def makePackaging(start: Int, pkg: Tree, stats: List[Tree]): PackageDef =
+ atPos(start, pkg.pos.mid) {
+ pkg match {
+ case Ident(name) =>
+ PackageDef(name, stats)
+ case Select(qual, name) =>
+ makePackaging(start, qual, List(PackageDef(name, stats)))
+ }
+ }
+
+ /** Create a tree representing a package object, converting
+ * package object foo { ... }
+ * to
+ * package foo {
+ * object `package` { ... }
+ * }
+ */
+ def makePackageObject(start: Int, objDef: ModuleDef): PackageDef = objDef match {
+ case ModuleDef(mods, name, impl) =>
+ makePackaging(
+ start, atPos(o2p(objDef.pos.start)){ Ident(name) }, List(ModuleDef(mods, nme.PACKAGEkw, impl)))
+ }
+
/** Packaging ::= package QualId [nl] `{' TopStatSeq `}'
*/
- def packaging(pkgPos: Int): Tree = {
+ def packaging(start: Int): Tree = {
val pkg = qualId()
- val pos = if (pkg.pos != NoPosition) pkg.pos else i2p(pkgPos)
- atPos(pos) {
- newLineOptWhenFollowedBy(LBRACE)
- accept(LBRACE)
- val stats = topStatSeq()
- accept(RBRACE)
- makePackaging(pkg, stats)
- }
+ newLineOptWhenFollowedBy(LBRACE)
+ accept(LBRACE)
+ val stats = topStatSeq()
+ accept(RBRACE)
+ makePackaging(start, pkg, stats)
}
/** TopStatSeq ::= TopStat {semi TopStat}
@@ -2406,30 +2332,29 @@ self =>
*/
def topStatSeq(): List[Tree] = {
val stats = new ListBuffer[Tree]
- while (inToken != RBRACE && inToken != EOF) {
- if (inToken == PACKAGE) {
- val pkgPos = accept(PACKAGE)
+ while (in.token != RBRACE && in.token != EOF) {
+ if (in.token == PACKAGE) {
+ val start = in.skipToken()
stats += {
- if (inToken == OBJECT)
- atPos(pkgPos) { makePackageObject(objectDef(NoMods)) }
- else packaging(pkgPos)
- }
- } else if (inToken == IMPORT) {
+ if (in.token == OBJECT) makePackageObject(start, objectDef(NoMods))
+ else packaging(start)
+ }
+ } else if (in.token == IMPORT) {
stats ++= importClause()
// XXX: IDE hook this all.
- } else if (inToken == CLASS ||
- inToken == CASECLASS ||
- inToken == TRAIT ||
- inToken == OBJECT ||
- inToken == CASEOBJECT ||
- inToken == LBRACKET || //todo: remove
- inToken == AT ||
+ } else if (in.token == CLASS ||
+ in.token == CASECLASS ||
+ in.token == TRAIT ||
+ in.token == OBJECT ||
+ in.token == CASEOBJECT ||
+ in.token == LBRACKET || //todo: remove
+ in.token == AT ||
isModifier) {
stats ++ joinComment(List(topLevelTmplDef))
} else if (!isStatSep) {
syntaxErrorOrIncomplete("expected class or object definition", true)
}
- if (inToken != RBRACE && inToken != EOF) acceptStatSep()
+ if (in.token != RBRACE && in.token != EOF) acceptStatSep()
}
stats.toList
}
@@ -2448,36 +2373,36 @@ self =>
val stats = new ListBuffer[Tree]
if (isExprIntro) {
val first = expr(InTemplate) // @S: first statement is potentially converted so cannot be stubbed.
- if (inToken == ARROW) {
+ if (in.token == ARROW) {
first match {
case Typed(tree @ This(name), tpt) if (name == nme.EMPTY.toTypeName) =>
- self = makeSelfDef(nme.WILDCARD, tpt).setPos(tree.pos)
+ self = atPos(tree.pos) { makeSelfDef(nme.WILDCARD, tpt) }
case _ =>
convertToParam(first) match {
case tree @ ValDef(_, name, tpt, EmptyTree) if (name != nme.ERROR) =>
- self = makeSelfDef(name, tpt).setPos(tree.pos)
+ self = atPos(tree.pos) { makeSelfDef(name, tpt) }
case _ =>
}
}
- inNextToken
+ in.nextToken()
} else {
stats += first
if (in.token != RBRACE && in.token != EOF/* !isStatSep(in.token)*/) acceptStatSep()
}
}
- while (inToken != RBRACE && inToken != EOF) {
- if (inToken == IMPORT) {
+ while (in.token != RBRACE && in.token != EOF) {
+ if (in.token == IMPORT) {
stats ++= importClause()
} else if (isExprIntro) {
stats += statement(InTemplate)
- } else if (isDefIntro || isModifier || inToken == LBRACKET /*todo: remove */ || inToken == AT) {
+ } else if (isDefIntro || isModifier || in.token == LBRACKET /*todo: remove */ || in.token == AT) {
if (isPre) // @S: avoid caching by calling a different method that does the same thing (except in the IDE)
stats ++= joinComment(preNonLocalDefOrDcl)
else stats ++= joinComment(nonLocalDefOrDcl)
} else if (!isStatSep) {
syntaxErrorOrIncomplete("illegal start of definition", true)
}
- if (inToken != RBRACE && inToken != EOF) acceptStatSep()
+ if (in.token != RBRACE && in.token != EOF) acceptStatSep()
}
(self, stats.toList)
}
@@ -2491,13 +2416,13 @@ self =>
*/
def refineStatSeq(): List[Tree] = checkNoEscapingPlaceholders {
val stats = new ListBuffer[Tree]
- while (inToken != RBRACE && inToken != EOF) {
+ while (in.token != RBRACE && in.token != EOF) {
if (isDclIntro) { // don't IDE hook
stats ++= joinComment(defOrDcl(NoMods))
} else if (!isStatSep) {
syntaxErrorOrIncomplete("illegal start of declaration", true)
}
- if (inToken != RBRACE) acceptStatSep()
+ if (in.token != RBRACE) acceptStatSep()
}
stats.toList
}
@@ -2506,13 +2431,13 @@ self =>
* Here's an idea how to fill in start and end positions.
def localDef : List[Tree] = {
atEndPos {
- atStartPos(inCurrentPos) {
+ atStartPos(in.offset) {
val annots = annotations(true)
val mods = localModifiers() withAnnotations annots
if (!(mods hasFlag ~(Flags.IMPLICIT | Flags.LAZY))) defOrDcl(mods)
else List(tmplDef(mods))
}
- } (inCurrentPos)
+ } (in.offset)
}
*/
@@ -2531,28 +2456,23 @@ self =>
* |
*/
def blockStatSeq(stats: ListBuffer[Tree]): List[Tree] = checkNoEscapingPlaceholders {
- var keepGoing = true
- var hasError = false
- while ((inToken != RBRACE) && (inToken != EOF) && (inToken != CASE) && keepGoing) {
- var hasError0 = hasError
- hasError = false
- if (inToken == IMPORT) {
+ while ((in.token != RBRACE) && (in.token != EOF) && (in.token != CASE)) {
+ if (in.token == IMPORT) {
stats ++= importClause()
acceptStatSep()
} else if (isExprIntro) {
stats += statement(InBlock)
- if (inToken != RBRACE && inToken != CASE) acceptStatSep()
+ if (in.token != RBRACE && in.token != CASE) acceptStatSep()
} else if (isDefIntro || isLocalModifier || in.token == AT) {
stats ++= localDef
- if (inToken == RBRACE || inToken == CASE) {
+ if (in.token == RBRACE || in.token == CASE) {
syntaxError("block must end in result expression, not in definition", false)
- stats += Literal(()).setPos(inCurrentPos)
+ stats += Literal(()).setPos(o2p(in.offset))
} else acceptStatSep()
} else if (isStatSep) {
- inNextToken
+ in.nextToken()
} else {
syntaxErrorOrIncomplete("illegal start of statement", true)
- if (hasError0) keepGoing = false else hasError = true
}
}
stats.toList
@@ -2561,31 +2481,31 @@ self =>
/** CompilationUnit ::= [package QualId semi] TopStatSeq
*/
def compilationUnit(): Tree = checkNoEscapingPlaceholders {
- var pos = inCurrentPos;
- {
- val ts = new ListBuffer[Tree]
- // @S: the IDE can insert phantom semi-colons before package during editing
- // @S: just eat them (doesn't really change the grammar)
- while (inToken == SEMI) inNextToken
- if (inToken == PACKAGE) {
- pos = inSkipToken
- if (in.token == OBJECT) {
- ts += makePackageObject(objectDef(NoMods))
- if (inToken != EOF) {
- acceptStatSep()
- ts ++= topStatSeq()
- }
- } else {
- val pkg = qualId()
- newLineOptWhenFollowedBy(LBRACE)
- if (inToken == EOF) {
- ts += makePackaging(pkg, List())
- } else if (isStatSep) {
- inNextToken
- ts += makePackaging(pkg, topStatSeq())
- } else {
- accept(LBRACE)
- ts += makePackaging(pkg, topStatSeq())
+ val ts = new ListBuffer[Tree]
+
+ // @S: the IDE can insert phantom semi-colons before package during editing
+ // @S: just eat them (doesn't really change the grammar)
+ while (in.token == SEMI) in.nextToken()
+ val start = in.offset
+ if (in.token == PACKAGE) {
+ in.nextToken()
+ if (in.token == OBJECT) {
+ ts += makePackageObject(start, objectDef(NoMods))
+ if (in.token != EOF) {
+ acceptStatSep()
+ ts ++= topStatSeq()
+ }
+ } else {
+ val pkg = qualId()
+ newLineOptWhenFollowedBy(LBRACE)
+ if (in.token == EOF) {
+ ts += makePackaging(start, pkg, List())
+ } else if (isStatSep) {
+ in.nextToken()
+ ts += makePackaging(start, pkg, topStatSeq())
+ } else {
+ accept(LBRACE)
+ ts += makePackaging(start, pkg, topStatSeq())
accept(RBRACE)
ts ++= topStatSeq()
}
@@ -2594,14 +2514,12 @@ self =>
ts ++= topStatSeq()
}
val stats = ts.toList
- val usePos =
- if (stats.isEmpty || stats.head.pos == NoPosition) i2p(pos)
- else stats.head.pos
- atPos(usePos) { stats match {
- case List(stat @ PackageDef(_, _)) => stat
- case _ => makePackaging(Ident(nme.EMPTY_PACKAGE_NAME), stats)
- }}
- }
+ atPos(start) {
+ stats match {
+ case List(stat @ PackageDef(_, _)) => stat
+ case _ => makePackaging(start, atPos(o2p(start)) { Ident(nme.EMPTY_PACKAGE_NAME) }, stats)
+ }
+ }
}
}
}