/* NSC -- new Scala compiler
 * Copyright 2005-2009 LAMP/EPFL
 * @author  Martin Odersky
 */
// $Id: Parsers.scala 17756 2009-05-18 14:28:59Z rytz $
//todo: allow infix type patterns


package scala.tools.nsc
package ast.parser

import scala.collection.mutable.ListBuffer
import scala.tools.nsc.util.{Position, OffsetPosition, NoPosition, BatchSourceFile}
import symtab.Flags
import Tokens._

//todo verify when stableId's should be just plain qualified type ids

/** <p>Performs the following context-free rewritings:</p>
 *  <ol>
 *    <li>
 *      Places all pattern variables in Bind nodes. In a pattern, for
 *      identifiers <code>x</code>:<pre>
 *                 x  => x @ _
 *               x:T  => x @ (_ : T)</pre>
 *    </li>
 *    <li>Removes pattern definitions (PatDef's) as follows:
 *      If pattern is a simple (typed) identifier:<pre>
 *        <b>val</b> x = e     ==>  <b>val</b> x = e
 *        <b>val</b> x: T = e  ==>  <b>val</b> x: T = e</pre>
 *    
 *      if there are no variables in pattern<pre>
 *        <b>val</b> p = e  ==>  e match (case p => ())</pre>
 *    
 *      if there is exactly one variable in pattern<pre>
 *        <b>val</b> x_1 = e <b>match</b> (case p => (x_1))</pre>
 *    
 *      if there is more than one variable in pattern<pre>
 *        <b>val</b> p = e  ==>  <b>private synthetic val</b> t$ = e <b>match</b> (case p => (x_1, ..., x_N))
 *                        <b>val</b> x_1 = t$._1
 *                        ...
 *                        <b>val</b> x_N = t$._N</pre>
 *    </li>
 *    <li>
 *       Removes function types as follows:<pre>
 *        (argtpes) => restpe   ==>   scala.Function_n[argtpes, restpe]</pre>
 *    </li>
 *    <li>
 *      Wraps naked case definitions in a match as follows:<pre>
 *        { cases }   ==>   (x => x.match {cases})<span style="font-family:normal;">, except when already argument to match</span></pre>
 *    </li>
 *  </ol>
 */
trait Parsers extends Scanners with MarkupParsers {
self =>
  val global: Global 
  import global._

  private val glob: global.type = global

  case class OpInfo(operand: Tree, operator: Name, offset: Offset)

  class UnitParser(val unit: global.CompilationUnit, patches: List[BracePatch]) extends Parser {

    def this(unit: global.CompilationUnit) = this(unit, List())

    val in = new UnitScanner(unit, patches)
    in.init()

    def freshName(pos: Position, prefix: String): Name =
      unit.fresh.newName(pos, prefix)

    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(offset: Int, msg: String) { unit.warning(o2p(offset), msg) }

    def deprecationWarning(offset: Int, 
                           msg: String) {
      unit.deprecationWarning(o2p(offset), msg)
    }

    var smartParsing = false

    val syntaxErrors = new ListBuffer[(Int, String)]
    
    def incompleteInputError(msg: String) {
      val offset = unit.source.asInstanceOf[BatchSourceFile].content.length - 1
      if (smartParsing) syntaxErrors += ((offset, msg))
      else unit.incompleteInputError(o2p(offset), msg)
    }

    def syntaxError(offset: Int, msg: String) { 
      if (smartParsing) syntaxErrors += ((offset, msg))
      else unit.error(o2p(offset), msg) 
    }

    /** parse unit. If there are inbalanced braces,
     *  try to correct them and reparse.
     */
    def smartParse(): Tree = try {
      smartParsing = true
      val firstTry = parse()
      if (syntaxErrors.isEmpty) firstTry
      else {
        val patches = in.healBraces() 
        if (patches.isEmpty) {
          for ((offset, msg) <- syntaxErrors) unit.error(o2p(offset), msg)
          firstTry
        } else {
//          println(patches)
          new UnitParser(unit, patches).parse()
        }
      }
    } finally {
      smartParsing = false
    }

    /** the markup parser */
    lazy val xmlp = new MarkupParser(this, true)

    object symbXMLBuilder extends SymbolicXMLBuilder(this, true) { // DEBUG choices
      val global: self.global.type = self.global
      def freshName(prefix: String): Name = UnitParser.this.freshName(prefix)
    }

    def xmlLiteral : Tree = xmlp.xLiteral

