summaryrefslogblamecommitdiff
path: root/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
blob: fd0c5269bbb8660df6f2003b892b6ba95440cdcb (plain) (tree)
1
2
3
4
5
6
7
8
9
10

                                


                          

                                 
 

                                  
                                                  

                   
 

                                                                     




                                                                     
                              





                                                             
  

                                                             
  

                                                                 
  


                                                                                                             
                             










                                                                                                                                        
   
                                       
 
                 
                                  
                                        
                                 
 
                                              
 
                              
 
                            
                                                            
 
                                            

                                                                      
     
                        
 
                                                                                                       

                                                                      

     

                                            

                                        
                         

                               
       




                                                                             
                                                                            

                     
                    
                        
                     
                  
                      
                                                    
                         
                                                    
                        
                                 
                        

                                    
                        
                                 
                        
                                 
                   

                      



                                                         
                                             


                                                                     

                            
       
                   


                           
       

     
                                         
                                                         


                                       

                                        

       



















                                                                                     
                                   
                             







                                                         
                                                     






                                                

                                           

     

                                          
       

                                                               
 


                                                                           



                                                                            
                                                                                        



                                                   
                                                       




                                              
                                                         







                                              

                                                                        
                                                             
                                                              
                                                                                        

                                                                   


                     

                                                         
                                                             
                                                                                      


                     


                                                         



                                                                               
                                                         
                            
                        

                                                               




                                                                              


                                                          
                                          
              
                                           
                               
                                            
           
               

                                                                    





                                            








                                                                               





                                                        
                                               
                                
                                                      
               

                                                           

     

                                         
                                                













                                                                     
       
 
               
                                                                           
                                                



                                                                                

                                                              



                                         
                                 







                                                     

                                     




                                      

       



                                                                             




                                                                                                    
                                                                                                             
                    

                                                                       
                               




                                                                             
                              





                                                                                             




                               
                               



                               

                       
                                                                   


                                 
              
                                                                                                        

                                                                                           
                 

       





                                                                     
                               
                                       
                                      
       
                                                        
                        
                             


                                                                
                                     





                                                          
              



                                                                        
             
                              
                                  
                                 
                          



                                                        
                          







                                                                              



       
                                                              
                                       
                      
                                           
              


                                                                      





                                     



                                     
              
                            


                       
                               


                                                            
                        



                              
                                                      
                                                                   







                                                                 
                                              




















                                                                  
                                                              

                  

       


                                          

                     
                                          
                                                               

                                                               

              
         


       

                                

                                                         

       








                                                                     
 





                                                                              
                     
 
                                                                   
      
                                 

                                                     
                                                                    
                                         
       
                     



                                 
                                           
                                 

                      



               







                                                      
       

                       
                                 
                        
                                   
                          
                                                                        




                                                                          
                  
                                   
                          
                                    
                            
                                    
                            

                                                                                      
                    
                            
                                                    


                
                                   
         
                                                    
                                              


            








                                                                                  
                                 






                                                                                                
                                                                                        






                                                                          
       

                                                                       
 
                                                                         
                                       
                                
                                                   

                  
                                                                                                 
                                                
       

     


                                                          


                                            
                                                               
                                                                         
                                                                   
                                                        

                                            
                                                                                   
       
                                                
                                    
                             
                   
                                               


                        
           





                                                 
                                                                                          


                                                                           
                                  
                
                                   
                           
                                          
                                        
           

                                                                                             
         



                          
                               
                                     
                                                     
           
                                          
                                                                    
                                  
              
                   
       
                                                              
                                          

     

                                                   
       
                                                    
                      
                                         






                                                               
                                                                            
                                                        

                                 

                                                 
       
               

     

                                 

                                                                     
       
                                           






                                                                                       
         
                  
 

                                                                             

                                                                     
 
                


                                             
                                                       



                              
                
                                        
                                                  


                                                                                    

                                                                                                 



                                              
                
                                           
                                                  






                                                                                    


                               
                    




                                                 
                                  
                                               
                                 
                                       



               



                                
                                
 
                                                 
                            
                                                                  
                            
                                                                      
                                                                                   

                                                                      
                                                                                             




                                                        
                                                     
                                                                  
                                    
                                                      

                                    
                      
                                       

                                 
                                                   


                           
                                      


                             
                         
     
 

                                   
                                                            
                

                                
                              


                          

                                                          
                        


                                             


                            

                                    



                                       
                   
                         

                                                               
                          


                                       


                                                      
                                         


                         

                                                   





                                                                   
                                         
                      


                                                     




                                                              













                                                          



                                                                                
                                                                

                         

               
                             






                                                                 
                                  
                                        
                                                               
                                     
                                                 
                            


                                                                             
                                     
                                                              
                    
                                                           
             
                                                      
                            
                                                                                   
                                                                        

                                                                                      
             

                                               

                                       
                                     


                                     
                           

           
                                                           
                                     
                                                                                          


           

     
                                                        
                                    
                                                                            

                               

                            
                       
                          
                                                                              

                                                           

                                                 
                          
                                          
                

                                    

                                                              
                                                        
         



                                           










                                                                       
                                                                       

                            
                                        
                          



                                                                              
                                                                                       

                               
                                                 
                                             

                               
                                                                       

                                                                               

                                
                                                                                       
                              
  
              
                    

       
                                                                                            

                                    
                                
                            
                                          

                                      

                                           
                                                 

                              

                        
                      


                                                                            
                        
                           
                                                            




                                   
                                       
                  
                           

                                           
                                                             
                            



                                                                    

                                                     










                                                            
                                                                  
                                                  
                                   
                                                                        
                                
                                      
                            
                                          
             
                                                                          
                                                        
           

                      


                                                                                     
                                                                  
                                                                                               
           
                                                                             
                           
       









                                                                                         
                   
             
         



                                                                                 






                                         
                         
              
                      
                                                               

                      


       
                                                         

                             
                                       
                                                              
                               
       
                    



                              
                                                 



                                                                   
 


                                              


                                      


               
                                                                 


                               
                           
                   
                                                                          
                        
                                                              

       
                                                                 
                                 
                                             

                            
                                           
                                                               
                                                       
                      
                                                                           





                                            
                                                


                               
                                               
                         

                                                  


                                                                              

                                                           
                                                                        
                                   
                          
                                 

                                                                      







                                                        

                             
                                      
                                         
                                           
                                               

                                                 


              
                                        
 

                                               
                                  

                                               

                                       

                                                                              
                                                   
                
                               
                 
                                                                                
                                                                  


                   

         






                                                 
                             
                           
                 
                             

                                             
                                                  

                                                          


                    
                   

             








                                                               

                                    
                             


                                                 
                                                     

                                                    
       
                                         
                          
                                                                               

                                                           
               
                                                  



                                            










                                                                   


                                    
                                       
                                                             
                                              
                                                                   



                                                
                                                                             
                                                                   
                                                

                                                              
                                                  
                          



                                                         
                                          



                       




                                   
                                                                              



                                                        
                                 
                                                                                    
                                        
                                                                                      

                    
                                                     
                                                                                                             
                            
                    

                                
                                                                                                                   




                                                

                      
                      
                            
               
                                     
                                                                              
                                                                                           
                                                                        
                        

     



















                                                                                  

                                                                                 













                                                                                     
                                               

















                                                                             

                                                                                        



                        
                                
                                   
                                    
                              
       

                                                             
                        
                                            
                     
                                         
                      
                                          
                       
                                                               
                         
                                                                 
                        
                                            
                        
                                            
                 

              
                  

     

                                                               
       
                                       
                                                             
                        
                                            
                     
                                         
                      
                                          
                        
                                            
                 

              
                  



                                                                              

                                                                       
                                    

                                                                                      
                                                      
       
                                                                                                          

                                 
                             
                              

                                           
                                 
                                                    
                                  
                            
                                         
                                         

                            
                                                                
                                                                         
             
                                                           
           
                            















                                                                                         
                                                                                             
         
       
                                         
                                           


                                       
                                                                                             
                          

                                        
                           


                                             

                     
       


                                            
                                                      




                                        
       
                             
                                     
                            
                                                                                    
                                 
                                                                    

                                                                                              
            
                                                                                            
                                                    





                                                 



                                                                            
            
                     
                                         
                        






                                                                          



                                                                                             
       
                                                                                                
                                     
                                         
                                          
                                

                                         
                                        

                                             
           
         
                               
                           
                                                          

                                                               



                                                                      

                                             
                                 

                             
                                   

                               
         
                        



                   
                                              
       
                                                             
                                       
                                               
                                         



                                                    


                                                                              
 


                                                      

                                                  
                                 
                                          






                                                                
                            

                          
                               
                                                                 
                                                
                           
                
                                                         
                           
                                 
                          
                                                        
                                                  
                             
                  
                 



                                   
                          
                                                 
                                          

                                        
                              

                                                
                               

                    
                                           






                                                                               

                                                 

                                        
                                            

                                      
       
                    




                                                  
                                                                  
                               
                                                           
              
                          
                  

                                  
                          
                                                                                 
                  
                
            


             


                             
                                         
                          


                             
                                         
       
                                               

                      
                           
                   
                           
                   
                                 
                    

                        

                                  
                             
       



                                                              
                                                    

                                    
          
                      
                              
                                 
                         
               

                                                          
                                            

                   
                                         
                                                               

                             



                                    
                                                    


                                                    
                                                                                         


             
       
                                                           





                                                  
                                                    
                                        
                                           
          
                                        
                                 
                         
                                                       
                      
                                                
                        
                   


                
              
                                          
                 
       
                                               
                                                                         

     
                                           


                                                                               

                                                       
                                            
                             
                               
                        


                                                                                                  
                                                                          
                

                            


                                                                          
                                  
                   

                                                                                
                                                
                       

                                                               
                         
                               

                                                                
       

                                           
                                        
       

                                                                                 
 
                                                              
       
                                                            


                                                                
                                                                                              

         
 

                                                                                 
                                                         
                             
                                           
                                            


                                                        
                                



                        
                                                 

                                 
                                             
                            
                                     

                          
                                                        
                          

                                                    
                          



                                                                       
                                                                        
                     


         

                                            
                                   
       

                                                         
                                                     
                   
                      
                       
                                   
                    
                       
                        
                                    
               
                                                                     
                 
     
 


                                                                                     
       
                                             
                             
                                     



                                                               
                                                                            



                                                                                 
                                       


                                                                          
                                            
                             


                                                                      
       
 
                                            
       
                                               
                             
                          
                                                                
                                       
       
 



                                                                                   
       
                                                                                                                   
                            

                                                           
                                                                 
                                                          
                                                                            
                                  
         

                                              
                                  
                        
                                        
                                                        
                           
                                                               
                                                                      
                              
                                    
                          
                                        
           
                

                                                                
                                                                                      

                         
                                               
                                           
                                       
                                  
         

                                        


                                                                  
                                                                                              
                               
       

                                                                                 
 
                                                                                 

                                      



                                              


          
                                                                           

                                    


                                








                                                                               



                                



                                 

                                                             




                                    
                                      

                                                     
                              
                                        
                                  






                                            
                                        
                                                                               
                                                             
                                                                              
         
                                                                  



                  
                                                                           






                                                           
                                      

                                                     
                                  
                                 
                         
                                                                      
                                        
                                                                          
                                                             
                                                                      
         
                                                                  




                                                
                                                                          
       

                                               
                                    

                            
                                   
                        
                              
         

                        



                  
                                                                                              
       
                                  
                                   

                               
                                                 
                      
                                                                
       

                                               
                               
                                                                     
                                                                    
                                                                

                                                         
                                   
                        

                                 
                      


                                                    
                                                       
     
 



                                                    
                                        
                                     










                                      



                 
                                                                       




                                         
                                      

                                                     
                                                 
                                                             
                                                                       
         
                                               



                  
                                                                      
                               
                                       
                                               
                              
                        
                                                        
       


                                                                                      









                                                                                      

                                                                                        
                                 

                                  
                                 

                                    
                                                     

                                       
                                                        
             
                                      
                                    
                                                       


                                                                                         

                                                                                   

                              
                                                                     
                                
                          
                                     
                                    
                                                             
                        
                
                                                                     
         



                  
                                                                        

                                                             
       
                                 
                            
                                     
                                  

                            
                                                                           
                          
                                                  
                  
                          
                                                  
                          
                               
           
                





                                                                       
         
       

   
/* NSC -- new Scala compiler
 * Copyright 2005-2006 LAMP/EPFL
 * @author  Martin Odersky
 */
