diff options
author | Martin Odersky <odersky@gmail.com> | 2009-05-19 16:25:32 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2009-05-19 16:25:32 +0000 |
commit | b3ce4c4f7d2e2016d7b71bea2df7aa6dc75bc3d5 (patch) | |
tree | 6920117580b355522f14bc168de0463f8677a3aa /src/compiler/scala/tools/nsc/ast/parser/Parsers.scala | |
parent | 14fb2dfadd8ef9b433fed2599c1b32049d4c90e2 (diff) | |
download | scala-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-x | src/compiler/scala/tools/nsc/ast/parser/Parsers.scala | 1978 |
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) + } + } } } } |