    def xmlLiteralPattern : Tree = xmlp.xLiteralPattern
  }

  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 {
    val in: Scanner
    //val unit : CompilationUnit
    //import in.ScanPosition
    def freshName(pos: Position, prefix: String): Name
    def freshName(prefix: String): Name = freshName(NoPosition, prefix) // todo get rid of position

    def o2p(offset: Int): Position
    def r2p(start: Int, mid: Int, end: Int): Position
    //private implicit def p2i(pos: Position) = pos.offset.get
    
    /** whether a non-continuable syntax error has been seen */
    //private var syntaxErrorSeen = false 

    private var lastErrorOffset : Int = -1

    object treeBuilder extends TreeBuilder {
      val global: self.global.type = self.global
      def freshName(prefix: String): Name = Parser.this.freshName(prefix)
      def o2p(offset: Int) = Parser.this.o2p(offset)
      def r2p(start: Int, point: Int, end: Int) = Parser.this.r2p(start, point, end)
    }
    import treeBuilder.{global => _, _}

    /** The types of the context bounds of type parameters of the surrounding class
     */
    var classContextBounds: List[Tree] = Nil

    /** this is the general parse method
     */
    def parse(): Tree = {
      val t = compilationUnit()
      accept(EOF)
      t
    }

/* --------------- PLACEHOLDERS ------------------------------------------- */

    /** The implicit parameters introduced by `_' in the current expression.
     *  Parameters appear in reverse order 
     */
    var placeholderParams: List[ValDef] = Nil

    /** The placeholderTypes introduced by `_' in the current type.
     *  Parameters appear in reverse order 
     */
    var placeholderTypes: List[TypeDef] = Nil

    def checkNoEscapingPlaceholders[T](op: => T): T = {
      val savedPlaceholderParams = placeholderParams
      val savedPlaceholderTypes = placeholderTypes
      placeholderParams = List()
      placeholderTypes = List()

      val res = op
      
      placeholderParams match {
        case vd :: _ => 
          syntaxError(vd.pos, "unbound placeholder parameter", false)
          placeholderParams = List()
        case _ =>
      }
      placeholderTypes match {
        case td :: _ => 
          syntaxError(td.pos, "unbound wildcard type", false)
          placeholderTypes = List()
        case _ =>
      }
      placeholderParams = savedPlaceholderParams
      placeholderTypes = savedPlaceholderTypes

      res
    }

    def placeholderTypeBoundary(op: => Tree): Tree = {
      val savedPlaceholderTypes = placeholderTypes
      placeholderTypes = List()
      var t = op
      if (!placeholderTypes.isEmpty && t.isInstanceOf[AppliedTypeTree]) {
        val expos = t.pos
        ensureNonOverlapping(t, placeholderTypes)
        t = atPos(expos) { 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 ------------------------------------------- */

    var assumedClosingParens = collection.mutable.Map(RPAREN -> 0, RBRACKET -> 0, RBRACE -> 0)

    protected def skip(targetToken: Int) {
      var nparens = 0
      var nbraces = 0
      while (true) {
        in.token match {
          case EOF =>
            return
          case SEMI =>
            if (nparens == 0 && nbraces == 0) return
          case NEWLINE =>
            if (nparens == 0 && nbraces == 0) return
          case NEWLINES =>
            if (nparens == 0 && nbraces == 0) return
          case RPAREN =>
            nparens -= 1
          case RBRACE =>
            if (nbraces == 0) return
            nbraces -= 1
          case LPAREN =>
            nparens += 1
          case LBRACE =>
            nbraces += 1
          case _ =>
        }
        if (targetToken == in.token && nparens == 0 && nbraces == 0) return
        in.nextToken()
      }
    }
    def warning(offset: Int, msg: String): Unit
    def incompleteInputError(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(offset: Int, msg: String): Unit
    def syntaxError(msg: String, skipIt: Boolean) {
      syntaxError(in.offset, msg, skipIt)
    }

    def syntaxError(offset: Int, msg: String, skipIt: Boolean) {
      if (offset > lastErrorOffset) {
        syntaxError(offset, msg)
        // no more errors on this token.
        lastErrorOffset = in.offset
      }
      if (skipIt) 
        skip(UNDEF)
    }

    def warning(msg: String) { warning(in.offset, msg) }

    def syntaxErrorOrIncomplete(msg: String, skipIt: Boolean) {
      if (in.token == EOF)
        incompleteInputError(msg)
      else
        syntaxError(in.offset, msg, skipIt)
    }

    def expectedMsg(token: Int): String =
      token2string(token) + " expected but " +token2string(in.token) + " found."

    /** Consume one token of the specified type, or
      * signal an error if it is not there.
      */
    def accept(token: Int): Int = {
      val offset = in.offset
      if (in.token != token) {
        syntaxErrorOrIncomplete(expectedMsg(token), false)
        if ((token == RPAREN || token == RBRACE || token == RBRACKET))
          if (in.parenBalance(token) + assumedClosingParens(token) < 0) 
            assumedClosingParens(token) += 1
          else
            skip(token)
        else 
          skip(UNDEF)
      }
      if (in.token == token) in.nextToken()
      offset
    }

    def surround[T](open: Int, close: Int)(f: => T, orElse: T): T = {
      val wasOpened = in.token == open
      accept(open)
      if (wasOpened) {
        val ret = f
        accept(close)
        ret
      } else orElse
    }

    /** semi = nl {nl} | `;' 
     *  nl  = `\n' // where allowed
     */
    def acceptStatSep(): Boolean =
      if (in.token == NEWLINE || in.token == NEWLINES) { in.nextToken(); true }
      else {
        val ret = in.token == SEMI
        accept(SEMI)
        ret
      }

    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 = in.token match {
      case ABSTRACT | FINAL | SEALED | PRIVATE |
           PROTECTED | OVERRIDE | IMPLICIT | LAZY => true
      case _ => false
    }

    def isLocalModifier: Boolean = in.token match {
      case ABSTRACT | FINAL | SEALED | IMPLICIT | LAZY => true
      case _ => false
    }

    def isDefIntro: Boolean = in.token match {
      case VAL | VAR | DEF | TYPE | OBJECT |
           CASEOBJECT | CLASS | CASECLASS | TRAIT => true
      case _ => false
    }

    def isDclIntro: Boolean = in.token match {
      case VAL | VAR | DEF | TYPE => true
      case _ => false
    }

    def isIdent = in.token == IDENTIFIER || in.token == BACKQUOTED_IDENT

    def isExprIntroToken(token: Int): Boolean = token match {
      case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT |
           STRINGLIT | SYMBOLLIT | TRUE | FALSE | NULL | IDENTIFIER | BACKQUOTED_IDENT |
           THIS | SUPER | IF | FOR | NEW | USCORE | TRY | WHILE |
           DO | RETURN | THROW | LPAREN | LBRACE | XMLSTART => true
      case _ => false
    }

    def isExprIntro: Boolean = isExprIntroToken(in.token)

    def isTypeIntroToken(token: Int): Boolean = token match {
      case IDENTIFIER | BACKQUOTED_IDENT | THIS |
           SUPER | USCORE | LPAREN | AT => true
      case _ => false
    }

    def isTypeIntro: Boolean = isTypeIntroToken(in.token)

    def isStatSep(token: Int): Boolean = 
      token == NEWLINE || token == NEWLINES || token == SEMI
    
    def isStatSep: Boolean = isStatSep(in.token)


/* --------- COMMENT AND ATTRIBUTE COLLECTION ----------------------------- */

    /** Join the comment associated with a definition
    */
    def joinComment(trees: => List[Tree]): List[Tree] = {
      val buf = in.flushDoc
      if ((buf ne null) && buf.length > 0) trees map (t => DocDef(buf, t) setPos t.pos) // !!! take true comment position
      else trees
    }

/* ---------- TREE CONSTRUCTION ------------------------------------------- */

    def atPos[T <: Tree](offset: Int)(t: T): T =
      global.atPos(r2p(offset, offset, in.lastOffset max offset))(t)
    def atPos[T <: Tree](start: Int, point: Int)(t: T): T =
      global.atPos(r2p(start, point, in.lastOffset max start))(t)
    def atPos[T <: Tree](start: Int, point: Int, end: Int)(t: T): T = 
      global.atPos(r2p(start, point, end))(t)
    def atPos[T <: Tree](pos: Position)(t: T): T =
      global.atPos(pos)(t)

    /** Convert tree to formal parameter list
    */
    def convertToParams(tree: Tree): List[ValDef] = tree match {
      case Parens(ts) =>
        ts map convertToParam
      case _ =>
        List(convertToParam(tree))
    }

    /** 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() setPos o2p(tree.pos.endOrPoint), 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 setPos o2p(tree.pos.endOrPoint), EmptyTree)
      }
    }

    /** Convert (qual)ident to type identifier
     */
    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
      }
    }

    /** part {`,' part} */
    def commaSeparated(part: => Tree): List[Tree] = {
      val ts = new ListBuffer[Tree] += part
      while (in.token == COMMA) {
        in.nextToken()
        ts += part
      }
      ts.toList
    }

/* --------- 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 =
      if (operator eq nme.ERROR) -1
      else {
        val firstCh = operator(0)
        if (((firstCh >= 'A') && (firstCh <= 'Z')) ||
            ((firstCh >= 'a') && (firstCh <= 'z')))
          1
        else if (nme.isOpAssignmentName(operator))
          0
        else 
          firstCh match {
            case '|'             => 2
            case '^'             => 3
            case '&'             => 4
            case '=' | '!'       => 5
            case '<' | '>'       => 6
            case ':'             => 7
            case '+' | '-'       => 8
            case '*' | '/' | '%' => 9
            case _               => 10
          }
      }

    def checkSize(kind: String, size: Int, max: Int) {
      if (size > max) syntaxError("too many "+kind+", maximum = "+max, false)
    }

    def checkAssoc(offset: Int, op: Name, leftAssoc: Boolean) = 
      if (treeInfo.isLeftAssoc(op) != leftAssoc)
        syntaxError(
          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.offset, opstack.head.operator, leftAssoc)
      while (opstack != base && 
             (prec < precedence(opstack.head.operator) ||
              leftAssoc && prec == precedence(opstack.head.operator))) {
        val opinfo = opstack.head
        opstack = opstack.tail
        val opPos = r2p(opinfo.offset, opinfo.offset, opinfo.offset+opinfo.operator.length)
        top = atPos(opinfo.operand.pos.startOrPoint, opinfo.offset) {
          makeBinop(isExpr, opinfo.operand, opinfo.operator, top, opPos)
        }
      }
      top
    }

/* -------- IDENTIFIERS AND LITERALS ------------------------------------------- */

    def ident(skipIt: Boolean): Name =
      if (in.token == IDENTIFIER || in.token == BACKQUOTED_IDENT) {
        val name = in.name.encode
        in.nextToken()
        name
      } else {
        syntaxErrorOrIncomplete(expectedMsg(IDENTIFIER), skipIt)
        nme.ERROR
      }

    def ident(): Name = ident(true)

    def selector(t: Tree): Tree = {
      val point = in.offset
      //assert(t.pos.isDefined, t)
      Select(t, ident(false)) setPos r2p(t.pos.startOrPoint, point, 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 (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 (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 tok = in.token
        val name = ident()
        t = atPos(start) {
          if (tok == BACKQUOTED_IDENT) new BackQuotedIdent(name)
          else Ident(name)
        }
        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 (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, dotOffset)
          }
        }
      }
      t
    }

    def selectors(t: Tree, typeOK: Boolean, dotOffset: Int): Tree =
      if (typeOK && in.token == TYPE) {
        in.nextToken()
        atPos(t.pos.startOrPoint, dotOffset) { SingletonTypeTree(t) }
      } else {
        val t1 = selector(t)
        if (in.token == DOT) { selectors(t1, typeOK, in.skipToken()) }
        else t1
      }

    /** MixinQualifier ::= `[' Id `]'
    */
    def mixinQualifierOpt(): Name =
      if (in.token == LBRACKET) {
        in.nextToken()
        val name = ident().toTypeName
        accept(RBRACKET)
        name
      } else {
        nme.EMPTY.toTypeName
      }

    /** StableId ::= Id
     *            |  Path `.' Id
     *            |  [id '.'] super [`[' id `]']`.' id
     */
    def stableId(): Tree =
      path(false, false)

    /** QualId ::= Id {`.' Id}
    */
    def qualId(): Tree = {
      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
     *  @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)
        }
      }
      in.nextToken()
      if (isSymLit) Apply(scalaDot(nme.Symbol), List(t)) else t
    }

/* ------------- NEW LINES ------------------------------------------------- */

    def newLineOpt() {
      if (in.token == NEWLINE) in.nextToken()
    }

    def newLinesOpt() {
      if (in.token == NEWLINE || in.token == NEWLINES)
        in.nextToken()
    }

    def newLineOptWhenFollowedBy(token: Int) {
      // note: next is defined here because current == NEWLINE
      if (in.token == NEWLINE && in.next.token == token) newLineOpt()
    }

    def newLineOptWhenFollowing(p: Int => Boolean) {
      // note: next is defined here because current == NEWLINE
      if (in.token == NEWLINE && p(in.next.token)) newLineOpt()
    }

/* ------------- TYPES ---------------------------------------------------- */

    /** TypedOpt ::= [`:' Type]
     */
    def typedOpt(): Tree =
      if (in.token == COLON) { in.nextToken(); typ() } 
      else TypeTree()