// $Id$
//todo: allow infix type patterns


package scala.tools.nsc.ast.parser

import scala.tools.nsc.util.{ListBuffer, Position}
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 requires SyntaxAnalyzer {

  import global._
  import RequiresIntsAsPositions._
  private val glob: global.type = global
  import global.posAssigner.atPos

  class Parser(unit: global.CompilationUnit) {

    val in = new Scanner(unit)

    /** the markup parser */
    val xmlp = new MarkupParser(unit, in, Parser.this, true)

    object treeBuilder extends TreeBuilder {
      val global: Parsers.this.global.type = Parsers.this.global
      def freshName(prefix: String): Name = unit.fresh.newName(prefix)
    }
    import treeBuilder._

    object symbXMLBuilder extends SymbolicXMLBuilder(treeBuilder, Parser.this, true) { // DEBUG choices
      val global: Parsers.this.global.type = Parsers.this.global
      def freshName(prefix: String): Name = unit.fresh.newName(prefix)
    }

    var implicitClassViews: List[Tree] = Nil

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

/////// ERROR HANDLING //////////////////////////////////////////////////////

    private def skip(): unit = {
      //System.out.println("<skipping> " + in.token2string(in.token))//DEBUG
      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 RPAREN =>
            nparens = nparens - 1
          case RBRACE =>
            if (nbraces == 0) return
            nbraces = nbraces - 1
          case LPAREN =>
            nparens = nparens + 1
          case LBRACE =>
            nbraces = nbraces + 1
          case _ =>
        }
        in.nextToken()
      }
    }

    def syntaxError(msg: String, skipIt: boolean): unit =
      syntaxError(in.currentPos, msg, skipIt)

    def syntaxError(pos: int, msg: String, skipIt: boolean): unit = {
      if (pos != in.errpos) {
        unit.error(pos, msg)
        in.errpos = pos
      }
      if (skipIt) {
        in.skipping = true
        skip()
        in.skipping = false
      }
    }

    def syntaxErrorMigrate(msg: String) =
      syntaxError(in.currentPos, migrateMsg + msg, false)

    def warning(msg: String) =
      if (in.currentPos != in.errpos) {
        unit.warning(in.currentPos, msg)
        in.errpos = in.currentPos
      }

    def incompleteInputError(pos: int, msg: String): unit = {
      if (pos != in.errpos) {
        unit.incompleteInputError(pos, msg)
        in.errpos = pos
      }
    }

    def incompleteInputError(msg: String): unit =
      incompleteInputError(in.currentPos, msg)  // in.currentPos should be at the EOF

    def syntaxErrorOrIncomplete(msg: String, skipIt: Boolean): unit = {
      if(in.token == EOF)
        incompleteInputError(msg)
      else
        syntaxError(in.currentPos, 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 = in.currentPos
      if (in.token != token) {
        val posToReport =
          if (Position.line(unit.source, in.currentPos) >
              Position.line(unit.source, in.lastPos))
            in.lastPos
          else
            in.currentPos
        val msg =
          in.token2string(token) + " expected but " +
          in.token2string(in.token) + " found."

        if(in.token == EOF)
          incompleteInputError(posToReport, msg)
        else
          syntaxError(posToReport, msg, true)
      }
      if (in.token == token) in.nextToken()
      pos
    }

    /** StatementSeparator = NewLine | `;'
     *  NewLine  = `\n' // where allowed
     */
    def acceptStatSep(): unit =
      if (in.token == NEWLINE) in.nextToken() else accept(SEMI)

    def errorTypeTree = TypeTree().setType(ErrorType).setPos(in.currentPos)
    def errorTermTree = Literal(Constant(null)).setPos(in.currentPos)
    def errorPatternTree = Ident(nme.WILDCARD).setPos(in.currentPos)

/////// TOKEN CLASSES //////////////////////////////////////////////////////

    def isModifier: boolean = in.token match {
      case ABSTRACT | FINAL | SEALED | PRIVATE | PROTECTED | OVERRIDE | IMPLICIT => true
      case _ => false
    }

    def isLocalModifier: boolean = in.token match {
      case ABSTRACT | FINAL | SEALED | IMPLICIT => 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)


/////// COMMENT AND ATTRIBUTE COLLECTION //////////////////////////////////////

    /** Join the comment associated with a definition
    */
    def joinComment(trees: => List[Tree]): List[Tree] = {
      val buf = in.docBuffer
      if (buf ne null) {
        in.docBuffer = null
        trees map (t => DocDef(buf.toString(), t) setPos t.pos)
      } else trees
    }

/////// TREE CONSTRUCTION ////////////////////////////////////////////////////

    /** Convert tree to formal parameter list
    */
    def convertToParams(t: Tree): List[ValDef] = t match {
      case Function(params, TypeTree()) =>
        params
      case Ident(_) | Typed(Ident(_), _) =>
        List(convertToParam(t))
      case Literal(c) if c.tag == UnitTag =>
        Nil
      case _ =>
        syntaxError(t.pos, "malformed formal parameter list", false)
        Nil
    }

    /** Convert tree to formal parameter
    */
    def convertToParam(tree: Tree): ValDef =
      atPos(tree.pos) {
        tree match {
          case Ident(name) =>
            ValDef(Modifiers(Flags.PARAM), name, TypeTree(), EmptyTree)
          case Typed(Ident(name), tpe) =>
            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 */
    def makeClosure(tree: Tree): Tree = {
      val pname: Name = unit.fresh.newName("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
        }
      }

      Function(
        List(ValDef(Modifiers(Flags.PARAM), pname, TypeTree(), EmptyTree)),
        wrapLiftedGenerators(insertParam(tree)))
    }

/////// OPERAND/OPERATOR STACK /////////////////////////////////////////////////

    case class OpInfo(operand: Tree, operator: Name, pos: int)
    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
          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(pos: 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)

    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)
      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)
        }
        opstack = opstack.tail
      }
      top
    }