    /** Types ::= Type {`,' Type} 
     */
    def types(isPattern: Boolean, isTypeApply: Boolean, isFuncArg: Boolean): List[Tree] =
      commaSeparated(argType(isPattern, isTypeApply, isFuncArg))

    /** Type ::= InfixType `=>' Type
     *         | `(' [`=>' Type] `)' `=>' Type
     *         | InfixType [ExistentialClause]
     *  ExistentialClause ::= forSome `{' ExistentialDcl {semi ExistentialDcl}} `}'
     *  ExistentialDcl    ::= type TypeDcl | val ValDcl
     */
    def typ(): Tree = typ(false)

    def typ(isPattern: Boolean): Tree = placeholderTypeBoundary {
      val start = in.offset
      val t = 
        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 (in.token == ARROW) 
              atPos(start, in.skipToken()) {
                makeFunctionTypeTree(ts, typ(isPattern))
              }
            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 (in.token == ARROW)
        atPos(start, in.skipToken()) { 
          makeFunctionTypeTree(List(t), typ(isPattern)) 
        }
      else if (in.token == FORSOME)
        atPos(start, in.skipToken()) {
          val whereClauses = refinement()
          whereClauses foreach checkLegalExistential
          ExistentialTypeTree(t, whereClauses)
        }
      else t
    }

    /** InfixType ::= CompoundType {id [nl] CompoundType} 
     */
    def infixType(isPattern: Boolean, mode: InfixMode.Value): Tree = placeholderTypeBoundary {
      infixTypeRest(compoundType(isPattern), isPattern, mode)
    }

    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()
        val tycon = atPos(opOffset) { Ident(op.toTypeName) }
        newLineOptWhenFollowing(isTypeIntroToken)
        def mkOp(t1: Tree) = atPos(t.pos.startOrPoint, opOffset) { AppliedTypeTree(tycon, List(t, t1)) }
        if (leftAssoc)
          infixTypeRest(mkOp(compoundType(isPattern)), isPattern, InfixMode.LeftOp)
        else
          mkOp(infixType(isPattern, InfixMode.RightOp))
      } else t
    }

    /** CompoundType ::= AnnotType {with AnnotType} [Refinement] 
     *                |  Refinement
     */  
    def compoundType(isPattern: Boolean): Tree = {
      val t = if (in.token == LBRACE) atPos(o2p(in.offset)) (scalaAnyRefConstr)
              else annotType(isPattern)
      compoundTypeRest(t, 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(t.pos.startOrPoint) {
        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
          // refinement from no refinement at all.  See bug #284.
          for (Ident(name) <- ts) name.toString match {
            case "Unit" | "scala.Unit"  =>
              warning("Detected apparent refinement of Unit; are you missing an '=' sign?")
            case _ =>
          }
          CompoundTypeTree(Template(ts.toList, emptyValDef, refinement()))
        }
        else 
          makeIntersectionTypeTree(ts.toList)
      }
    }

    /** AnnotType        ::=  SimpleType {Annotation}
     */
    def annotType(isPattern: Boolean): Tree = placeholderTypeBoundary {
      annotTypeRest(simpleType(isPattern))
    }

    def annotTypeRest(t: Tree): Tree = 
      (t /: annotations(false, false)) (makeAnnotated)

    /** SimpleType       ::=  SimpleType TypeArgs 
     *                     |  SimpleType `#' Id
     *                     |  StableId
     *                     |  Path `.' type
     *                     |  `(' Types `)'
     *                     |  WildcardType
     */
    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(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 simpleTypeRest(t: Tree, isPattern: Boolean): Tree =
      if (in.token == HASH) {
        val hashOffset = in.skipToken()
        val nameOffset = in.offset
        val name = ident(false)
        val sel = atPos(t.pos.startOrPoint, if (name == nme.ERROR) hashOffset else nameOffset) {
          SelectFromTypeTree(t, name.toTypeName)
        }
        simpleTypeRest(sel, isPattern)
      } else if (in.token == LBRACKET) {
        simpleTypeRest(atPos(t.pos.startOrPoint) { AppliedTypeTree(t, typeArgs(isPattern, false)) }, isPattern)
      } else {
        t
      }

    /** WildcardType ::= `_' TypeBounds
     */
    def wildcardType(start: Int) = {
      val pname = freshName(o2p(start), "_$").toTypeName
      val t = atPos(start) { Ident(pname) }
      val bounds = typeBounds()
      val param = atPos(t.pos union bounds.pos) { makeSyntheticTypeParam(pname, bounds) }
      placeholderTypes = param :: placeholderTypes
      t
    }

    /** TypeArgs    ::= `[' ArgType {`,' ArgType} `]'
     */
    def typeArgs(isPattern: Boolean, isTypeApply: Boolean): List[Tree] = {
      accept(LBRACKET)
      val ts = types(isPattern, isTypeApply, false)
      accept(RBRACKET)
      ts
    }       

    /** ArgType       ::=  Type
     */ 
    def argType(isPattern: Boolean, isTypeApply: Boolean, isFuncArg: Boolean): Tree = {
      val start = in.offset
      if (isPattern) {
        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 (in.token == ARROW) {
          in.nextToken()
          val tycon = atPos(start) { rootScalaDot(nme.BYNAME_PARAM_CLASS_NAME.toTypeName) }
          atPos(start) { AppliedTypeTree(tycon, List(typ())) }
        } else {
          val t = typ()
          if (isIdent && in.name == STAR) {
            val tycon = atPos(in.skipToken()) { rootScalaDot(nme.REPEATED_PARAM_CLASS_NAME.toTypeName) }
            atPos(start) { AppliedTypeTree(tycon, List(t)) }
          } else t
        }
      } else {
        typ()
      }
    }

/* ----------- EXPRESSIONS ------------------------------------------------ */    

    /** EqualsExpr ::= `=' Expr
     */
    def equalsExpr(): Tree = {
      accept(EQUALS)
      expr()
    }

    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
     *  ResultExpr ::= (Bindings | Id `:' CompoundType) `=>' Block
     *               | Expr1
     *  Expr1      ::= if `(' Expr `)' {nl} Expr [[semi] else Expr]
     *               | try (`{' Block `}' | Expr) [catch `{' CaseClauses `}'] [finally Expr]
     *               | while `(' Expr `)' {nl} Expr
     *               | do Expr [semi] while `(' Expr `)'
     *               | for (`(' Enumerators `)' | '{' Enumerators '}') {nl} [yield] Expr
     *               | throw Expr
     *               | return [Expr]
     *               | [SimpleExpr `.'] Id `=' Expr
     *               | SimpleExpr1 ArgumentExprs `=' Expr
     *               | PostfixExpr Ascription
     *               | PostfixExpr match `{' CaseClauses `}'
     *  Bindings   ::= `(' [Binding {`,' Binding}] `)'
     *  Binding    ::= (Id | `_') [`:' Type]
     *  Ascription ::= `:' CompoundType
     *               | `:' Annotation {Annotation} 
     *               | `:' `_' `*'
     */
    def expr(): Tree = expr(Local)

    def expr(location: Int): Tree = {
      var savedPlaceholderParams = placeholderParams
      placeholderParams = List()
      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 (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()
          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) in.nextToken()
          accept(WHILE)
          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 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.startOrPoint, in.skipToken()) { makeAssign(t, expr()) }
            case _ => 
          }
        } 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.startOrPoint, colonPos) {
                Typed(t, atPos(uscorePos) { Ident(nme.WILDCARD_STAR.toTypeName) })
              }
            } else {
              syntaxErrorOrIncomplete("`*' expected", true)
            }
          } else if (in.token == AT) {
            t = (t /: annotations(false, false)) (makeAnnotated)
          } else {
            t = atPos(t.pos.startOrPoint, 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 = treeCopy.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)
            }
          }
        } else if (in.token == MATCH) {
          t = atPos(t.pos.startOrPoint, in.skipToken()) {
            Match(stripParens(t), surround(LBRACE, RBRACE)(caseClauses(), Nil))
          }
        }
        // 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.startOrPoint, in.skipToken()) {
            Function(convertToParams(t), if (location != InBlock) expr() else block())
          }
        }
        stripParens(t)
    }

    /** PostfixExpr   ::= InfixExpr [Id [nl]]
     *  InfixExpr     ::= PrefixExpr
     *                  | InfixExpr Id [nl] InfixExpr
     */
    def postfixExpr(): Tree = {
      val base = opstack
      var top = prefixExpr()
      // Various errors in XML literals can cause xmlLiteral to propagate
      // EmptyTree's. Watch out for them here.
      if (top == EmptyTree)
        return EmptyTree

      while (isIdent) {
        top = reduceStack(true, base, top, precedence(in.name), treeInfo.isLeftAssoc(in.name))
        val op = in.name
        opstack = OpInfo(top, op, in.offset) :: opstack
        ident()
        newLineOptWhenFollowing(isExprIntroToken)
        if (isExprIntro) {
          val next = prefixExpr()
          if (next == EmptyTree)
            return reduceStack(true, base, top, 0, true)
          top = next
        } else {
          val topinfo = opstack.head
          opstack = opstack.tail
          val od = stripParens(reduceStack(true, base, topinfo.operand, 0, true))
          return atPos(od.pos.startOrPoint, topinfo.offset) {
            Select(od, topinfo.operator.encode)
          }
        }
      }
      reduceStack(true, base, top, 0, true)
    }

    /** PrefixExpr   ::= [`-' | `+' | `~' | `!' | `&'] SimpleExpr 
    */
    def prefixExpr(): Tree = {
      def unaryOp(): Name = "unary_" + ident()
      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 {
        simpleExpr()
      }
    }
    def xmlLiteral(): Tree
    
    /* SimpleExpr    ::= new (ClassTemplate | TemplateBody)
     *                |  BlockExpr
     *                |  SimpleExpr1 [`_']
     * SimpleExpr1   ::= literal
     *                |  xLiteral
     *                |  Path
     *                |  `(' [Exprs] `)'
     *                |  SimpleExpr `.' Id 
     *                |  SimpleExpr TypeArgs
     *                |  SimpleExpr1 ArgumentExprs
     */
    def simpleExpr(): Tree = {
      var canApply = true
      val t = in.token match {
        case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT | STRINGLIT | 
             SYMBOLLIT | TRUE | FALSE | NULL =>
          atPos(in.offset) { literal(false) }
        case XMLSTART => 
          xmlLiteral()
        case IDENTIFIER | BACKQUOTED_IDENT | THIS | SUPER =>
          path(true, false)
        case USCORE =>
          val start = in.offset
          val pname = freshName(o2p(start), "x$")
          in.nextToken()
          val id = atPos(start) (Ident(pname))
          val param = atPos(id.pos.focus){ makeSyntheticParam(pname) }
          placeholderParams = param :: placeholderParams
          id
        case LPAREN =>
          atPos(in.skipToken()) {
            val ts = if (in.token == RPAREN) List() else commaSeparated(expr)
            accept(RPAREN)
            Parens(ts)
          }
        case LBRACE =>
          canApply = false
          blockExpr()
        case NEW =>
          canApply = false
          val nstart = in.skipToken()
          val npos = r2p(nstart, nstart, in.lastOffset)
          val tstart = in.offset
          val (parents, argss, self, stats) = template(false)
          val cpos = r2p(tstart, tstart, in.lastOffset)
          makeNew(parents, self, stats, argss, npos, cpos)
        case _ =>
          syntaxErrorOrIncomplete("illegal start of simple expression", true)
          errorTermTree
      }
      simpleExprRest(t, canApply)
    }

    def simpleExprRest(t: Tree, canApply: Boolean): Tree = {
      if (canApply) newLineOptWhenFollowedBy(LBRACE)
      in.token match {
        case DOT =>
          in.nextToken()
          simpleExprRest(selector(stripParens(t)), true)
        case LBRACKET =>
          val t1 = stripParens(t)
          t1 match {
            case Ident(_) | Select(_, _) =>
              val tapp = atPos(t1.pos.startOrPoint, in.offset) { 
                TypeApply(t1, typeArgs(false, true))
              }
              simpleExprRest(tapp, true)
            case _ =>
              t1
          }
        case LPAREN | LBRACE if (canApply) =>
          val app = atPos(t.pos.startOrPoint, in.offset) {
            // look for anonymous function application like (f _)(x) and
            // translate to (f _).apply(x), bug #460
            val sel = t match {
              case Parens(List(Typed(_, _: Function))) =>
                Select(stripParens(t), nme.apply)
              case _ =>
                stripParens(t)
            }
            Apply(sel, argumentExprs())
          }
          simpleExprRest(app, true)
        case USCORE =>
          atPos(t.pos.startOrPoint, in.skipToken()) { 
            Typed(stripParens(t), Function(List(), EmptyTree)) 
          }
        case _ =>
          t
      }
    }

    /** ArgumentExprs ::= `(' [Exprs] `)'
      *                 | [nl] BlockExpr
     */
    def argumentExprs(): List[Tree] = {
      def args(): List[Tree] = commaSeparated {
        val maybeNamed = isIdent
        expr() match {
          case a @ Assign(id, rhs) if maybeNamed =>
            atPos(a.pos) { AssignOrNamedArg(id, rhs) }
          case e => e
        }
      }

      // if arg has the form "x$1 => a = x$1" it's treated as "a = x$1" with x$1
      // in placeholderParams. This allows e.g. "val f: Int => Int = foo(a = 1, b = _)"
      def convertArg(arg: Tree): Tree = arg match {
        case Function(
          List(vd @ ValDef(mods, pname1, ptype1, EmptyTree)),
          Assign(Ident(aname), rhs)) if (mods hasFlag Flags.SYNTHETIC) =>
          rhs match {
            case Ident(`pname1`) | Typed(Ident(`pname1`), _) =>
              placeholderParams = vd :: placeholderParams
              atPos(arg.pos) { AssignOrNamedArg(Ident(aname), Ident(pname1)) }
            case _ => arg
          }
        case _ => arg
      }

      if (in.token == LBRACE) 
        List(blockExpr())
      else
        surround(LPAREN, RPAREN)(if (in.token == RPAREN) List() else (args() map convertArg), List())
    }
        
    /** BlockExpr ::= `{' (CaseClauses | Block) `}'
     */
    def blockExpr(): Tree = {
      val res = atPos(accept(LBRACE)) { // no need to surround
        if (in.token == CASE) Match(EmptyTree, caseClauses())
        else block()
      }
      accept(RBRACE)
      res
    }
    
    /** Block ::= BlockStatSeq
     *  @note  Return tree does not carry position.
     */
    def block(): Tree = {
      makeBlock(blockStatSeq(new ListBuffer[Tree]))
    }

   /** CaseClauses ::= CaseClause {CaseClause} 
    */
    def caseClauses(): List[CaseDef] = {
      val ts = new ListBuffer[CaseDef]
      do { ts += caseClause()
      } while (in.token == CASE)
      ts.toList
    }

    /** CaseClause ::= case Pattern [Guard] `=>' Block
     */
    def caseClause(): CaseDef =
      atPos(accept(CASE)) {
        val pat = pattern()
        val gd = guard()
        makeCaseDef(pat, gd, caseBlock())
      }
    // IDE HOOK (so we can memoize case blocks) // needed?
    def caseBlock(): Tree = 
      atPos(accept(ARROW))(block())

    /** Guard ::= if PostfixExpr
     */
    def guard(): Tree = 
      if (in.token == IF) { in.nextToken(); stripParens(postfixExpr()) } 
      else EmptyTree
      
    /** Enumerators ::= Generator {semi Enumerator}
     *  Enumerator  ::=  Generator
     *                |  Guard
     *                |  val Pattern1 `=' Expr
     */
    def enumerators(): List[Enumerator] = {
      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) {
        in.nextToken()
        if (newStyle) {
          if (in.token == IF) enums += makeFilter(in.offset, guard())
          else generator(enums, true)
        } else {
          if (in.token == VAL) generator(enums, true) 
          else enums += makeFilter(in.offset, expr())
        }
      }
      enums.toList
    }

    /** Generator ::= Pattern1 (`<-' | '=') Expr [Guard]
     */
    def generator(enums: ListBuffer[Enumerator], eqOK: Boolean) {
      val start = in.offset
      if (in.token == VAL) in.nextToken()
      val pat = pattern1(false)
      val point = in.offset
      val tok = in.token
      if (tok == EQUALS && eqOK) in.nextToken()
      else accept(LARROW)
      val rhs = expr()
      enums += makeGenerator(r2p(start, point, in.lastOffset), pat, tok == EQUALS, rhs)
      if (in.token == IF) enums += makeFilter(in.offset, guard())
    }

    def makeFilter(start: Int, tree: Tree) = Filter(r2p(start, tree.pos.point, tree.pos.endOrPoint), tree)

/* -------- PATTERNS ------------------------------------------- */    

    /**   Patterns ::= Pattern { `,' Pattern }  
     *    SeqPatterns ::= SeqPattern { `,' SeqPattern }  
     */
    def patterns(seqOK: Boolean): List[Tree] =
      commaSeparated(pattern(seqOK))

    /**   Pattern  ::=  Pattern1 { `|' Pattern1 }
     *    SeqPattern ::= SeqPattern1 { `|' SeqPattern1 }
     */
    def pattern(seqOK: Boolean): Tree = {
      val start = in.offset
      val t = pattern1(seqOK)
      if (isIdent && in.name == BAR) {
        val ts = new ListBuffer[Tree] += t
        while (isIdent && in.name == BAR) {
          in.nextToken(); ts += pattern1(seqOK)
        }
        atPos(start) { makeAlternative(ts.toList) }
      } else t
    }

    def pattern(): Tree = pattern(false)

    /**   Pattern1    ::= varid `:' TypePat
     *                 |  `_' `:' TypePat
     *                 |  Pattern2
     *    SeqPattern1 ::= varid `:' TypePat
     *                 |  `_' `:' TypePat
     *                 |  [SeqPattern2]
     */
    def pattern1(seqOK: Boolean): Tree = {
      val p = pattern2(seqOK)
      p match {
        case Ident(name) if (treeInfo.isVarPattern(p) && in.token == COLON) =>
          atPos(p.pos.startOrPoint, in.skipToken()) { Typed(p, compoundType(true)) }
        case _ =>
          p
      }
    }

    /*   Pattern2    ::=  varid [ @ Pattern3 ]
     *                |   Pattern3
     *   SeqPattern2 ::=  varid [ @ SeqPattern3 ]
     *                |   SeqPattern3
     */
    def pattern2(seqOK: Boolean): Tree = {
      val p = pattern3(seqOK)
      if (in.token == AT) {
        p match {
          case Ident(name) =>
            if (name == nme.WILDCARD) {
              in.nextToken() 
              pattern3(seqOK)
            } else if (treeInfo.isVarPattern(p)) {
              in.nextToken()
              atPos(p.pos.startOrPoint) { Bind(name, pattern3(seqOK)) }
            } else {
              p
            }
          case _ =>
            p
        }
      } else p
    }

    /*   Pattern3    ::= SimplePattern
     *                |  SimplePattern {Id [nl] SimplePattern} 
     *   SeqPattern3 ::= SeqSimplePattern [ '*' | '?' | '+' ]
     *                |  SeqSimplePattern {Id [nl] SeqSimplePattern} 
     */
    def pattern3(seqOK: Boolean): Tree = {
      val base = opstack
      var top = simplePattern(seqOK)
      if (seqOK && isIdent && in.name == STAR)
        return atPos(top.pos.startOrPoint, in.skipToken())(Star(stripParens(top)))
          
      while (isIdent && in.name != BAR) {
        top = reduceStack(
          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)
      }
      stripParens(reduceStack(false, base, top, 0, true))
    }
     
    def xmlLiteralPattern(): Tree 

    /** SimplePattern    ::= varid
     *                    |  `_'
     *                    |  literal
     *                    |  XmlPattern
     *                    |  StableId  [TypeArgs] [`(' [SeqPatterns] `)']
     *                    |  `(' [Patterns] `)'
     *  SimpleSeqPattern ::= varid
     *                    |  `_'
     *                    |  literal
     *                    |  XmlPattern
     *                    |  `<' xLiteralPattern 
     *                    |  StableId [TypeArgs] [`(' [SeqPatterns] `)']
     *                    |  `(' [SeqPatterns] `)'
     * 
     * XXX: Hook for IDE
     */
    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, 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)
            Parens(ps)
          }
        case XMLSTART =>
          xmlLiteralPattern()
        case _ =>
          syntaxErrorOrIncomplete("illegal start of simple pattern", true)
          errorPatternTree
      }
    }

    def argumentPatterns(): List[Tree] = {
      accept(LPAREN)
      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
      else if ((mods hasFlag Flags.ABSTRACT) && (mods hasFlag Flags.OVERRIDE))
        mods &~ (Flags.ABSTRACT | Flags.OVERRIDE) | Flags.ABSOVERRIDE
      else
        mods

    private def addMod(mods: Modifiers, mod: Long): Modifiers = {
      if (mods hasFlag mod) syntaxError(in.offset, "repeated modifier", false)
      in.nextToken()
      mods | mod
    }

    /** AccessQualifier ::= "[" (Id | this) "]"
     */
    def accessQualifierOpt(mods: Modifiers): Modifiers = {
      var result = mods
      if (in.token == LBRACKET) {
        in.nextToken()
        if (mods.privateWithin != nme.EMPTY.toTypeName)
          syntaxError("duplicate private/protected qualifier", false)
        result = if (in.token == THIS) { in.nextToken(); mods | Flags.LOCAL }
                 else Modifiers(mods.flags, ident().toTypeName)
        accept(RBRACKET)
      }
      result
    }

    /** AccessModifier ::= (private | protected) [AccessQualifier]
     */
    def accessModifierOpt(): Modifiers = normalize {
      in.token match {
        case PRIVATE => in.nextToken(); accessQualifierOpt(Modifiers(Flags.PRIVATE))
        case PROTECTED => in.nextToken(); accessQualifierOpt(Modifiers(Flags.PROTECTED))
        case _ => NoMods
      }
    }

    /** Modifiers ::= {Modifier}
     *  Modifier  ::= LocalModifier 
     *             |  AccessModifier
     *             |  override
     */
    def modifiers(): Modifiers = normalize {
      def loop(mods: Modifiers): Modifiers = in.token match {
        case ABSTRACT =>
          loop(addMod(mods, Flags.ABSTRACT))
        case FINAL =>
          loop(addMod(mods, Flags.FINAL))
        case SEALED =>
          loop(addMod(mods, Flags.SEALED))
        case PRIVATE =>
          loop(accessQualifierOpt(addMod(mods, Flags.PRIVATE)))
        case PROTECTED =>
          loop(accessQualifierOpt(addMod(mods, Flags.PROTECTED)))
        case OVERRIDE =>
          loop(addMod(mods, Flags.OVERRIDE))
        case IMPLICIT =>
          loop(addMod(mods, Flags.IMPLICIT))
        case LAZY =>
          loop(addMod(mods, Flags.LAZY))
        case NEWLINE =>
          in.nextToken()
          loop(mods)
        case _ =>
          mods
      }
      loop(NoMods)
    }

    /** LocalModifiers ::= {LocalModifier}
     *  LocalModifier  ::= abstract | final | sealed | implicit | lazy
     */
    def localModifiers(): Modifiers = {
      def loop(mods: Modifiers): Modifiers = in.token match {
        case ABSTRACT =>
          loop(addMod(mods, Flags.ABSTRACT))
        case FINAL =>
          loop(addMod(mods, Flags.FINAL))
        case SEALED =>
          loop(addMod(mods, Flags.SEALED))
        case IMPLICIT =>
          loop(addMod(mods, Flags.IMPLICIT))
        case LAZY =>
          loop(addMod(mods, Flags.LAZY))
        case _ =>
          mods
      }
      loop(NoMods)
    }

    /** Annotations      ::= {`@' SimpleType {ArgumentExprs}}
     *  ConsrAnnotations ::= {`@' SimpleType ArgumentExprs}
     */
    def annotations(skipNewLines: Boolean, requireOneArgList: Boolean): List[Tree] = {
      var annots = new ListBuffer[Tree]
      while (in.token == AT) {
        in.nextToken()
        annots += annotationExpr(requireOneArgList)
        if (skipNewLines) newLineOpt()
      }
      annots.toList
    }

    def annotationExpr(requireOneArgList: Boolean): Tree = {
      atPos(in.offset) {
        val t = simpleType(false)
        val argss = new ListBuffer[List[Tree]]
        if (requireOneArgList)
          argss += argumentExprs()
        else if (in.token == LPAREN)
          do { argss += argumentExprs() } while (in.token == LPAREN)
        else argss += List()
        New(t, argss.toList)
      }
    }

/* -------- PARAMETERS ------------------------------------------- */    

    /** ParamClauses      ::= {ParamClause} [[nl] `(' implicit Params `)']
     *  ParamClause       ::= [nl] `(' [Params] ')'
     *  Params            ::= Param {`,' Param}
     *  Param             ::= {Annotation} Id [`:' ParamType] [`=' Expr]
     *  ClassParamClauses ::= {ClassParamClause} [[nl] `(' implicit ClassParams `)']
     *  ClassParamClause  ::= [nl] `(' [ClassParams] ')'
     *  ClassParams       ::= ClassParam {`,' ClassParam}
     *  ClassParam        ::= {Annotation}  [{Modifier} (`val' | `var')] Id [`:' ParamType] [`=' Expr]
     */
    def paramClauses(owner: Name, contextBounds: List[Tree], ofCaseClass: Boolean): List[List[ValDef]] = {
      var implicitmod = 0
      var caseParam = ofCaseClass
      def param(): ValDef = {
        val start = in.offset
        val annots = annotations(false, 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
          }
          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
            }
            paramType()
          }
        val default =
          if (in.token == EQUALS) {
            in.nextToken()
            mods |= Flags.DEFAULTPARAM
            expr()
          } else EmptyTree
        atPos(start, if (name == nme.ERROR) start else nameOffset) {
          ValDef((mods | implicitmod | bynamemod) withAnnotations annots, name, tpt, default)
        }
      }
      def paramClause(): List[ValDef] = {
        val params = new ListBuffer[ValDef]
        if (in.token != RPAREN) {
          if (in.token == IMPLICIT) {
            if (!contextBounds.isEmpty)
              syntaxError("cannot have both implicit parameters and context bounds `: ...' on type parameters", false)
            in.nextToken()
            implicitmod = Flags.IMPLICIT 
          }
          params += param()
          while (in.token == COMMA) {
            in.nextToken(); params += param()
          }
        }
        params.toList
      }
      val vds = new ListBuffer[List[ValDef]]
      val start = in.offset
      newLineOptWhenFollowedBy(LPAREN)
      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 && in.token == LPAREN) {
        in.nextToken()
        vds += paramClause()
        accept(RPAREN)
        caseParam = false
        newLineOptWhenFollowedBy(LPAREN)
      }
      val result = vds.toList
      if (owner == nme.CONSTRUCTOR && 
          (result.isEmpty || 
           (!result.head.isEmpty && result.head.head.mods.hasFlag(Flags.IMPLICIT))))
        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(start, "auxiliary constructor needs non-implicit parameter list", false)
      addEvidenceParams(owner, result, contextBounds)
    }

    /** ParamType ::= Type | `=>' Type | Type `*'
     */
    def paramType(): Tree =
      if (in.token == ARROW) {
        atPos(in.skipToken()) {
          AppliedTypeTree(
            rootScalaDot(nme.BYNAME_PARAM_CLASS_NAME.toTypeName), List(typ()))
        }
      } else {
        val t = typ()
        if (isIdent && in.name == STAR) {
          in.nextToken()
          atPos(t.pos.startOrPoint, t.pos.point) { 
            AppliedTypeTree(
              rootScalaDot(nme.REPEATED_PARAM_CLASS_NAME.toTypeName), List(t))
          }
        } else t
      }

    /** TypeParamClauseOpt    ::= [TypeParamClause]
     *  TypeParamClause       ::= `[' VariantTypeParam {`,' VariantTypeParam} `]']
     *  VariantTypeParam      ::= {Annotation} [`+' | `-'] TypeParam
     *  FunTypeParamClauseOpt ::= [FunTypeParamClause]
     *  FunTypeParamClause    ::= `[' TypeParam {`,' TypeParam} `]']
     *  TypeParam             ::= Id TypeParamClauseOpt TypeBounds {<% Type} {":" Type}
     */
    def typeParamClauseOpt(owner: Name, contextBoundBuf: ListBuffer[Tree]): List[TypeDef] = {
      def typeParam(ms: Modifiers): TypeDef = {
        var mods = ms | Flags.PARAM
        val start = in.offset
        if (owner.isTypeName && isIdent) {
          if (in.name == PLUS) {
            in.nextToken()
            mods |= Flags.COVARIANT
          } else if (in.name == MINUS) {
            in.nextToken()
            mods |= Flags.CONTRAVARIANT
          }
        }
        val nameOffset = in.offset
        val pname = 
          (if (in.token == USCORE) { // @M! also allow underscore 
            in.nextToken()
            nme.WILDCARD
          } else ident()).toTypeName
        val param = atPos(start, nameOffset) {
          val tparams = typeParamClauseOpt(pname, null) // @M TODO null --> no higher-order context bounds for now
          TypeDef(mods, pname, tparams, typeBounds())
        }
        if (contextBoundBuf ne null) {
          while (in.token == VIEWBOUND) {
            contextBoundBuf += atPos(in.skipToken()) {
              makeFunctionTypeTree(List(Ident(pname)), typ())
            }
          }
          while (in.token == COLON) {
            contextBoundBuf += atPos(in.skipToken()) {
              AppliedTypeTree(typ(), List(Ident(pname)))
            }
          }
        }
        param
      }
      val params = new ListBuffer[TypeDef]
      newLineOptWhenFollowedBy(LBRACKET) 
      if (in.token == LBRACKET) {
        in.nextToken()
        params += typeParam(NoMods.withAnnotations(annotations(true, false)))
        while (in.token == COMMA) {
          in.nextToken()
          params += typeParam(NoMods.withAnnotations(annotations(true, false)))
        }
        accept(RBRACKET)
      }
      params.toList
    }

    /** TypeBounds ::= [`>:' Type] [`<:' Type] 
     */
    def typeBounds(): TypeBoundsTree = { 
      val t = TypeBoundsTree(
        bound(SUPERTYPE, nme.Nothing),
        bound(SUBTYPE, nme.Any))
      t setPos (wrappingPos(List(t.hi, t.lo)))
      t
    }
    
    def bound(tok: Int, default: Name): Tree =
      if (in.token == tok) { in.nextToken(); typ() } 
      else atPos(o2p(in.lastOffset)) { rootScalaDot(default.toTypeName) }