/////// IDENTIFIERS AND LITERALS ////////////////////////////////////////////////////////////

    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 OPT  : Name = "?"
    final val LT   : Name = "<"

    def ident(): Name =
      if (in.token == IDENTIFIER || in.token == BACKQUOTED_IDENT) {
        val name = in.name.encode
        in.nextToken()
        name
      } else {
        if (settings.migrate.value && in.token == MATCH || in.token == REQUIRES || in.token == IMPLICIT)
          syntaxErrorMigrate(""+in+" is now a reserved word; cannot be used as identifier")
        accept(IDENTIFIER)
        nme.ERROR
      }

    def selector(t: Tree) = {
      if (in.token == MATCH && settings.migrate.value)
        syntaxErrorMigrate("Period should be omitted before `match'")
      Select(t, ident())
    }

    /** Path       ::= StableId
     *              |  [Ident `.'] this
     *  SimpleType ::= Path [`.' type]
     */
    def path(thisOK: boolean, typeOK: boolean): Tree = {
      var t: Tree = null
      if (in.token == THIS) {
        t = atPos(in.skipToken()) { This(nme.EMPTY.toTypeName) }
        if (!thisOK || in.token == DOT)
          t =  selectors(t, typeOK, accept(DOT))
      } else if (in.token == SUPER) {
        t = atPos(in.skipToken()) {
          Super(nme.EMPTY.toTypeName, mixinQualifierOpt())
        }
        t = atPos(accept(DOT)) { selector(t) }
        if (in.token == DOT)
          t = selectors(t, typeOK, in.skipToken())
      } else {
        val i = atPos(in.currentPos) {
          if (in.token == BACKQUOTED_IDENT) new BackQuotedIdent(ident())
          else Ident(ident())
        }
        t = i
        if (in.token == DOT) {
          val pos = in.skipToken()
          if (in.token == THIS) {
            in.nextToken()
            t = atPos(i.pos) { This(i.name.toTypeName) }
            if (!thisOK || in.token == DOT)
              t = selectors(t, typeOK, accept(DOT))
          } else if (in.token == SUPER) {
            in.nextToken()
            t = atPos(i.pos) { Super(i.name.toTypeName, mixinQualifierOpt()) }
            t = atPos(accept(DOT)) {selector(t)}
            if (in.token == DOT)
              t = selectors(t, typeOK, in.skipToken())
          } else {
            t = selectors(t, typeOK, pos)
          }
        }
      }
      t
    }

    def selectors(t: Tree, typeOK: boolean, pos : Int): Tree =
      if (typeOK && in.token == TYPE) {
        in.nextToken()
        atPos(pos) { SingletonTypeTree(t) }
      } else {
        val t1 = atPos(pos) { 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 [MixinQualifier] ` `.' Id
    */
    def stableId(): Tree =
      path(false, false)

    /** QualId ::= Id {`.' Id}
    */
    def qualId(): Tree = {
      val id = atPos(in.currentPos) { Ident(ident()) }
      if (in.token == DOT) { selectors(id, false, in.skipToken()) }
      else id
    }

    /** SimpleExpr    ::= literal
    *                  | symbol [ArgumentExprs]
    *                  | null
    */
    def literal(isPattern: boolean, isNegated: boolean): Tree = {
      def litToTree() = atPos(in.currentPos) {
        Literal(
          in.token match {
            case CHARLIT =>
              Constant(in.intVal.asInstanceOf[char])
            case INTLIT =>
              Constant(in.intVal(isNegated).asInstanceOf[int])
            case LONGLIT =>
              Constant(in.intVal(isNegated))
            case FLOATLIT =>
              Constant(in.floatVal(isNegated).asInstanceOf[float])
            case DOUBLELIT =>
              Constant(in.floatVal(isNegated))
            case STRINGLIT | SYMBOLLIT =>
              Constant(in.name.toString())
            case TRUE =>
              Constant(true)
            case FALSE =>
              Constant(false)
            case NULL =>
              Constant(null)
            case _ =>
              syntaxErrorOrIncomplete("illegal literal", true)
              null
          })
      }

      val isSymLit = in.token == SYMBOLLIT
      val t = litToTree()
      val pos = in.skipToken()
      if (isSymLit) {
        atPos(pos) {
          var symid = scalaDot(nme.Symbol)
          if (isPattern) { symid = /*convertToTypeId*/(symid) }
          val symobj = Apply(symid, List(t))
          if (isPattern) symobj else Select(symobj, nme.intern)
        }
      } else {
        t
      }
    }

    def newLineOpt(): unit =
      if (in.token == NEWLINE) {
        if (settings.migrate.value) in.newNewLine = false
        in.nextToken()
      }

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

    def newLineOptWhenFollowing(p: int => boolean): unit = {
      // 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()

    /** RequiresTypedOpt ::= [`:' SimpleType | requires SimpleType]
    */
    def requiresTypeOpt(): Tree =
      if (in.token == COLON | in.token == REQUIRES) {
        if (in.token == COLON)
          warning("`:' has been deprecated; use `requires' instead")
        in.nextToken(); simpleType(false)
      }
      else TypeTree()

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

    /** modes for infix types */
    final val FirstOp = 0   // first operand
    final val LeftOp = 1    // left associative
    final val RightOp = 2   // right associative

    /** Type ::= InfixType `=>' Type
     *         | `(' [Types | `=>' Type] `)' `=>' Type
     *         | InfixType
     */
    def typ(): Tree = {
      val t =
        if (in.token == LPAREN) {
          in.nextToken()
          if (in.token == RPAREN) {
            in.nextToken()
            atPos(accept(ARROW)) { makeFunctionTypeTree(List(), typ()) }
          } else if (in.token == ARROW) {
            in.nextToken()
            val t0 = typ()
            accept(RPAREN)
            atPos(accept(ARROW)) { makeByNameFunctionTypeTree(t0, typ()) }
          } else {
            val pos = in.currentPos
            val t0 = typ()
            if (in.token == COMMA) {
              in.nextToken()
              val ts = t0 :: types()
              accept(RPAREN)
              checkSize("function arguments", ts.length, definitions.MaxFunctionArity)
              atPos (accept(ARROW)) { makeFunctionTypeTree(ts, typ()) }
            } else {
              accept(RPAREN)
              infixTypeRest(pos, t0, false, FirstOp)
            }
          }
        } else {
          infixType(false, FirstOp)
        }
      if (in.token == ARROW) atPos(in.skipToken()) {
        makeFunctionTypeTree(List(t), typ()) }
      else t
    }

    /** InfixType ::= CompoundType {id [NewLine] CompoundType}
     *  TypePattern ::= CompoundTypePattern {id [NewLine] CompoundTypePattern
     */
    def infixType(isPattern: boolean, mode: int): Tree =
      infixTypeRest(in.currentPos, simpleType(isPattern), isPattern, mode)

    def infixTypeRest(pos: int, t0: Tree, isPattern: boolean, mode: int): Tree = {
      val t = compoundTypeRest(pos, t0, isPattern)
      if (isIdent && in.name != nme.STAR) {
        val opPos = in.currentPos
        val leftAssoc = treeInfo.isLeftAssoc(in.name)
        if (mode == LeftOp) checkAssoc(opPos, in.name, true)
        else if (mode == RightOp) checkAssoc(opPos, in.name, false)
        val op = ident()
        newLineOptWhenFollowing(isTypeIntroToken)
        def mkOp(t1: Tree) = atPos(opPos) { AppliedTypeTree(Ident(op.toTypeName), List(t, t1)) }
        if (leftAssoc)
          infixTypeRest(in.currentPos, mkOp(compoundType(isPattern)), isPattern, LeftOp)
        else
          mkOp(infixType(isPattern, RightOp))
      } else t
    }

    /** CompoundType ::= SimpleType {with SimpleType} [Refinement]
     *  CompoundTypePattern ::= SimpleTypePattern {with SimpleTypePattern}
     */
    def compoundType(isPattern: boolean): Tree =
      compoundTypeRest(in.currentPos, simpleType(isPattern), isPattern)

    def compoundTypeRest(pos: int, t: Tree, isPattern: boolean): Tree = {
      var ts = new ListBuffer[Tree] + t
      while (in.token == WITH) {
        in.nextToken(); ts += simpleType(isPattern)
      }
      atPos(pos) {
        if (in.token == LBRACE && !isPattern) CompoundTypeTree(Template(ts.toList, refinement()))
        else makeIntersectionTypeTree(ts.toList)
      }
    }

    /** SimpleType        ::=  {`@' Attribute} SimpleType1
     *  SimpleType1       ::=  SimpleType1 TypeArgs
     *                     |   SimpleType1 `#' Id
     *                     |   StableId
     *                     |   Path `.' type
     *                     |   `(' Type `)'
     *                     |   `{' [Type `,' [Types [`,']]] `}'
     *                     |   TypeAttributes SimpleType (if -Xplugtypes)
     * SimpleTypePattern  ::=  SimpleTypePattern1 [TypePatternArgs]
     * SimpleTypePattern1 ::=  SimpleTypePattern1 "#" Id
     *                     |   StableId
     *                     |   Path `.' type
     *                     |   `{' [ArgTypePattern `,' [ArgTypePatterns [`,']]] `}'
     */
    def simpleType(isPattern: boolean): Tree = {
      val attribs = typeAttributes()
      val pos = in.currentPos
      var t: Tree =
        if (in.token == LPAREN && !isPattern) {
          in.nextToken()
          val t = typ()
          accept(RPAREN)
          t
        } else if (in.token == LBRACE) {
          in.nextToken()
          val ts = if (in.token == RBRACE) List()
                   else {
                     val t1 = argType(isPattern)
                     accept(COMMA)
                     t1 :: (if (in.token == RBRACE) List() else argTypes(isPattern, true))
                   }
          checkSize("tuple elements", ts.length, definitions.MaxTupleArity)
          accept(RBRACE)
          makeTupleType(ts, false)
        } else {
          val r = path(false, true)
          val x = r match {
            case SingletonTypeTree(_) => r
            case _ => convertToTypeId(r)
          }
          // System.err.println("SIMPLE_TYPE: " + r.pos + " " + r + " => " + x.pos + " " + x)
          x
        }

      // scan for # and []
      var done = false
      while (!done) {
        if (in.token == HASH) {
          t = atPos(in.skipToken()) {
            SelectFromTypeTree(t, ident().toTypeName)
          }
        } else if (in.token == LBRACKET) {
          t = atPos(pos) { AppliedTypeTree(t, typeArgs(isPattern)) }
          if (isPattern) done=true
        } else
          done=true
      }
      if (settings.Xplugtypes.value) t.withAttributes(attribs)
      else (t /: attribs) (makeAttributed)
    }

    /** TypeArgs        ::= `[' ArgTypes `]'
     *  TypePatternArgs ::= '[' ArgTypePatterns `]'
     */
    def typeArgs(isPattern: boolean): List[Tree] = {
      accept(LBRACKET)
      val ts = argTypes(isPattern, false)
      accept(RBRACKET)
      ts
    }

    /** ArgTypes        ::= ArgType {`,' ArgType}
     *  ArgTypePatterns ::= ArgTypePattern {`,' ArgTypePattern}
     */
    def argTypes(isPattern: boolean, trailingComma: boolean): List[Tree] = {
      val ts = new ListBuffer[Tree] + argType(isPattern)
      while (in.token == COMMA) {
        in.nextToken()
        if (!trailingComma || in.token != RBRACE)
          ts += argType(isPattern)
      }
      ts.toList
    }

    /** ArgType       ::= Type
     *  ArgTypePattern ::=  varid
     *                 |  `_'
     *                 |  Type            // for array elements only!
     */
    def argType(isPattern: boolean): Tree =
      if (isPattern) {
        if (in.token == USCORE)
          atPos(in.skipToken()) { Bind(nme.WILDCARD.toTypeName, EmptyTree) }
        else if (in.token == IDENTIFIER && treeInfo.isVariableName(in.name.toTypeName))
          atPos(in.currentPos) { Bind(ident().toTypeName, EmptyTree) }
        else {
          typ()
        }
      } else typ()

//////// EXPRESSIONS ////////////////////////////////////////////////////////

    // XX_LIFTED
    var liftedGenerators = new collection.mutable.ListBuffer[ValFrom]

    // XX_LIFTED
    def wrapLiftedGenerators(t: Tree): Tree =
      if (liftedGenerators.isEmpty) t
      else {
        val t1 = makeLifted(liftedGenerators.toList, t)
        liftedGenerators.clear
        t1
      }

    // XX_LIFTED
    def noLifting(op: => Tree): Tree = {
      val savedLiftedGenerators = liftedGenerators
      if (!savedLiftedGenerators.isEmpty) // optimization to avoid buffer allocation
        liftedGenerators = new collection.mutable.ListBuffer
      val t = op
      if (!liftedGenerators.isEmpty)
        syntaxError(liftedGenerators.toList.head.pos, "no lifted expression allowed here", false)
      liftedGenerators = savedLiftedGenerators
      t
    }

    // XX_LIFTED
    def liftingScope(op: => Tree): Tree = {
      val savedLiftedGenerators = liftedGenerators
      if (!savedLiftedGenerators.isEmpty) // optimization to avoid buffer allocation
        liftedGenerators = new collection.mutable.ListBuffer
      val t = wrapLiftedGenerators(op)
      liftedGenerators = savedLiftedGenerators
      t
    }

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

    /** Exprs ::= Expr {`,' Expr} [ `:' `_' `*' ]
     */
    def argExprs(): List[Tree] = {
      val ts = new ListBuffer[Tree] + argExpr()
      while (in.token == COMMA) {
        in.nextToken(); ts += argExpr()
      }
      ts.toList
    }

    /** expression modifiles */

    final val IsArgument     = 1
    final val IsInBlock      = 2
    final val ClosureOK      = 4

    /** Expr       ::= (Bindings | Id)  `=>' Expr
     *               | Expr1
     *  ResultExpr ::= (Bindings | Id `:' CompoundType) `=>' Block
     *               | Expr1
     *  Expr1      ::= if (' Expr `)' [NewLine] Expr [[`;'] else Expr]
     *               | try `{' block `}' [catch `{' caseClauses `}'] [finally Expr]
     *               | while `(' Expr `)' [NewLine] Expr
     *               | do Expr [StatementSeparator] while `(' Expr `)'
     *               | for (`(' Enumerators `)' | '{' Enumerators '}') [NewLine] [yield] Expr
     *               | throw Expr
     *               | return [Expr]
     *               | [SimpleExpr `.'] Id `=' Expr
     *               | SimpleExpr ArgumentExprs `=' Expr
     *               | `.' SimpleExpr
     *               | PostfixExpr [`:' CompoundType]
     *               | PostfixExpr match [`!'] `{' CaseClauses `}'
     *               | MethodClosure
     *  Bindings   ::= `(' [Binding {`,' Binding}] `)'
     *  Binding    ::= Id [`:' Type]
     */
    def expr(): Tree =
      liftingScope(exprImpl(ClosureOK))

    def blockStatExpr(): Tree = {
      liftingScope(exprImpl(IsInBlock | ClosureOK))
    }

    def argExpr(): Tree = {
      exprImpl(IsArgument | ClosureOK)
    }

    def localExpr(): Tree = {
      exprImpl(ClosureOK)
    }

    def expr1(): Tree = exprImpl(0)

    private def exprImpl(mode: int): Tree = in.token match {
      case IF =>
        val pos = in.skipToken()
        accept(LPAREN)
        val cond = localExpr()
        accept(RPAREN)
        newLineOpt()
        val thenp = expr()
        val elsep =
          if (in.token == ELSE) { in.nextToken(); expr() }
          else EmptyTree
        atPos(pos) { If(cond, thenp, elsep) }
      case TRY =>
        atPos(in.skipToken()) {
          accept(LBRACE)
          val body = block()
          accept(RBRACE)
          val catches =
            if (in.token == CATCH) {
              in.nextToken()
              accept(LBRACE)
              val cases = caseClauses()
              accept(RBRACE)
              cases
            } else List()
          val finalizer =
            if (in.token == FINALLY) { in.nextToken(); expr() }
            else EmptyTree
          Try(body, catches, finalizer)
        }
      case WHILE =>
        val lname: Name = unit.fresh.newName("while$")
        val pos = in.skipToken()
        accept(LPAREN)
        val cond = noLifting(localExpr())
        accept(RPAREN)
        newLineOpt()
        val body = expr()
        atPos(pos) { makeWhile(lname, cond, body) }
      case DO =>
        val lname: Name = unit.fresh.newName("doWhile$")
        val pos = in.skipToken()
        val body = expr()
        if (in.token == SEMI || in.token == NEWLINE) in.nextToken()
        accept(WHILE)
        accept(LPAREN)
        val cond = noLifting(localExpr())
        accept(RPAREN)
        atPos(pos) { makeDoWhile(lname, body, cond) }
      case FOR =>
        atPos(in.skipToken()) {
          val startToken = in.token
          accept(if (startToken == LBRACE) LBRACE else LPAREN)
          val enums = enumerators()
          accept(if (startToken == LBRACE) RBRACE else RPAREN)
          newLineOpt()
          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 DOT =>
        atPos(in.skipToken()) {
          if (isIdent) {
            liftingScope(makeClosure(simpleExpr()))
            // Note: makeClosure does some special treatment of liftedGenerators
          } else {
            syntaxErrorOrIncomplete("identifier expected", true)
            errorTermTree
          }
        }
      case _ =>
        var t = postfixExpr()
        if (in.token == EQUALS) {
          t match {
            case Ident(_) | Select(_, _) | Apply(_, _) =>
              t = atPos(in.skipToken()) { makeAssign(t, expr()) }
            case _ =>
          }
        } else if (in.token == COLON) {
          val pos = in.skipToken()
          val attribs = typeAttributes()
          if ((mode & IsArgument) != 0 && in.token == USCORE) {
            val pos1 = in.skipToken()
            if (isIdent && in.name == nme.STAR) {
              in.nextToken()
              t = atPos(pos) {
                Typed(t, atPos(pos1) { Ident(nme.WILDCARD_STAR.toTypeName) })
              }
              if (in.token != RPAREN)
                syntaxErrorOrIncomplete("`)' expected", false)
            } else {
              syntaxErrorOrIncomplete("`*' expected", true)
            }
          } else if (attribs.isEmpty || isTypeIntro) {
            t = atPos(pos) {
              val tpt = if ((mode & IsInBlock) != 0) compoundType(false) else typ()
              // this does not correspond to syntax, but is necessary to
              // accept closures. We might restrict closures to be between {...} only!
              Typed(t, (tpt /: attribs) (makeAttributed))
            }
          } else {
            t = (t /: attribs) (makeAttributed)
          }
        } else if (in.token == MATCH) {
          t = atPos(in.skipToken()) {
            accept(LBRACE)
            val cases = caseClauses()
            accept(RBRACE)
            Match(t, cases)
          }
        }
        if ((mode & ClosureOK) != 0 && in.token == ARROW) {
          t = atPos(in.skipToken()) {
            Function(convertToParams(t), if ((mode & IsInBlock) != 0) block() else expr())
          }
        }
        t
    }

    /** PostfixExpr   ::= [`.'] InfixExpr [Id [NewLine]]
     *  InfixExpr     ::= PrefixExpr
     *                  | InfixExpr Id [NewLine] (InfixExpr | ArgumentExprs)
     */
    def postfixExpr(): Tree = {
      val base = opstack
      var top = prefixExpr()
      while (isIdent) {
        top = reduceStack(
          true, base, top, precedence(in.name), treeInfo.isLeftAssoc(in.name))
        val op = in.name
        opstack = OpInfo(top, op, in.currentPos) :: opstack
        ident()
        newLineOptWhenFollowing(isExprIntroToken)
        if (isExprIntro) {
          top = secondInfixOperandExpr(op)
        } else {
          val topinfo = opstack.head
          opstack = opstack.tail
          return Select(
            reduceStack(true, base, topinfo.operand, 0, true),
            topinfo.operator.encode).setPos(topinfo.pos)
        }
      }
      reduceStack(true, base, top, 0, true)
    }

    def secondInfixOperandExpr(op: Name): Tree =
      if (in.token == LPAREN && treeInfo.isLeftAssoc(op)) {
        val pos = in.currentPos
        val args = argumentExprs()
        if (args.isEmpty) simpleExprRest(Literal(()) setPos pos, false)
        else if (args.tail.isEmpty) simpleExprRest(args.head, false)
        else ArgumentExprs(args)
      } else {
        prefixExpr()
      }

    /** PrefixExpr   ::= [`-' | `+' | `~' | `!' | `&' | `/'] SimpleExpr
    */
    def prefixExpr(): Tree =
      if (isIdent && in.name == MINUS) {
        val name = ident()
        in.token match {
          case INTLIT | LONGLIT | FLOATLIT | DOUBLELIT => literal(false, true)
          case _ => atPos(in.currentPos) { Select(simpleExpr(), name) }
        }
      } else if (isIdent && (in.name == PLUS || in.name == TILDE || in.name == BANG)) {
        val pos = in.currentPos
        val name = ident()
        atPos(pos) { Select(simpleExpr(), name) }
      } else if (isIdent && in.name == AMP) {
        val pos = in.currentPos
        val name = ident()
        atPos(pos) { Typed(simpleExpr(), Function(List(), EmptyTree)) }
/* XX-LIFTING
      } else if (settings.Xexperimental.value && isIdent && in.name == SLASH) {
        val pos = in.skipToken()
        val name = freshName()
        liftedGenerators += ValFrom(pos, Bind(name, Ident(nme.WILDCARD)), simpleExpr())
        Ident(name) setPos pos
*/
      } else {
        simpleExpr()
      }

    /* SimpleExpr    ::= new SimpleType {`(' [Exprs] `)'} {`with' SimpleType} [TemplateBody]
     *                |  SimpleExpr1
     * SimpleExpr1   ::= literal
     *                | xLiteral
     *                | Path
     *                | StableId `.' class
     *                | `(' [Expr] `)'
     *                | BlockExpr
     *                | SimpleExpr `.' Id
     *                | SimpleExpr TypeArgs
     *                | SimpleExpr1 ArgumentExprs
     */
    def simpleExpr(): Tree = {
      var t: Tree = null
      var isNew = false
      in.token match {
        case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT | STRINGLIT |
             SYMBOLLIT | TRUE | FALSE | NULL =>
          t = literal(false, false)
        case XMLSTART =>
          t = xmlp.xLiteral
        case IDENTIFIER | BACKQUOTED_IDENT | THIS | SUPER =>
          t = path(true, false)
        case LPAREN =>
          val pos = in.skipToken()
          if (in.token == RPAREN) {
            in.nextToken()
            t = Literal(()).setPos(pos)
          } else {
            t = localExpr()
            if (in.token == COMMA) {
              val commapos = in.skipToken()
              val ts = new ListBuffer[Tree] + t ++ argExprs()
              accept(RPAREN)
              if (in.token == ARROW) {
                t = atPos(pos) {
                  Function(ts.toList map convertToParam, TypeTree())
                }
              } else if(in.token == EOF) {
                incompleteInputError("`=>' expected")
              } else {
                syntaxError(commapos, "`)' expected", false)
              }
            } else {
              accept(RPAREN)
            }
          }
        case LBRACE =>
          t = blockExpr()
        case NEW =>
          t = atPos(in.skipToken()) {
            val parents = new ListBuffer[Tree] + simpleType(false)
            val argss = new ListBuffer[List[Tree]]
            if (in.token == LPAREN)
              do { argss += argumentExprs() } while (in.token == LPAREN)
            else argss += List()
            while (in.token == WITH) {
              in.nextToken()
              parents += simpleType(false)
            }
            val stats = if (in.token == LBRACE) templateBody() else List()
            makeNew(parents.toList, stats, argss.toList)
          }
          isNew = true
        case _ =>
          if (settings.migrate.value) {
            if (in.token == MATCH)
              syntaxErrorMigrate("`match' must be preceded by a selector expression")
            else if (in.token == REQUIRES || in.token == IMPLICIT)
              syntaxErrorMigrate(""+in+" is now a reserved word; cannot be used as identifier")
          }
          syntaxErrorOrIncomplete("illegal start of simple expression", true)
          t = errorTermTree
      }
      simpleExprRest(t, isNew)
    }

    def simpleExprRest(t: Tree, isNew: boolean): Tree = in.token match {
      case DOT =>
        simpleExprRest(atPos(in.skipToken()) { selector(t) }, false)
      case LBRACKET =>
        t match {
          case Ident(_) | Select(_, _) =>
            simpleExprRest(atPos(in.currentPos) { TypeApply(t, typeArgs(false)) }, false)
          case _ =>
            t
        }
      case LPAREN | LBRACE if (!isNew) =>
        simpleExprRest(atPos(in.currentPos) { Apply(t, argumentExprs()) }, false)
      case _ =>
        t
    }

    /** ArgumentExprs ::= `(' [Exprs] `)'
      *                 | BlockExpr
     */
    def argumentExprs(): List[Tree] = {
      if (in.token == LBRACE) {
        List(blockExpr())
      } else {
        accept(LPAREN)
        val ts = if (in.token == RPAREN) List() else argExprs()
        accept(RPAREN)
        ts
      }
    }

    /** BlockExpr ::= `{' CaseClauses | Block | Tuple `}'
     */
    def blockExpr(): Tree = {
      val res = atPos(accept(LBRACE)) {
        if (in.token == CASE) makeVisitor(caseClauses(), true)
        else blockOrTuple(true)
      }
      accept(RBRACE)
      res
    }

    /** Block ::= BlockStatSeq
     *  Tuple ::= [Expr1 `,' {Expr1 `,'} [Expr1]]
     */
    def block(): Tree = blockOrTuple(false)
    def blockOrTuple(tupleOK: boolean): Tree =
      makeBlock(blockStatSeqOrTuple(tupleOK, 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 [if PostfixExpr] `=>' Block
     */
    def caseClause(): CaseDef =
      atPos(accept(CASE)) {
        val pat = pattern()
        val guard =
          if (in.token == IF) { in.nextToken(); noLifting(postfixExpr()) }
          else EmptyTree
        makeCaseDef(pat, guard, atPos(accept(ARROW))(block()))
      }

    /** Enumerators ::= Generator {StatementSeparator Enumerator}
     *  Enumerator  ::= Generator
     *                | val Pattern1 `=' Expr
     *                | Expr
     */
    def enumerators(): List[Enumerator] = {
      val enums = new ListBuffer[Enumerator] + generator(false)
      while (in.token == SEMI || in.token == NEWLINE) {
        in.nextToken()
        enums += (if (in.token == VAL) generator(true) else Filter(expr()))
      }
      enums.toList
    }

    /** Generator ::= val Pattern1 `<-' Expr
     */
    def generator(eqOK: boolean): Enumerator = {
      val pos = accept(VAL)
      val pat = pattern1(false)
      val tok = in.token
      if (tok == EQUALS && eqOK) in.nextToken()
      else accept(LARROW)
      makeGenerator(pos, pat, tok == EQUALS, expr)
    }

//////// PATTERNS ////////////////////////////////////////////////////////////

    /**   Patterns ::= Pattern { `,' Pattern }  */
    /**   SeqPatterns ::= SeqPattern { `,' SeqPattern }  */
    def patterns(seqOK: boolean, trailingComma: boolean): List[Tree] = {
      val ts = new ListBuffer[Tree]
      ts += pattern(seqOK)
      while (in.token == COMMA) {
        in.nextToken();
        if (!trailingComma || in.token != RBRACE) ts += pattern(seqOK)
      }
      ts.toList
    }

    /**   Pattern  ::=  Pattern1 { `|' Pattern1 }
     *    SeqPattern ::= SeqPattern1 { `|' SeqPattern1 }
     */
    def pattern(seqOK: boolean): Tree = {
      val pos = in.currentPos
      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(pos) { makeAlternative(ts.toList) }
      } else t
    }

    def pattern(): Tree = pattern(false)

    /**   Pattern1    ::= varid `:' TypePattern
     *                 |  `_' `:' TypePattern
     *                 |  Pattern2
     *    SeqPattern1 ::= varid `:' TypePattern
     *                 |  `_' `:' TypePattern
     *                 |  [SeqPattern2]
     */
    def pattern1(seqOK: boolean): Tree = {
      //if (false && /*disabled, no regexp matching*/ seqOK && !isExprIntro) {
        //atPos(in.currentPos) { Sequence(List()) }
      //} else {
        val p = pattern2(seqOK)
        p match {
          case Ident(name) if (treeInfo.isVarPattern(p) && in.token == COLON) =>
            atPos(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) { Bind(name, pattern3(seqOK)) }
            } else {
              p
            }
          case _ =>
            p
        }
      } else p
    }

    /*   Pattern3    ::= SimplePattern
     *                |  SimplePattern {Id SimplePattern}
     *   SeqPattern3 ::= SeqSimplePattern [ '*' | '?' | '+' ]
     *                |  SeqSimplePattern {Id SeqSimplePattern}
     */
    def pattern3(seqOK: boolean): Tree = {
      val base = opstack
      var top = simplePattern(seqOK)
      if (seqOK && isIdent) {
        if (in.name == STAR)
          return atPos(in.skipToken())(Star(top))
        else if (in.name == PLUS)
          return atPos(in.skipToken())(makePlus(top))
        else if (in.name == OPT)
          return atPos(in.skipToken())(makeOpt(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.currentPos) :: opstack
        ident()
        top = secondInfixOperandPattern(op, seqOK)
      }
      reduceStack(false, base, top, 0, true)
    }

    def secondInfixOperandPattern(op: Name, seqOK: boolean): Tree =
      if (in.token == LPAREN && treeInfo.isLeftAssoc(op)) {
        val pos = in.currentPos
        val args = argumentPatterns()
        if (args.isEmpty) Literal(()) setPos pos
        else if (args.tail.isEmpty) args.head
        else ArgumentExprs(args)
      } else {
        simplePattern(seqOK)
      }

    /** SimplePattern    ::= varid
     *                    |  `_'
     *                    |  literal
     *                    |  XmlPattern
     *                    |  StableId [ `(' SeqPatterns `)' ]
     *                    |  `(' [Pattern] `)'
     *                    |  `{' [Pattern `,' [Patterns [`,']]] `}'
     *  SimpleSeqPattern ::= varid
     *                    |  `_'
     *                    |  literal
     *                    |  `<' xLiteralPattern
     *                    |  StableId [TypePatternArgs] `(' SeqPatterns `)' ]
     *                    |  `{' [Pattern `,' [Patterns [`,']]] `}'
     *                    |  `(' SeqPatterns `)'
     */
    def simplePattern(seqOK: boolean): Tree = 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 literal(true, true)
              case _ =>
            }
          case _ =>
        }
/* not yet
        if (in.token == LBRACKET)
          atPos(in.currentPos) {
            val ts = typeArgs(true)
            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(in.currentPos) { Apply(/*convertToTypeId*/(t), argumentPatterns()) }
        } else if (in.token == LBRACE) {
          atPos(in.currentPos) { Apply(/*convertToTypeId*/(t), List(tuplePattern())) }
        } else t
      case USCORE =>
        atPos(in.skipToken()) { Ident(nme.WILDCARD) }
      case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT | STRINGLIT | SYMBOLLIT | TRUE | FALSE | NULL =>
        literal(true, false)
      case LPAREN =>
        val pos = in.skipToken()
        val p =
          //if (false /*disabled, no regexp matching*/ && seqOK) atPos(pos) { makeSequence(patterns(true, false)) }
          //else
          if (in.token != RPAREN) pattern(false)
          else Literal(()).setPos(pos)
        accept(RPAREN)
        p
      case LBRACE =>
        tuplePattern()
      case XMLSTART =>
        xmlp.xLiteralPattern
      case _ =>
        if (settings.migrate.value &&
            in.token == MATCH || in.token == REQUIRES || in.token == IMPLICIT)
          syntaxErrorMigrate(""+in+" is now a reserved word; cannot be used as identifier")
        syntaxErrorOrIncomplete("illegal start of simple pattern", true)
        errorPatternTree
    }

    def argumentPatterns(): List[Tree] = {
      accept(LPAREN)
      val ps = if (in.token == RPAREN) List() else patterns(true, false)
      accept(RPAREN)
      ps
    }

    def tuplePattern(): Tree = {
      in.nextToken()
      val ts = if (in.token == RBRACE) List()
               else {
                 val p1 = pattern()
                 accept(COMMA)
                 p1 :: (if (in.token == RBRACE) List() else patterns(false, true))
               }
      checkSize("tuple elements", ts.length, definitions.MaxTupleArity)
      accept(RBRACE)
      makeTuplePattern(ts)
    }