/* -------- DEFS ------------------------------------------- */    


    /** Import  ::= import ImportExpr {`,' ImportExpr}
     */
    def importClause(): List[Tree] = {
      accept(IMPORT)
      commaSeparated(importExpr())
    }

    /**  ImportExpr ::= StableId `.' (Id | `_' | ImportSelectors)
     * XXX: Hook for IDE
     */
    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 {
          t = id
        }
      }
      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)))
          }
        }
      atPos(start) { loop() }
    }
      
    /** ImportSelectors ::= `{' {ImportSelector `,'} (ImportSelector | `_') `}'
     */
    def importSelectors(): List[(Name, Name)] = {
      val names = new ListBuffer[(Name, Name)]
      accept(LBRACE)
      var isLast = importSelector(names)
      while (!isLast && in.token == COMMA) {
        in.nextToken()
        isLast = importSelector(names)
      }
      accept(RBRACE)
      names.toList
    }

    /** ImportSelector ::= Id [`=>' Id | `=>' `_']
     */
    def importSelector(names: ListBuffer[(Name, Name)]): Boolean =
      if (in.token == USCORE) {
        in.nextToken(); names += ((nme.WILDCARD, null)); true
      } else {
        val name = ident()
        names += ((
          name,
          if (in.token == ARROW) {
            in.nextToken()
            if (in.token == USCORE) { in.nextToken(); nme.WILDCARD } else ident()
          } else {
            name
          }))
        false
      }
    
    /** Def    ::= val PatDef
     *           | var VarDef
     *           | def FunDef
     *           | type [nl] TypeDef
     *           | TmplDef 
     *  Dcl    ::= val ValDcl
     *           | var ValDcl
     *           | def FunDcl
     *           | type [nl] TypeDcl
     */
    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)
      in.token match {
        case VAL =>
          patDefOrDcl(mods)
        case VAR =>
          patDefOrDcl(mods | Flags.MUTABLE)
        case DEF =>
          List(funDefOrDcl(mods))
        case TYPE =>
          List(typeDefOrDcl(mods))
        case _ =>
          List(tmplDef(mods))
      }
    }
    /** IDE hook: for non-local defs or dcls with modifiers and annotations */
    def nonLocalDefOrDcl : List[Tree] = {
      val annots = annotations(true, false)
      defOrDcl(modifiers() withAnnotations annots)
    }
    /** not hooked by the IDE, will not undergo stubbing. Used for early initialization blocks. */
    def preNonLocalDefOrDcl : List[Tree] = {
      val annots = annotations(true, false)
      defOrDcl(modifiers() withAnnotations annots)
    }
    
    
    /** PatDef ::= Pattern2 {`,' Pattern2} [`:' Type] `=' Expr
     *  ValDcl ::= Id {`,' Id} `:' Type
     *  VarDef ::= PatDef | Id {`,' Id} `:' Type `=' `_'
     */
    def patDefOrDcl(mods: Modifiers): List[Tree] = {
      var newmods = mods
      val lhsBuf = new ListBuffer[Tree]
      do {
        in.nextToken()
        val p = pattern2(false)
        lhsBuf += stripParens(p)
      } while (in.token == COMMA)
      val lhs = lhsBuf.toList
      val tp = typedOpt()
      val rhs =
        if (tp.isEmpty || in.token == EQUALS) {
          accept(EQUALS)
          if (!tp.isEmpty && newmods.hasFlag(Flags.MUTABLE) && 
              (lhs.toList forall (_.isInstanceOf[Ident])) && in.token == USCORE) {
            in.nextToken()
            newmods = newmods | Flags.DEFAULTINIT
            EmptyTree
          } else {
            expr()
          }
        } else {
          newmods = newmods | Flags.DEFERRED
          EmptyTree
        }
      def mkDefs(p: Tree, tp: Tree, rhs: Tree): List[Tree] = {
        //Console.println("DEBUG: p = "+p.toString()); // DEBUG
        val trees = 
          makePatDef(newmods, 
                     if (tp.isEmpty) p 
                     else Typed(p, tp) setPos (p.pos union tp.pos), 
                     rhs)
        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)
            case _ => syntaxError(p.pos, "pattern definition may not be abstract", false)
          }
        }
        trees
      }
      (lhs.toList.init flatMap (mkDefs(_, tp.duplicate, rhs.duplicate))) ::: mkDefs(lhs.last, tp, rhs)
    }

    /** VarDef ::= PatDef
     *           | Id {`,' Id} `:' Type `=' `_'
     *  VarDcl ::= Id {`,' Id} `:' Type
    def varDefOrDcl(mods: Modifiers): List[Tree] = {
      var newmods = mods | Flags.MUTABLE
      val lhs = new ListBuffer[(Int, Name)]
      do {
        in.nextToken()
        lhs += (in.offset, ident())
      } while (in.token == COMMA)
      val tp = typedOpt()
      val rhs = if (tp.isEmpty || in.token == EQUALS) {
        accept(EQUALS)
        if (!tp.isEmpty && in.token == USCORE) {
          in.nextToken()
          EmptyTree
        } else {
          expr()
        }
      } else {
        newmods = newmods | Flags.DEFERRED
        EmptyTree
      }
    }
     */

    /** FunDef ::= FunSig `:' Type `=' Expr
     *           | FunSig [nl] `{' Block `}'
     *           | this ParamClause ParamClauses (`=' ConstrExpr | [nl] ConstrBlock)
     *  FunDcl ::= FunSig [`:' Type]
     *  FunSig ::= id [FunTypeParamClause] ParamClauses
     */
    def funDefOrDcl(mods: Modifiers): Tree = {
      val start = in.skipToken() 
      if (in.token == THIS) {  
        atPos(start, in.skipToken()) {
          val vparamss = paramClauses(nme.CONSTRUCTOR, classContextBounds map (_.duplicate), false)
          newLineOptWhenFollowedBy(LBRACE)
          val rhs = if (in.token == LBRACE) {
                      atPos(in.offset) { constrBlock(vparamss) }
                    } else { 
                      accept(EQUALS)
                      atPos(in.offset) { constrExpr(vparamss) }
                    }
          DefDef(mods, nme.CONSTRUCTOR, List(), vparamss, TypeTree(), rhs)
        }
      } else {
        var newmods = mods
        val nameOffset = in.offset
        val name = ident()
        atPos(start, if (name == nme.ERROR) start else nameOffset) {
          // contextBoundBuf is for context bounded type parameters of the form
          // [T : B] or [T : => B]; it contains the equivalent implicit parameter type,
          // i.e. (B[T] or T => B)
          val contextBoundBuf = new ListBuffer[Tree]  
          val tparams = typeParamClauseOpt(name, contextBoundBuf)
          val vparamss = paramClauses(name, contextBoundBuf.toList, false)
          newLineOptWhenFollowedBy(LBRACE)
          var restype = typedOpt()
          val rhs =
            if (isStatSep || in.token == RBRACE) {
              if (restype.isEmpty) restype = scalaUnitConstr
              newmods |= Flags.DEFERRED
              EmptyTree
            } else if (restype.isEmpty && in.token == LBRACE) {
              restype = scalaUnitConstr
              blockExpr()
            } else {
              equalsExpr()
            }
          DefDef(newmods, name, tparams, vparamss, restype, rhs)
        }
      }
    }

    /** ConstrExpr      ::=  SelfInvocation
     *                    |  ConstrBlock
     */
    def constrExpr(vparamss: List[List[ValDef]]): Tree =
      if (in.token == LBRACE) constrBlock(vparamss)
      else Block(List(selfInvocation(vparamss)), Literal(()))

    /** SelfInvocation  ::= this ArgumentExprs {ArgumentExprs}
     */
    def selfInvocation(vparamss: List[List[ValDef]]): Tree =
      atPos(accept(THIS)) {
        newLineOptWhenFollowedBy(LBRACE)
        var t = Apply(Ident(nme.CONSTRUCTOR), argumentExprs())
        while (in.token == LPAREN || in.token == LBRACE) {
          t = Apply(t, argumentExprs())
          newLineOptWhenFollowedBy(LBRACE)
        }
        if (classContextBounds.isEmpty) t
        else Apply(t, vparamss.last.map(vp => Ident(vp.name)))
      }

    /** ConstrBlock    ::=  `{' SelfInvocation {semi BlockStat} `}' 
     */
    def constrBlock(vparamss: List[List[ValDef]]): Tree =
      atPos(in.skipToken()) {
        val statlist = new ListBuffer[Tree]
        statlist += selfInvocation(vparamss)
        val stats = if (isStatSep) { in.nextToken(); blockStatSeq(statlist) } 
                    else statlist.toList
        accept(RBRACE)
        Block(stats, Literal(()))
      }

    /** TypeDef ::= type Id [TypeParamClause] `=' Type
     *  TypeDcl ::= type Id [TypeParamClause] TypeBounds
     */
    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 = typeParamClauseOpt(name, null)
        in.token match {
          case EQUALS =>
            in.nextToken()
            TypeDef(mods, name, tparams, typ())
          case SUPERTYPE | SUBTYPE | SEMI | NEWLINE | NEWLINES | COMMA | RBRACE =>
            TypeDef(mods | Flags.DEFERRED, name, tparams, typeBounds())
          case _ =>
            syntaxErrorOrIncomplete("`=', `>:', or `<:' expected", true)
            EmptyTree
        }
      }
    }

    /** Hook for IDE, for top-level classes/objects */
    def topLevelTmplDef: Tree = {
      val annots = annotations(true, false)
      val mods = modifiers() withAnnotations annots
      tmplDef(mods)
    }
    
    /**  TmplDef ::= [case] class ClassDef
     *            |  [case] object ObjectDef
     *            |  [override] trait TraitDef
     */
    def tmplDef(mods: Modifiers): Tree = {
      if (mods.hasFlag(Flags.LAZY)) syntaxError("classes cannot be lazy", false)
      in.token match {
        case TRAIT =>
          classDef(mods | Flags.TRAIT | Flags.ABSTRACT)
        case CLASS =>
          classDef(mods)
        case CASECLASS =>
          classDef(mods | Flags.CASE)
        case OBJECT =>
          objectDef(mods)
        case CASEOBJECT =>
          objectDef(mods | Flags.CASE)
        case _ =>
          syntaxErrorOrIncomplete("expected start of definition", true)
          EmptyTree
      }
    }

    /** ClassDef ::= Id [TypeParamClause] {Annotation}
                     [AccessModifier] ClassParamClauses RequiresTypeOpt ClassTemplateOpt
     *  TraitDef ::= Id [TypeParamClause] RequiresTypeOpt TraitTemplateOpt
     */
    def classDef(mods: Modifiers): ClassDef = {
      val start = in.skipToken() 
      val nameOffset = in.offset
      val name = ident().toTypeName
      atPos(start, if (name == nme.ERROR.toTypeName) start else nameOffset) {
        val savedContextBounds = classContextBounds
        val contextBoundBuf = new ListBuffer[Tree]
        val tparams = typeParamClauseOpt(name, contextBoundBuf)
        classContextBounds = contextBoundBuf.toList
        val tstart = (in.offset::classContextBounds.map(_.pos.startOrPoint)).min 
        if (!classContextBounds.isEmpty && mods.hasFlag(Flags.TRAIT)) {
          syntaxError("traits cannot have type parameters with context bounds `: ...'", false)
          classContextBounds = List()
        }
        val constrAnnots = annotations(false, true)
        val (constrMods, vparamss) = 
          if (mods.hasFlag(Flags.TRAIT)) (Modifiers(Flags.TRAIT), List())
          else (accessModifierOpt(), paramClauses(name, classContextBounds, mods.hasFlag(Flags.CASE)))
        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)
        }
        val template = templateOpt(mods1, name, constrMods withAnnotations constrAnnots, vparamss, tstart)
        if (isInterface(mods1, template.body)) mods1 |= Flags.INTERFACE 
        val result = ClassDef(mods1, name, tparams, template)
        classContextBounds = savedContextBounds
        result
      }
    }

    /** ObjectDef       ::= Id ClassTemplateOpt
     */
    def objectDef(mods: Modifiers): ModuleDef = {
      val start = in.skipToken() 
      val nameOffset = in.offset
      val name = ident()
      val tstart = in.offset
      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(), tstart)
        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 argss = new ListBuffer[List[Tree]]
      if (in.token == LPAREN && !isTrait)
        do { argss += argumentExprs() } while (in.token == LPAREN)
      else argss += List()
      while (in.token == WITH) {
        in.nextToken()
        parents += annotType(false)
      }
      (parents.toList, argss.toList)
    }      

    /** ClassTemplate ::= [EarlyDefs with] ClassParents [TemplateBody]
     *  TraitTemplate ::= [EarlyDefs with] TraitParents [TemplateBody]
     *  EarlyDefs     ::= `{' [EarlyDef {semi EarlyDef}] `}'
     *  EarlyDef      ::= Annotations Modifiers PatDef
     */
    def template(isTrait: Boolean): (List[Tree], List[List[Tree]], ValDef, List[Tree]) = {
      newLineOptWhenFollowedBy(LBRACE)
      if (in.token == LBRACE) {
        // @S: pre template body cannot stub like post body can!
        val (self, body) = templateBody(true) 
        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(treeCopy.ValDef(vdef, mods | Flags.PRESUPER, name, tpt, rhs))
            case tdef @ TypeDef(mods, name, tparams, rhs) =>
              List(treeCopy.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)
              List()
            case _ => List()
          }
          in.nextToken()
          val (parents, argss) = templateParents(isTrait)
          val (self1, body1) = templateBodyOpt(isTrait)
          (parents, argss, self1, earlyDefs ::: body1)
        } else {
          (List(), List(List()), self, body)
        }
      } else {
        val (parents, argss) = templateParents(isTrait)
        val (self, body) = templateBodyOpt(isTrait)
        (parents, argss, self, body)
      }
    }

    def isInterface(mods: Modifiers, body: List[Tree]): Boolean =
      (mods hasFlag Flags.TRAIT) && (body forall treeInfo.isInterfaceMember)

    /** ClassTemplateOpt ::= 'extends' ClassTemplate | [['extends'] TemplateBody] 
     *  TraitTemplateOpt ::= TraitExtends TraitTemplate | [['extends'] TemplateBody] | '<:' TemplateBody
     *  TraitExtends     ::= 'extends' | `<:'
     */
    def templateOpt(mods: Modifiers, name: Name, constrMods: Modifiers,
                    vparamss: List[List[ValDef]], tstart: Int): Template = {
      val (parents0, argss, self, body) = 
        if (in.token == EXTENDS || settings.Xexperimental.value && (mods hasFlag Flags.TRAIT) && in.token == SUBTYPE) {
          in.nextToken()
          template(mods hasFlag Flags.TRAIT)
        } else if ((in.token == SUBTYPE) && (mods hasFlag Flags.TRAIT)) {
	  in.nextToken()
          template(true)
	} else {
          newLineOptWhenFollowedBy(LBRACE)
          val (self, body) = templateBodyOpt(false)
          (List(), List(List()), self, body)
        }
      var parents = parents0
      if (name != nme.ScalaObject.toTypeName && !isInterface(mods, body)) 
        parents = parents ::: List(scalaScalaObjectConstr)
      if (parents.isEmpty)
        parents = List(scalaAnyRefConstr)
      if (mods.hasFlag(Flags.CASE)) parents = parents ::: List(productConstr)
      val tstart0 = if (body.isEmpty && in.lastOffset < tstart) in.lastOffset else tstart
      atPos(tstart0) {
        Template(parents, self, constrMods, vparamss, argss, body, o2p(tstart))
      }
    }

/* -------- TEMPLATES ------------------------------------------- */        

    /** TemplateBody ::= [nl] `{' TemplateStatSeq `}'
     * @param isPre specifies whether in early initializer (true) or not (false) 
     */
    def templateBody(isPre: Boolean) = {
      accept(LBRACE)
      val result @ (self, stats) = templateStatSeq(isPre)
      accept(RBRACE)
      if (stats.isEmpty) (self, List(EmptyTree)) else result
    }
    def templateBodyOpt(traitParentSeen: Boolean): (ValDef, List[Tree]) = {
      newLineOptWhenFollowedBy(LBRACE)
      if (in.token == LBRACE) {
        templateBody(false) 
      } else {
        if (in.token == LPAREN) 
          syntaxError((if (traitParentSeen) "parents of traits" else "traits or objects")+
                      " may not have parameters", true)
        (emptyValDef, List())
      }
    }

    /** Refinement ::= [nl] `{' RefineStat {semi RefineStat} `}'
     */
    def refinement(): List[Tree] = {
      accept(LBRACE)
      val body = refineStatSeq()
      accept(RBRACE)
      body
    }

/* -------- STATSEQS ------------------------------------------- */        

  /** Create a tree representing a packaging */
    def makePackaging(start: Int, pkg: Tree, stats: List[Tree]): PackageDef = 
      atPos(start, pkg.pos.point) { PackageDef(pkg.asInstanceOf[RefTree], stats) }