////////// MODIFIERS ////////////////////////////////////////////////////////////

    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: int): Modifiers = {
      if (mods hasFlag mod) syntaxError(in.currentPos, "repeated modifier", false)
      in.nextToken()
      mods | mod
    }

    /** AccessQualifier ::= "[" (Id | this) "]"
     */
    def accessQualifierOpt(mods: 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 _ =>
          mods
      }
      loop(NoMods)
    }

    /** LocalModifiers ::= {LocalModifier}
     *  LocalModifier  ::= abstract | final | sealed | implicit
     */
    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 _ =>
          mods
      }
      loop(NoMods)
    }

//////// PARAMETERS //////////////////////////////////////////////////////////

    /** ParamClauses ::= {[NewLine] `(' [Param {`,' Param}] ')'}
     *                   [[NewLine] `(' implicit Param {`,' Param} `)']
     *  Param ::= Id [`:' ParamType]
     *  ClassParamClauses ::= {[NewLine] `(' [ClassParam {`' ClassParam}] ')'}
     *                        [[NewLine] `(' implicit ClassParam {`,' ClassParam} `)']
     *  ClassParam ::= [[modifiers] (val | var)] Param
     */
    def paramClauses(owner: Name, implicitViews: List[Tree], ofCaseClass: boolean): List[List[ValDef]] = {
      var implicitmod = 0
      var caseParam = ofCaseClass
      def param(): ValDef = {
        atPos(in.currentPos) {
          val attrs = attributeClauses()
          var mods = Modifiers(Flags.PARAM)
          if (owner.isTypeName) {
            mods = modifiers() | Flags.PARAMACCESSOR
            if (in.token == VAL) {
              in.nextToken()
            } else if (in.token == VAR) {
              mods = mods | Flags.MUTABLE
              in.nextToken()
            } else {
              if (mods.flags != Flags.PARAMACCESSOR) accept(VAL)
              if (!(caseParam)) mods = mods | Flags.PRIVATE | Flags.LOCAL
            }
            if (caseParam) mods = mods | Flags.CASEACCESSOR
          }
          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.currentPos,
                    (if (mods.hasFlag(Flags.MUTABLE)) "`var'" else "`val'") +
                    " parameters may not be call-by-name", false)
                else bynamemod = Flags.BYNAMEPARAM
              }
              paramType()
            }
          ValDef((mods | implicitmod | bynamemod) withAttributes attrs, name, tpt, EmptyTree)
        }
      }
      def paramClause(): List[ValDef] = {
        val params = new ListBuffer[ValDef]
        if (in.token != RPAREN) {
          if (in.token == IMPLICIT) {
            if (!implicitViews.isEmpty)
              syntaxError("cannot have both view bounds `<%' and implicit 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 pos = in.currentPos
      newLineOptWhenFollowedBy(LPAREN)
      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(pos, "no type parameters allowed here", false)
        else if(in.token == EOF)
          incompleteInputError(pos, "auxiliary constructor needs non-implicit parameter list")
        else
          syntaxError(pos, "auxiliary constructor needs non-implicit parameter list", false)
      addImplicitViews(owner, result, implicitViews)
    }

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

    /** TypeParamClauseOpt    ::= [[NewLine] `[' VariantTypeParam {`,' VariantTypeParam} `]']
     *  VariantTypeParam      ::= [`+' | `-'] TypeParam
     *  FunTypeParamClauseOpt ::= [[NewLine] `[' TypeParam {`,' TypeParam} `]']
     *  TypeParam             ::= Id TypeBounds [<% Type]
     */
    def typeParamClauseOpt(owner: Name, implicitViewBuf: ListBuffer[Tree]): List[AbsTypeDef] = {
      def typeParam(): AbsTypeDef = {
        var mods = Modifiers(Flags.PARAM)
        if (owner.isTypeName && isIdent) {
          if (in.name == PLUS) {
            in.nextToken()
            mods = mods | Flags.COVARIANT
          } else if (in.name == MINUS) {
            in.nextToken()
            mods = mods | Flags.CONTRAVARIANT
          }
        }
        val pos = in.currentPos
        val pname = ident()
        val param = atPos(pos) { typeBounds(mods, pname) }
        if (in.token == VIEWBOUND && (implicitViewBuf ne null))
          implicitViewBuf += atPos(in.skipToken()) {
            makeFunctionTypeTree(List(Ident(pname.toTypeName)), typ())
          }
        param
      }
      val params = new ListBuffer[AbsTypeDef]
      //newLineOptWhenFollowedBy(LBRACKET)
      if (in.token == LBRACKET) {
        in.nextToken()
        params += typeParam()
        while (in.token == COMMA) {
          in.nextToken()
          params += typeParam()
        }
        accept(RBRACKET)
      }
      params.toList
    }

    /** TypeBounds ::= [`>:' Type] [`<:' Type]
     */
    def typeBounds(mods: Modifiers, name: Name): AbsTypeDef =
      AbsTypeDef(mods, name.toTypeName,
                 bound(SUPERTYPE, nme.Nothing),
                 bound(SUBTYPE, nme.Any))

    def bound(tok: int, default: Name): Tree =
      if (in.token == tok) { in.nextToken(); typ() }
      else scalaDot(default.toTypeName)

//////// DEFS ////////////////////////////////////////////////////////////////


    /** Import  ::= import ImportExpr {`,' ImportExpr}
     */
    def importClause(): List[Tree] = {
      accept(IMPORT)
      val ts = new ListBuffer[Tree] + importExpr()
      while (in.token == COMMA) {
        in.nextToken(); ts += importExpr()
      }
      ts.toList
    }

    /**  ImportRef ::= StableId `.' (Id | `_' | ImportSelectors)
     */
    def importExpr(): Tree =
      atPos(in.currentPos) {
        var t: Tree = null
        var pos = 0
        if (in.token == THIS) {
          t = atPos(in.currentPos) { This(nme.EMPTY.toTypeName) }
          t = atPos(accept(DOT)) { selector(t) }
          pos = accept(DOT)
        } else {
          val i = atPos(in.currentPos) { Ident(ident()) }
          pos = accept(DOT)
          if (in.token == THIS) {
            in.nextToken()
            t = atPos(i.pos) { This(i.name.toTypeName) }
            t = atPos(accept(DOT)) { selector(t) }
            pos = accept(DOT)
          } else {
            t = i
          }
        }
        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 name = ident()
            if (in.token == DOT) {
              t = atPos(pos) { Select(t, name) }
              pos = accept(DOT)
              loop
            } else {
              Import(t, List({name, name}))
            }
          }
        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 [NewLine] TypeDef
     *           | TmplDef
     *  Dcl    ::= val ValDcl
     *           | var ValDcl
     *           | def FunDcl
     *           | type [NewLine] TypeDcl
     */
    def defOrDcl(mods: Modifiers): List[Tree] =
      in.token match {
        case VAL =>
          patDefOrDcl(mods)
        case VAR =>
          varDefOrDcl(mods)
        case DEF =>
          List(funDefOrDcl(mods))
        case TYPE =>
          in.nextToken()
          newLineOpt()
          List(typeDefOrDcl(mods))
        case _ =>
          List(tmplDef(mods))
      }

    /** PatDef ::= Pattern2 {`,' Pattern2} [`:' Type] `=' Expr
     *  ValDcl ::= Id {`,' Id} `:' Type
     */
    def patDefOrDcl(mods: Modifiers): List[Tree] = {
      var newmods = mods
      var lhs = new ListBuffer[Tree]
      do {
        in.nextToken()
        lhs += pattern2(false)
      } while (in.token == COMMA)
      val tp = typedOpt()
      val rhs =
        if (tp.isEmpty || in.token == EQUALS) equalsExpr()
        else {
          newmods = newmods | Flags.DEFERRED
          EmptyTree
        }
      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),
                     rhs.duplicate) map atPos(p.pos)
        if (rhs == EmptyTree) {
          trees match {
            case List(ValDef(_, _, _, EmptyTree)) =>
            case _ => syntaxError(p.pos, "pattern definition may not be abstract", false)
          }
        }
        trees
      }
      for (val p <- lhs.toList; val d <- mkDefs(p)) yield d
    }

    /** VarDef ::= Id {`,' Id} [`:' Type] `=' Expr
     *           | 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 {
        lhs += {in.skipToken(), 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
      }
      for (val {pos, name} <- lhs.toList) yield
        atPos(pos) { ValDef(newmods, name, tp.duplicate, rhs.duplicate) }
    }

    /** FunDef ::= FunSig `:' Type `=' Expr
                 | FunSig Block
     *           | this ParamClause ParamClauses (`=' ConstrExpr | ConstrBlock)
     *  FunDcl ::= FunSig [`:' Type]
     *  FunSig ::= id [FunTypeParamClause] ParamClauses
     */
    def funDefOrDcl(mods: Modifiers): Tree =
      atPos(in.skipToken()) {
        if (in.token == THIS) {
          in.nextToken()
          val vparamss = paramClauses(nme.CONSTRUCTOR, implicitClassViews map (.duplicate), false)
          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 name = ident()
          val implicitViewBuf = new ListBuffer[Tree]
          val tparams = typeParamClauseOpt(name, implicitViewBuf)
          val vparamss = paramClauses(name, implicitViewBuf.toList, false)
          var restype = typedOpt()
          val rhs =
            if (in.token == SEMI || in.token == NEWLINE || in.token == RBRACE) {
              if (restype.isEmpty) restype = scalaUnitConstr
              newmods = 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 selfInvocation(vparamss)

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

    /** ConstrBlock    ::=  `{' SelfInvocation {StatementSeparator BlockStat} `}'
     */
    def constrBlock(vparamss: List[List[ValDef]]): Tree =
      atPos(in.skipToken()) {
        val statlist = new ListBuffer[Tree]
        statlist += selfInvocation(vparamss)
        val stats =
          if (in.token == SEMI || in.token == NEWLINE) {
            in.nextToken(); blockStatSeq(statlist)
          } else statlist.toList
        accept(RBRACE)
        makeBlock(stats)
      }

    /** TypeDef ::= Id [TypeParamClause] `=' Type
     *  TypeDcl ::= Id TypeBounds
     */
    def typeDefOrDcl(mods: Modifiers): Tree =
      atPos(in.currentPos) {
        val name = ident().toTypeName
        in.token match {
          case LBRACKET =>
            val tparams = typeParamClauseOpt(name, null)
            accept(EQUALS)
            AliasTypeDef(mods, name, tparams, typ())
          case EQUALS =>
            in.nextToken()
            AliasTypeDef(mods, name, List(), typ())
          case SUPERTYPE | SUBTYPE | SEMI | NEWLINE | COMMA | RBRACE =>
            typeBounds(mods | Flags.DEFERRED, name)
          case _ =>
            syntaxErrorOrIncomplete("`=', `>:', or `<:' expected", true)
            EmptyTree
        }
      }

    /**  TmplDef ::= [case] class ClassDef
     *            |  [case] object ObjectDef
     *            |  trait TraitDef
     */
    def tmplDef(mods: Modifiers): Tree = 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]
                     [AccessModifier] ClassParamClauses RequiresTypeOpt ClassTemplate
     *  TraitDef ::= Id [TypeParamClause] RequiresTypeOpt MixinClassTemplate
     */
    def classDef(mods: Modifiers): ClassDef =
      atPos(in.skipToken()) {
        val name = ident().toTypeName
        val savedViews = implicitClassViews
        val implicitViewBuf = new ListBuffer[Tree]
        val tparams = typeParamClauseOpt(name, implicitViewBuf)
        implicitClassViews = implicitViewBuf.toList
        //if (mods.hasFlag(Flags.CASE) && in.token != LPAREN) accept(LPAREN)
        val {constrMods, vparamss} =
          if (mods.hasFlag(Flags.TRAIT)) {NoMods, List()}
          else {accessModifierOpt(),
                paramClauses(name, implicitClassViews, mods.hasFlag(Flags.CASE))}
        val thistpe = requiresTypeOpt()
        val template = classTemplate(mods, name, constrMods, vparamss)
        val mods1 = if (mods.hasFlag(Flags.TRAIT) &&
                        (template.body forall treeInfo.isInterfaceMember))
                      mods | Flags.INTERFACE
                    else mods
        val result = ClassDef(mods1, name, tparams, thistpe, template)
        implicitClassViews = savedViews
        result
      }

    /** ObjectDef       ::= Id ClassTemplate
     */
    def objectDef(mods: Modifiers): ModuleDef =
      atPos(in.skipToken()) {
        val name = ident()
        val template = classTemplate(mods, name, NoMods, List())
        ModuleDef(mods, name, template)
      }

    /** ClassTemplate      ::= [`extends' TemplateParents] [[NewLine] TemplateBody]
     *  TemplateParents    ::= SimpleType {`(' [Exprs] `)'} {`with' SimpleType}
     *  MixinClassTemplate ::= [`extends' MixinParents] [[NewLine] TemplateBody]
     *  MixinParents       ::= SimpleType {`with' SimpleType}
     */
    def classTemplate(mods: Modifiers, name: Name, constrMods: Modifiers, vparamss: List[List[ValDef]]): Template =
      atPos(in.currentPos) {
        def acceptEmptyTemplateBody(msg: String): unit = {
          if (in.token == LPAREN && settings.migrate.value)
            syntaxErrorMigrate("traites may not have parameters")
          if (!(in.token == SEMI || in.token == NEWLINE ||
                in.token == COMMA || in.token == RBRACE || in.token == EOF))
            syntaxError(msg, true)
        }
        val parents = new ListBuffer[Tree]
        val argss = new ListBuffer[List[Tree]]
        if (in.token == EXTENDS) {
          in.nextToken()
          val parent = simpleType(false)
          // System.err.println("classTempl: " + parent)
          parents += parent
          if (in.token == LPAREN && !mods.hasFlag(Flags.TRAIT))
            do { argss += argumentExprs() } while (in.token == LPAREN)
          else argss += List()
          while (in.token == WITH) {
            in.nextToken()
            parents += simpleType(false)
          }
        } else {
          if (in.token == WITH && settings.migrate.value)
            syntaxErrorMigrate("`extends' needed before `with'")
          if (in.token != LBRACE) acceptEmptyTemplateBody("`extends' or `{' expected")
          argss += List()
        }
        if (name != nme.ScalaObject.toTypeName)
          parents += scalaScalaObjectConstr
        if (mods.hasFlag(Flags.CASE)) {
          parents += productConstr
        }
        val ps = parents.toList
        newLineOptWhenFollowedBy(LBRACE)
        var body =
          if (in.token == LBRACE) templateBody()
          else { acceptEmptyTemplateBody("`{' expected"); List() }
        if (!mods.hasFlag(Flags.TRAIT)) Template(ps, constrMods, vparamss, argss.toList, body)
        else Template(ps, body)
      }

////////// TEMPLATES ////////////////////////////////////////////////////////////

    /** TemplateBody ::= `{' [TemplateStat {StatementSeparator TemplateStat}] `}'
     */
    def templateBody(): List[Tree] = {
      accept(LBRACE)
      var body = templateStatSeq()
      if (body.isEmpty) body = List(EmptyTree)
      accept(RBRACE)
      body
    }

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

/////// STATSEQS //////////////////////////////////////////////////////////////

    /** Packaging ::= package QualId `{' TopStatSeq `}'
     */
    def packaging(): Tree = {
      atPos(accept(PACKAGE)) {
        val pkg = qualId()
        accept(LBRACE)
        val stats = topStatSeq()
        accept(RBRACE)
        makePackaging(pkg, stats)
      }
    }

    /** TopStatSeq ::= [TopStat {StatementSeparator TopStat}]
     *  TopStat ::= AttributeClauses Modifiers TmplDef
     *            | Packaging
     *            | Import
     *            |
     */
    def topStatSeq(): List[Tree] = {
      val stats = new ListBuffer[Tree]
      while (in.token != RBRACE && in.token != EOF) {
        if (in.token == PACKAGE) {
          stats += packaging()
        } else if (in.token == IMPORT) {
          stats ++= importClause()
        } else if (in.token == CLASS ||
                   in.token == CASECLASS ||
                   in.token == TRAIT ||
                   in.token == OBJECT ||
                   in.token == CASEOBJECT ||
                   in.token == LBRACKET ||
                   isModifier) {
          val attrs = attributeClauses()
          stats ++ joinComment(List(tmplDef(modifiers() withAttributes attrs)))
        } else if (in.token != SEMI && in.token != NEWLINE) {
          syntaxErrorOrIncomplete("expected class or object definition", true)
        }
        if (in.token != RBRACE && in.token != EOF) acceptStatSep()
      }
      stats.toList
    }

    /** TemplateStatSeq  ::= TemplateStat {StatementSeparator TemplateStat}
     *  TemplateStat     ::= Import
     *                     | AttributeClauses Modifiers Def
     *                     | AttributeClauses Modifiers Dcl
     *                     | Expr
     *                     |
     */
    def templateStatSeq(): List[Tree] = {
      val stats = new ListBuffer[Tree]
      while (in.token != RBRACE && in.token != EOF) {
        if (in.token == IMPORT) {
          stats ++= importClause()
        } else if (isExprIntro) {
          stats += expr()
        } else if (isDefIntro || isModifier || in.token == LBRACKET) {
          val attrs = attributeClauses()
          stats ++ joinComment(defOrDcl(modifiers() withAttributes attrs))
        } else if (in.token != SEMI && in.token != NEWLINE) {
          syntaxErrorOrIncomplete("illegal start of definition", true)
        }
        if (in.token != RBRACE && in.token != EOF) acceptStatSep()
      }
      stats.toList
    }

    /** AttributeClauses   ::= {AttributeClause}
     *  AttributeClause    ::= `[' Attribute {`,' Attribute} `]' [NewLine]
     */
    def attributeClauses(): List[Attribute] = {
      var attrs = new ListBuffer[Attribute]
      while (in.token == LBRACKET) {
        in.nextToken()
        attrs += attribute()
        while (in.token == COMMA) {
          in.nextToken()
          attrs += attribute()
        }
        accept(RBRACKET)
        newLineOpt()
      }
      attrs.toList
    }

    /** Attribute          ::= StableId [TypeArgs] [`(' [Exprs] `)'] [`{' {NameValuePair} `}']
     */
    def attribute(): Attribute = {
      def nameValuePair(): Tree = {
        accept(VAL)
        var pos = in.currentPos
        val aname = atPos(pos) { Ident(ident()) }
        accept(EQUALS)
        atPos(pos) { Assign(aname, liftingScope(prefixExpr())) }
      }
      val pos = in.currentPos
      var t: Tree = convertToTypeId(stableId())
      if (in.token == LBRACKET)
        t = atPos(in.currentPos)(AppliedTypeTree(t, typeArgs(false)))
      val args = if (in.token == LPAREN) argumentExprs() else List()
      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 = atPos(pos) { New(t, List(args)) }
      glob.Attribute(constr, nameValuePairs) setPos pos
    }

    /** TypeAttributes     ::= (`[' Exprs `]') *
     *
     * Type attributes may be arbitrary expressions.
     */
    def typeAttributes(): List[Tree] = {
      val exps = new ListBuffer[Tree]
      if (settings.Xplugtypes.value) {
        while(in.token == LBRACKET) {
          accept(LBRACKET)
          exps ++= argExprs
          accept(RBRACKET)
        }
      } else {
        while (in.token == AT) {
          val pos = in.skipToken()
          exps += attribute()
        }
      }
      exps.toList
    }

    /** RefineStatSeq    ::= RefineStat {StatementSeparator RefineStat}
     *  RefineStat       ::= Dcl
     *                     | type TypeDef
     *                     |
     */
    def refineStatSeq(): List[Tree] = {
      val stats = new ListBuffer[Tree]
      while (in.token != RBRACE && in.token != EOF) {
        if (isDclIntro) {
          stats ++= joinComment(defOrDcl(NoMods))
        } else if (in.token != SEMI && in.token != NEWLINE) {
          syntaxErrorOrIncomplete("illegal start of declaration", true)
        }
        if (in.token != RBRACE) acceptStatSep()
      }
      stats.toList
    }

    /** BlockStatSeq ::= { BlockStat StatementSeparator } [ResultExpr]
     *  BlockStat    ::= Import
     *                 | [implicit] Def
     *                 | LocalModifiers TmplDef
     *                 | Expr1
     *                 |
     *  Tuple        ::= [Expr1 `,' {Expr1 `,'} [Expr1]]
     */
    def blockStatSeq(stats: ListBuffer[Tree]): List[Tree] =
      blockStatSeqOrTuple(false, stats)
    def blockStatSeqOrTuple(tupleOK: boolean, stats: ListBuffer[Tree]): List[Tree] = {
      def localDef(mods: Modifiers) = {
        if (!(mods hasFlag ~Flags.IMPLICIT)) stats ++= defOrDcl(mods)
        else stats += tmplDef(mods)
        if (in.token == RBRACE || in.token == CASE)
          syntaxError("block must end in result expression, not in definition", false)
        else
          acceptStatSep()
        if (in.token == RBRACE || in.token == CASE)
          stats += Literal(()).setPos(in.currentPos)
      }
      var last = false
      while ((in.token != RBRACE) && (in.token != EOF) && (in.token != CASE) && !last) {
        if (in.token == IMPORT) {
          stats ++= importClause()
          acceptStatSep()
        } else if (isExprIntro) {
          val expr = blockStatExpr()
          if (in.token == COMMA) {
            val exprbuf = new ListBuffer[Tree] + expr
            while (in.token == COMMA) {
              in.nextToken()
              if (in.token != RBRACE) exprbuf += expr1()
            }
            val exprs = exprbuf.toList
            if (in.token == ARROW) {
              val vdefs = exprs flatMap convertToParams
              checkSize("function arguments", vdefs.length, definitions.MaxFunctionArity)
              stats += atPos(in.skipToken()) { Function(vdefs, block()) }
            } else {
              checkSize("tuple elements:", exprs.length, definitions.MaxTupleArity)
              stats += makeTupleTerm(exprs, false)
            }
          } else stats += expr
          if (in.token != RBRACE && in.token != CASE) acceptStatSep()
        } else if (isDefIntro) {
          localDef(NoMods)
        } else if (isLocalModifier) {
          localDef(localModifiers())
        } else if (in.token == SEMI || in.token == NEWLINE) {
          in.nextToken()
        } else {
          syntaxErrorOrIncomplete("illegal start of statement", true)
        }
      }
      stats.toList
    }

    /** CompilationUnit ::= package QualId StatementSeparator TopStatSeq
     *                    | package QualId `{' TopStatSeq `}'
     *                    | TopStatSeq
     */
    def compilationUnit(): Tree =
      atPos(in.currentPos) {
        val ts = new ListBuffer[Tree]
        if (in.token == PACKAGE) {
          in.nextToken()
          val pkg = qualId()
          if (in.token == SEMI || in.token == NEWLINE || in.token == EOF) {
            in.nextToken()
            ts += makePackaging(pkg, topStatSeq())
          } else {
            accept(LBRACE)
            ts += makePackaging(pkg, topStatSeq())
            accept(RBRACE)
            ts ++= topStatSeq()
          }
        } else {
          ts ++= topStatSeq()
        }
        val stats = ts.toList
        stats match {
          case List(stat @ PackageDef(_, _)) => stat
          case _ => makePackaging(Ident(nme.EMPTY_PACKAGE_NAME), stats)
        }
      }
  }
}