/*
        pkg match {
          case id @ Ident(_) =>
            PackageDef(id, stats)
          case Select(qual, name) => // drop this to flatten packages
            makePackaging(start, qual, List(PackageDef(Ident(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.startOrPoint)){ Ident(name) }, List(ModuleDef(mods, nme.PACKAGEkw, impl)))
    }

    /** Packaging ::= package QualId [nl] `{' TopStatSeq `}'
     */
    def packaging(start: Int): Tree = {
      val pkg = qualId()
      newLineOptWhenFollowedBy(LBRACE)
      accept(LBRACE)
      val stats = topStatSeq()
      accept(RBRACE)
      makePackaging(start, pkg, stats)
    }

    /** TopStatSeq ::= TopStat {semi TopStat}
     *  TopStat ::= Annotations Modifiers TmplDef
     *            | Packaging
     *            | package object objectDef
     *            | Import
     *            | 
     */
    def topStatSeq(): List[Tree] = {
      val stats = new ListBuffer[Tree]
      while (in.token != RBRACE && in.token != EOF) {
        if (in.token == PACKAGE) {
          val start = in.skipToken()
	  stats += {
	    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 (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 (in.token != RBRACE && in.token != EOF) acceptStatSep()
      }
      stats.toList
    }

    /** TemplateStatSeq  ::= [id [`:' Type] `=>'] TemplateStat {semi TemplateStat} 
     *  TemplateStat     ::= Import
     *                     | Annotations Modifiers Def
     *                     | Annotations Modifiers Dcl
     *                     | Expr1
     *                     | super ArgumentExprs {ArgumentExprs}
     *                     |
     * @param isPre specifies whether in early initializer (true) or not (false)
     */
    def templateStatSeq(isPre : Boolean) = checkNoEscapingPlaceholders {
      var self: ValDef = emptyValDef
      val stats = new ListBuffer[Tree]
      if (isExprIntro) {
        val first = expr(InTemplate) // @S: first statement is potentially converted so cannot be stubbed.
        if (in.token == ARROW) {
          first match {
            case Typed(tree @ This(name), tpt) if (name == nme.EMPTY.toTypeName) =>
              self = atPos(tree.pos union tpt.pos) { makeSelfDef(nme.WILDCARD, tpt) }
            case _ =>
              convertToParam(first) match {
                case tree @ ValDef(_, name, tpt, EmptyTree) if (name != nme.ERROR) =>
                  self = atPos(tree.pos union tpt.pos) { makeSelfDef(name, tpt) }
                case _ =>
              }
          }
          in.nextToken()
        } else {
          stats += first
          if (in.token != RBRACE && in.token != EOF/* !isStatSep(in.token)*/) acceptStatSep()
        }
      }
      while (in.token != RBRACE && in.token != EOF) {
        if (in.token == IMPORT) {
          stats ++= importClause()
        } else if (isExprIntro) {
          stats += statement(InTemplate)
        } 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 (in.token != RBRACE && in.token != EOF) acceptStatSep()
      }
      (self, stats.toList)
    }
     
     

    /** RefineStatSeq    ::= RefineStat {semi RefineStat}
     *  RefineStat       ::= Dcl
     *                     | type TypeDef
     *                     |
     */
    def refineStatSeq(): List[Tree] = checkNoEscapingPlaceholders {
      val stats = new ListBuffer[Tree]
      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 (in.token != RBRACE) acceptStatSep()
      }
      stats.toList
    }

    /** overridable IDE hook for local definitions of blockStatSeq 
     *  Here's an idea how to fill in start and end positions.
    def localDef : List[Tree] = {
      atEndPos {
        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))
        }
      } (in.offset)
    }
    */

    def localDef : List[Tree] = {
      val annots = annotations(true, false)
      val mods = localModifiers() withAnnotations annots
      if (!(mods hasFlag ~(Flags.IMPLICIT | Flags.LAZY))) defOrDcl(mods)
      else List(tmplDef(mods))
    }

    /** BlockStatSeq ::= { BlockStat semi } [ResultExpr]
     *  BlockStat    ::= Import 
     *                 | Annotations [implicit] [lazy] Def
     *                 | Annotations LocalModifiers TmplDef
     *                 | Expr1
     *                 |
     */
    def blockStatSeq(stats: ListBuffer[Tree]): List[Tree] = checkNoEscapingPlaceholders {
      while ((in.token != RBRACE) && (in.token != EOF) && (in.token != CASE)) {
        if (in.token == IMPORT) {
          stats ++= importClause()
          acceptStatSep()
        } else if (isExprIntro) {
          stats += statement(InBlock)
          if (in.token != RBRACE && in.token != CASE) acceptStatSep()
        } else if (isDefIntro || isLocalModifier || in.token == AT) {
          stats ++= localDef
          if (in.token == RBRACE || in.token == CASE) {
            //syntaxError("block must end in result expression, not in definition", false)
            stats += Literal(()).setPos(o2p(in.offset))
          } else acceptStatSep()
        } else if (isStatSep) {
          in.nextToken()
        } else {
          syntaxErrorOrIncomplete("illegal start of statement", true)
        }
      }
      stats.toList
    }

    /** CompilationUnit ::= {package QualId semi} TopStatSeq
     */
    def compilationUnit(): Tree = checkNoEscapingPlaceholders {
      def topstats(): List[Tree] = {
        val ts = new ListBuffer[Tree]
        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, topstats())
            } else {
              accept(LBRACE)
              ts += makePackaging(start, pkg, topStatSeq())
              accept(RBRACE)
              ts ++= topStatSeq()
            }
	  }
        } else {
          ts ++= topStatSeq()
        }
        ts.toList
      }
      val start = in.offset max 0
      topstats() match {        
        case List(stat @ PackageDef(_, _)) => stat
        case stats => makePackaging(start, atPos(o2p(start)) { Ident(nme.EMPTY_PACKAGE_NAME) }, stats)
      }
    }
  }
}