alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Scala example source code file (JavaParsers.scala)

This example Scala source code file (JavaParsers.scala) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Scala tags/keywords

classdef, comma, int, int, list, list, listbuffer, modifiers, name, semi, string, string, tree, tree

The Scala JavaParsers.scala source code

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


package scala.tools.nsc
package javac

import scala.tools.nsc.util.OffsetPosition
import scala.collection.mutable.ListBuffer
import symtab.Flags
import JavaTokens._

trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners {
  val global : Global 
  import global._
  import definitions._

  case class JavaOpInfo(operand: Tree, operator: Name, pos: Int)

  class JavaUnitParser(val unit: global.CompilationUnit) extends JavaParser {
    val in = new JavaUnitScanner(unit)
    def freshName(prefix: String): Name = freshTermName(prefix)
    def freshTermName(prefix: String): TermName = unit.freshTermName(prefix)
    def freshTypeName(prefix: String): TypeName = unit.freshTypeName(prefix)
    def deprecationWarning(off: Int, msg: String) = unit.deprecationWarning(off, msg)
    implicit def i2p(offset : Int) : Position = new OffsetPosition(unit.source, offset)
    def warning(pos : Int, msg : String) : Unit = unit.warning(pos, msg)
    def syntaxError(pos: Int, msg: String) : Unit = unit.error(pos, msg)
  }

  abstract class JavaParser extends ParserCommon {
    val in: JavaScanner

    protected def posToReport: Int = in.currentPos
    def freshName(prefix : String): Name
    protected implicit def i2p(offset : Int) : Position
    private implicit def p2i(pos : Position): Int = if (pos.isDefined) pos.point else -1

    /** The simple name of the package of the currently parsed file */
    private var thisPackageName: TypeName = tpnme.EMPTY
    
    /** this is the general parse method
     */
    def parse(): Tree = {
      val t = compilationUnit()
      accept(EOF)
      t
    }

    // -------- error handling ---------------------------------------

    private var lastErrorPos : Int = -1

    protected def skip() {
      var nparens = 0
      var nbraces = 0
      while (true) {
        in.token match {
          case EOF =>
            return
          case SEMI =>
            if (nparens == 0 && nbraces == 0) return
          case RPAREN =>
            nparens -= 1
          case RBRACE =>
            if (nbraces == 0) return
            nbraces -= 1
          case LPAREN =>
            nparens += 1
          case LBRACE =>
            nbraces += 1
          case _ =>
        }
        in.nextToken
      }
    }

    def warning(pos : Int, msg : String) : Unit
    def syntaxError(pos: Int, msg: String) : Unit
    def syntaxError(msg: String, skipIt: Boolean) {
      syntaxError(in.currentPos, msg, skipIt)
    }
    
    def syntaxError(pos: Int, msg: String, skipIt: Boolean) {
      if (pos > lastErrorPos) {
        syntaxError(pos, msg)
        // no more errors on this token.
        lastErrorPos = in.currentPos
      }
      if (skipIt) 
        skip()
    }
    def warning(msg: String) : Unit = warning(in.currentPos, msg)
        
    def errorTypeTree = TypeTree().setType(ErrorType) setPos in.currentPos
    def errorTermTree = Literal(Constant(null)) setPos in.currentPos
    def errorPatternTree = blankExpr setPos in.currentPos

    // --------- tree building -----------------------------

    import gen.{ rootId, scalaDot }

    def javaDot(name: Name): Tree = 
      Select(rootId(nme.java), name)

    def javaLangDot(name: Name): Tree =
      Select(javaDot(nme.lang), name)

    def javaLangObject(): Tree = javaLangDot(tpnme.Object)

    def arrayOf(tpt: Tree) = 
      AppliedTypeTree(scalaDot(tpnme.Array), List(tpt))

    def blankExpr = Ident(nme.WILDCARD)

    def makePackaging(pkg: RefTree, stats: List[Tree]): PackageDef = 
      atPos(pkg.pos) {  PackageDef(pkg, stats) }

    def makeTemplate(parents: List[Tree], stats: List[Tree]) =
      Template(
        parents, 
        emptyValDef,
        if (treeInfo.firstConstructor(stats) == EmptyTree) makeConstructor(List()) :: stats
        else stats)

    def makeParam(name: String, tpt: Tree) =
      ValDef(Modifiers(Flags.JAVA | Flags.PARAM), newTermName(name), tpt, EmptyTree)

    def makeConstructor(formals: List[Tree]) = {
      val vparams = formals.zipWithIndex map { case (p, i) => makeParam("x$" + (i + 1), p) }
      DefDef(Modifiers(Flags.JAVA), nme.CONSTRUCTOR, List(), List(vparams), TypeTree(), blankExpr)
    }
    
    // ------------- general parsing ---------------------------

    /** skip parent or brace enclosed sequence of things */
    def skipAhead() {
      var nparens = 0
      var nbraces = 0
      do {
        in.token match {
          case LPAREN =>
            nparens += 1
          case LBRACE =>
            nbraces += 1
          case _ =>
        }
        in.nextToken
        in.token match {
          case RPAREN =>
            nparens -= 1
          case RBRACE =>
            nbraces -= 1
          case _ =>
        }
      } while (in.token != EOF && (nparens > 0 || nbraces > 0))
    }

    def skipTo(tokens: Int*) {
      while (!(tokens contains in.token) && in.token != EOF) {
        if (in.token == LBRACE) { skipAhead(); accept(RBRACE) }
        else if (in.token == LPAREN) { skipAhead(); accept(RPAREN) }
        else in.nextToken
      }
    }

    /** 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 (in.currentPos.line(unit.source).get(0) > in.lastPos.line(unit.source).get(0))
          //  in.lastPos
          //else
            in.currentPos
        val msg =
          JavaScannerConfiguration.token2string(token) + " expected but " +
            JavaScannerConfiguration.token2string(in.token) + " found."

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

    def acceptClosingAngle() {
      val closers: PartialFunction[Int, Int] = {
        case GTGTGTEQ => GTGTEQ
        case GTGTGT   => GTGT
        case GTGTEQ   => GTEQ
        case GTGT     => GT
        case GTEQ     => ASSIGN
      }
      if (closers isDefinedAt in.token) in.token = closers(in.token)
      else accept(GT)
    }

    def identForType(): TypeName = ident().toTypeName
    def ident(): Name =
      if (in.token == IDENTIFIER) {
        val name = in.name
        in.nextToken
        name
      } else {
        accept(IDENTIFIER)
        nme.ERROR
      }

    def repsep[T <: Tree](p: () => T, sep: Int): List[T] = {
      val buf = ListBuffer[T](p())
      while (in.token == sep) {
        in.nextToken
        buf += p()
      }
      buf.toList
    }

    /** Convert (qual)ident to type identifier
     */
    def convertToTypeId(tree: Tree): Tree = gen.convertToTypeName(tree) match {
      case Some(t)  => t setPos tree.pos
      case _        => tree match {
        case AppliedTypeTree(_, _) | ExistentialTypeTree(_, _) | SelectFromTypeTree(_, _) =>
          tree
        case _ =>
          syntaxError(tree.pos, "identifier expected", false)
          errorTypeTree
      }
    }

    // -------------------- specific parsing routines ------------------

    def qualId(): RefTree = {
      var t: RefTree = atPos(in.currentPos) { Ident(ident()) }
      while (in.token == DOT) { 
        in.nextToken
        t = atPos(in.currentPos) { Select(t, ident()) }
      }
      t
    }

    def optArrayBrackets(tpt: Tree): Tree = 
      if (in.token == LBRACKET) {
        val tpt1 = atPos(in.pos) { arrayOf(tpt) }
        in.nextToken
        accept(RBRACKET)
        optArrayBrackets(tpt1)
      } else tpt

    def basicType(): Tree = 
      atPos(in.pos) {
        in.token match {
          case BYTE => in.nextToken; TypeTree(ByteClass.tpe)
          case SHORT => in.nextToken; TypeTree(ShortClass.tpe)
          case CHAR => in.nextToken; TypeTree(CharClass.tpe)
          case INT => in.nextToken; TypeTree(IntClass.tpe)
          case LONG => in.nextToken; TypeTree(LongClass.tpe)
          case FLOAT => in.nextToken; TypeTree(FloatClass.tpe)
          case DOUBLE => in.nextToken; TypeTree(DoubleClass.tpe)
          case BOOLEAN => in.nextToken; TypeTree(BooleanClass.tpe)
          case _ => syntaxError("illegal start of type", true); errorTypeTree
        }
      }

    def typ(): Tree =
      optArrayBrackets {
        if (in.token == FINAL) in.nextToken
        if (in.token == IDENTIFIER) {
          var t = typeArgs(atPos(in.currentPos)(Ident(ident())))
          // typeSelect generates Select nodes is the lhs is an Ident or Select,
          // SelectFromTypeTree otherwise. See #3567.
          // Select nodes can be later
          // converted in the typechecker to SelectFromTypeTree if the class
          // turns out to be an instance ionner class instead of a static inner class.
          def typeSelect(t: Tree, name: Name) = t match {
            case Ident(_) | Select(_, _) => Select(t, name)
            case _ => SelectFromTypeTree(t, name.toTypeName)
          }
          while (in.token == DOT) {
            in.nextToken
            t = typeArgs(atPos(in.currentPos)(typeSelect(t, ident())))
          }
          convertToTypeId(t)
        } else {
          basicType()
        }
      }

    def typeArgs(t: Tree): Tree = {
      val wildcards = new ListBuffer[TypeDef]
      def typeArg(): Tree = 
        if (in.token == QMARK) {
          val pos = in.currentPos
          in.nextToken
          var lo: Tree = TypeTree(NothingClass.tpe)
          var hi: Tree = TypeTree(AnyClass.tpe)
          if (in.token == EXTENDS) {
            in.nextToken
            hi = typ()
          } else if (in.token == SUPER) {
            in.nextToken
            lo = typ()
          }
          val tdef = atPos(pos) {
            TypeDef(
              Modifiers(Flags.JAVA | Flags.DEFERRED), 
              newTypeName("_$"+ (wildcards.length + 1)),
              List(), 
              TypeBoundsTree(lo, hi))
          }
          wildcards += tdef
          atPos(pos) { Ident(tdef.name) }
        } else {
          typ()
        }
      if (in.token == LT) {
        in.nextToken
        val t1 = convertToTypeId(t)
        val args = repsep(typeArg, COMMA)
        acceptClosingAngle()
        atPos(t1.pos) {
          val t2: Tree = AppliedTypeTree(t1, args)
          if (wildcards.isEmpty) t2
          else ExistentialTypeTree(t2, wildcards.toList)
        }
      } else t
    }

    def annotations(): List[Tree] = {
      //var annots = new ListBuffer[Tree]
      while (in.token == AT) {
        in.nextToken
        annotation()
      }
      List() // don't pass on annotations for now
    }

    /** Annotation ::= TypeName [`(' AnnotationArgument {`,' AnnotationArgument} `)']
     */
    def annotation() {
      val pos = in.currentPos
      var t = qualId()
      if (in.token == LPAREN) { skipAhead(); accept(RPAREN) }
      else if (in.token == LBRACE) { skipAhead(); accept(RBRACE) }
    }
/*
    def annotationArg() = {
      val pos = in.token
      if (in.token == IDENTIFIER && in.lookaheadToken == ASSIGN) {
        val name = ident()
        accept(ASSIGN)
        atPos(pos) {
          ValDef(Modifiers(Flags.JAVA), name, TypeTree(), elementValue())
        }
      } else {
        elementValue()
      }
    }

    def elementValue(): Tree =
      if (in.token == AT) annotation()
      else if (in.token == LBRACE) elementValueArrayInitializer()
      else expression1()

    def elementValueArrayInitializer() = {
      accept(LBRACE)
      val buf = new ListBuffer[Tree]
      def loop() =
        if (in.token != RBRACE) {
          buf += elementValue()
          if (in.token == COMMA) {
            in.nextToken
            loop()
          }
        }
      loop()
      accept(RBRACE)
      buf.toList
    }
 */

    def modifiers(inInterface: Boolean): Modifiers = {
      var flags: Long = Flags.JAVA
      // assumed true unless we see public/private/protected
      var isPackageAccess = true
      var annots: List[Tree] = Nil
      def addAnnot(sym: Symbol) =
        annots :+= New(TypeTree(sym.tpe), List(Nil))

      while (true) {
        in.token match {
          case AT if (in.lookaheadToken != INTERFACE) => 
            in.nextToken
            annotation()
          case PUBLIC => 
            isPackageAccess = false
            in.nextToken
          case PROTECTED => 
            flags |= Flags.PROTECTED
            in.nextToken
          case PRIVATE =>
            isPackageAccess = false
            flags |= Flags.PRIVATE
            in.nextToken
          case STATIC =>  
            flags |= Flags.STATIC
            in.nextToken
          case ABSTRACT =>
            flags |= Flags.ABSTRACT
            in.nextToken
          case FINAL =>
            flags |= Flags.FINAL
            in.nextToken
          case NATIVE =>
            addAnnot(NativeAttr)
            in.nextToken
          case TRANSIENT =>
            addAnnot(TransientAttr)
            in.nextToken
          case VOLATILE =>
            addAnnot(VolatileAttr)
            in.nextToken
          case SYNCHRONIZED | STRICTFP =>
            in.nextToken
          case _ =>
            val privateWithin: TypeName =
              if (isPackageAccess && !inInterface) thisPackageName
              else tpnme.EMPTY
            
            return Modifiers(flags, privateWithin) withAnnotations annots
        }
      }
      abort("should not be here")
    }

    def typeParams(): List[TypeDef] =
      if (in.token == LT) {
        in.nextToken
        val tparams = repsep(typeParam, COMMA)
        acceptClosingAngle()
        tparams
      } else List()

    def typeParam(): TypeDef = 
      atPos(in.currentPos) {
        val name = identForType()
        val hi = 
          if (in.token == EXTENDS) {
            in.nextToken
            bound()
          } else {
            scalaDot(tpnme.Any)
          }
        TypeDef(Modifiers(Flags.JAVA | Flags.DEFERRED | Flags.PARAM), name, List(), 
                TypeBoundsTree(scalaDot(tpnme.Nothing), hi))
      }

    def bound(): Tree = 
      atPos(in.currentPos) {
        val buf = ListBuffer[Tree](typ())
        while (in.token == AMP) {
          in.nextToken
          buf += typ()
        }
        val ts = buf.toList
        if (ts.tail.isEmpty) ts.head
        else CompoundTypeTree(Template(ts, emptyValDef, List()))
      }
        
    def formalParams(): List[ValDef] = {
      accept(LPAREN)
      val vparams = if (in.token == RPAREN) List() else repsep(formalParam, COMMA)
      accept(RPAREN)
      vparams
    }

    def formalParam(): ValDef = {
      if (in.token == FINAL) in.nextToken
      annotations()
      var t = typ()
      if (in.token == DOTDOTDOT) {
        in.nextToken
        t = atPos(t.pos) {
          AppliedTypeTree(scalaDot(tpnme.JAVA_REPEATED_PARAM_CLASS_NAME), List(t))
        }
      }
     varDecl(in.currentPos, Modifiers(Flags.JAVA | Flags.PARAM), t, ident())
    }

    def optThrows() {
      if (in.token == THROWS) {
        in.nextToken
        repsep(typ, COMMA)
      }
    }

    def methodBody(): Tree = {
      skipAhead()
      accept(RBRACE) // skip block
      blankExpr
    } 

    def definesInterface(token: Int) = token == INTERFACE || token == AT

    def termDecl(mods: Modifiers, parentToken: Int): List[Tree] = {
      val inInterface = definesInterface(parentToken)
      val tparams = if (in.token == LT) typeParams() else List()
      val isVoid = in.token == VOID
      var rtpt =
        if (isVoid) {
          in.nextToken
          TypeTree(UnitClass.tpe) setPos in.pos
        } else typ()
      var pos = in.currentPos
      val rtptName = rtpt match {
        case Ident(name) => name
        case _ => nme.EMPTY
      }
      if (in.token == LPAREN && rtptName != nme.EMPTY && !inInterface) { 
        // constructor declaration
        val vparams = formalParams()
        optThrows()
        List {
          atPos(pos) {
            DefDef(mods, nme.CONSTRUCTOR, tparams, List(vparams), TypeTree(), methodBody())
          }
        }
      } else {        
        var mods1 = mods
        if (mods hasFlag Flags.ABSTRACT) mods1 = mods &~ Flags.ABSTRACT | Flags.DEFERRED
        pos = in.currentPos
        val name = ident()
        if (in.token == LPAREN) {
          // method declaration
          val vparams = formalParams()
          if (!isVoid) rtpt = optArrayBrackets(rtpt)
          optThrows()
          val body = 
            if (!inInterface && in.token == LBRACE) {
              methodBody()
            } else {
              if (parentToken == AT && in.token == DEFAULT) {
                val annot = 
                  atPos(pos) {
                    New(Select(scalaDot(newTermName("runtime")), tpnme.AnnotationDefaultATTR), List(List()))
                  }
                mods1 = Modifiers(mods1.flags, mods1.privateWithin, annot :: mods1.annotations, mods1.positions)
                skipTo(SEMI)
                accept(SEMI)
                blankExpr
              } else {
                accept(SEMI)
                EmptyTree 
              }
            }
          if (inInterface) mods1 |= Flags.DEFERRED
          List {
            atPos(pos) {
              DefDef(mods1, name, tparams, List(vparams), rtpt, body)
            }
          }
        } else {
          if (inInterface) mods1 |= Flags.FINAL | Flags.STATIC
          val result = fieldDecls(pos, mods1, rtpt, name)
          accept(SEMI)
          result
        }
      }
    }
    
    /** Parse a sequence of field declarations, separated by commas.
     *  This one is tricky because a comma might also appear in an
     *  initializer. Since we don't parse initializers we don't know
     *  what the comma signifies.
     *  We solve this with a second list buffer `maybe' which contains
     *  potential variable definitions. 
     *  Once we have reached the end of the statement, we know whether
     *  these potential definitions are real or not.
     */
    def fieldDecls(pos: Position, mods: Modifiers, tpt: Tree, name: Name): List[Tree] = {
      val buf = ListBuffer[Tree](varDecl(pos, mods, tpt, name))
      val maybe = new ListBuffer[Tree] // potential variable definitions.
      while (in.token == COMMA) {
        in.nextToken
        if (in.token == IDENTIFIER) { // if there's an ident after the comma ...
          val name = ident()
          if (in.token == ASSIGN || in.token == SEMI) { // ... followed by a `=' or `;', we know it's a real variable definition
            buf ++= maybe 
            buf += varDecl(in.currentPos, mods, tpt.duplicate, name)
            maybe.clear()
          } else if (in.token == COMMA) { // ... if there's a comma after the ident, it could be a real vardef or not.
            maybe += varDecl(in.currentPos, mods, tpt.duplicate, name)
          } else { // ... if there's something else we were still in the initializer of the
                   // previous var def; skip to next comma or semicolon.
            skipTo(COMMA, SEMI)
            maybe.clear()
          }
        } else { // ... if there's no ident following the comma we were still in the initializer of the
                 // previous var def; skip to next comma or semicolon.
          skipTo(COMMA, SEMI)
          maybe.clear()
        }
      }
      if (in.token == SEMI) {
        buf ++= maybe // every potential vardef that survived until here is real. 
      }
      buf.toList
    }

    def varDecl(pos: Position, mods: Modifiers, tpt: Tree, name: TermName): ValDef = {
      val tpt1 = optArrayBrackets(tpt)
      if (in.token == ASSIGN && !mods.isParameter) skipTo(COMMA, SEMI)
      val mods1 = if (mods.isFinal) mods &~ Flags.FINAL else mods | Flags.MUTABLE
      atPos(pos) {
        ValDef(mods1, name, tpt1, blankExpr)
      }
    }

    def memberDecl(mods: Modifiers, parentToken: Int): List[Tree] = in.token match {
      case CLASS | ENUM | INTERFACE | AT => 
        typeDecl(if (definesInterface(parentToken)) mods | Flags.STATIC else mods)
      case _ => 
        termDecl(mods, parentToken)
    }

    def makeCompanionObject(cdef: ClassDef, statics: List[Tree]): Tree = 
      atPos(cdef.pos) {
        ModuleDef(cdef.mods & (Flags.AccessFlags | Flags.JAVA), cdef.name.toTermName,
                  makeTemplate(List(), statics))
      }

    def importCompanionObject(cdef: ClassDef): Tree =
      atPos(cdef.pos) {
        Import(Ident(cdef.name.toTermName), List(ImportSelector(nme.WILDCARD, -1, null, -1)))
      }

    // Importing the companion object members cannot be done uncritically: see
    // ticket #2377 wherein a class contains two static inner classes, each of which
    // has a static inner class called "Builder" - this results in an ambiguity error
    // when each performs the import in the enclosing class's scope.
    //
    // To address this I moved the import Companion._ inside the class, as the first
    // statement.  This should work without compromising the enclosing scope, but may (?)
    // end up suffering from the same issues it does in scala - specifically that this
    // leaves auxiliary constructors unable to access members of the companion object
    // as unqualified identifiers.
    def addCompanionObject(statics: List[Tree], cdef: ClassDef): List[Tree] = {      
      def implWithImport(importStmt: Tree) = {
        import cdef.impl._
        treeCopy.Template(cdef.impl, parents, self, importStmt :: body)
      }
      // if there are no statics we can use the original cdef, but we always
      // create the companion so import A._ is not an error (see ticket #1700)
      val cdefNew =
        if (statics.isEmpty) cdef
        else treeCopy.ClassDef(cdef, cdef.mods, cdef.name, cdef.tparams, implWithImport(importCompanionObject(cdef)))
      
      List(makeCompanionObject(cdefNew, statics), cdefNew)
    }

    def importDecl(): List[Tree] = {
      accept(IMPORT)
      val pos = in.currentPos
      val buf = new ListBuffer[Name]
      def collectIdents() : Int = {
        if (in.token == ASTERISK) {
          val starOffset = in.pos
          in.nextToken
          buf += nme.WILDCARD
          starOffset
        } else {
          val nameOffset = in.pos
          buf += ident()
          if (in.token == DOT) {
            in.nextToken
            collectIdents()
          } else nameOffset
        }
      }
      if (in.token == STATIC) in.nextToken
      else buf += nme.ROOTPKG
      val lastnameOffset = collectIdents()
      accept(SEMI)
      val names = buf.toList
      if (names.length < 2) {
        syntaxError(pos, "illegal import", false)
        List()
      } else {
        val qual = ((Ident(names.head): Tree) /: names.tail.init) (Select(_, _))
        val lastname = names.last
        val selector = lastname match {
          case nme.WILDCARD => ImportSelector(lastname, lastnameOffset, null, -1)
          case _            => ImportSelector(lastname, lastnameOffset, lastname, lastnameOffset)
        }
        List(atPos(pos)(Import(qual, List(selector))))
      }
    }

    def interfacesOpt() =
      if (in.token == IMPLEMENTS) {
        in.nextToken
        repsep(typ, COMMA)
      } else {
        List()
      }

    def classDecl(mods: Modifiers): List[Tree] = {
      accept(CLASS)
      val pos = in.currentPos
      val name = identForType()
      val tparams = typeParams()
      val superclass = 
        if (in.token == EXTENDS) {
          in.nextToken
          typ()
        } else {
          javaLangObject()
        }
      val interfaces = interfacesOpt()
      val (statics, body) = typeBody(CLASS, name) 
      addCompanionObject(statics, atPos(pos) {
        ClassDef(mods, name, tparams, makeTemplate(superclass :: interfaces, body))
      })
    }

    def interfaceDecl(mods: Modifiers): List[Tree] = {
      accept(INTERFACE)
      val pos = in.currentPos
      val name = identForType()
      val tparams = typeParams()
      val parents = 
        if (in.token == EXTENDS) {
          in.nextToken
          repsep(typ, COMMA)
        } else {
          List(javaLangObject)
        }
      val (statics, body) = typeBody(INTERFACE, name)
      addCompanionObject(statics, atPos(pos) {
        ClassDef(mods | Flags.TRAIT | Flags.INTERFACE | Flags.ABSTRACT, 
                 name, tparams, 
                 makeTemplate(parents, body))
      })
    }

    def typeBody(leadingToken: Int, parentName: Name): (List[Tree], List[Tree]) = {
      accept(LBRACE)
      val defs = typeBodyDecls(leadingToken, parentName)
      accept(RBRACE)
      defs
    }
 
    def typeBodyDecls(parentToken: Int, parentName: Name): (List[Tree], List[Tree]) = {
      val inInterface = definesInterface(parentToken)
      val statics = new ListBuffer[Tree]
      val members = new ListBuffer[Tree]
      while (in.token != RBRACE && in.token != EOF) {
        var mods = modifiers(inInterface)
        if (in.token == LBRACE) {
          skipAhead() // skip init block, we just assume we have seen only static
          accept(RBRACE)
        } else if (in.token == SEMI) {
          in.nextToken
        } else {
          if (in.token == ENUM || definesInterface(in.token)) mods |= Flags.STATIC
          val decls = memberDecl(mods, parentToken)
          (if (mods.hasStaticFlag || inInterface && !(decls exists (_.isInstanceOf[DefDef])))
             statics 
           else 
             members) ++= decls
        }
      }
      def forwarders(sdef: Tree): List[Tree] = sdef match {
        case ClassDef(mods, name, tparams, _) if (parentToken == INTERFACE) =>
          val tparams1: List[TypeDef] = tparams map (_.duplicate)
          var rhs: Tree = Select(Ident(parentName.toTermName), name)
          if (!tparams1.isEmpty) rhs = AppliedTypeTree(rhs, tparams1 map (tp => Ident(tp.name)))
          List(TypeDef(Modifiers(Flags.PROTECTED), name, tparams1, rhs))
        case _ =>
          List()
      }
      val sdefs = statics.toList
      val idefs = members.toList ::: (sdefs flatMap forwarders)
      (sdefs, idefs)
    }
      
    def annotationDecl(mods: Modifiers): List[Tree] = {
      accept(AT)
      accept(INTERFACE)
      val pos = in.currentPos
      val name = identForType()
      val parents = List(scalaDot(newTypeName("Annotation")), 
                         Select(javaLangDot(newTermName("annotation")), newTypeName("Annotation")),
                         scalaDot(newTypeName("ClassfileAnnotation")))
      val (statics, body) = typeBody(AT, name)
      def getValueMethodType(tree: Tree) = tree match {
        case DefDef(_, nme.value, _, _, tpt, _) => Some(tpt.duplicate)
        case _ => None
      }
      var templ = makeTemplate(parents, body)
      for (stat <- templ.body; tpt <- getValueMethodType(stat))
        templ = makeTemplate(parents, makeConstructor(List(tpt)) :: templ.body)
      addCompanionObject(statics, atPos(pos) {
        ClassDef(mods, name, List(), templ)
      })
    }

    def enumDecl(mods: Modifiers): List[Tree] = {
      accept(ENUM)
      val pos = in.currentPos
      val name = identForType()
      def enumType = Ident(name)
      val interfaces = interfacesOpt()
      accept(LBRACE)
      val buf = new ListBuffer[Tree]
      def parseEnumConsts() {
        if (in.token != RBRACE && in.token != SEMI && in.token != EOF) {
          buf += enumConst(enumType)
          if (in.token == COMMA) {
            in.nextToken
            parseEnumConsts()
          }
        }
      }
      parseEnumConsts() 
      val consts = buf.toList
      val (statics, body) = 
        if (in.token == SEMI) {
          in.nextToken
          typeBodyDecls(ENUM, name)
        } else {
          (List(), List())
        }
      val predefs = List(
        DefDef(
          Modifiers(Flags.JAVA | Flags.STATIC), newTermName("values"), List(), 
          List(List()),
          arrayOf(enumType),
          blankExpr),
        DefDef(
          Modifiers(Flags.JAVA | Flags.STATIC), newTermName("valueOf"), List(), 
          List(List(makeParam("x", TypeTree(StringClass.tpe)))),
          enumType,
          blankExpr))
      accept(RBRACE)
      val superclazz = 
        AppliedTypeTree(javaLangDot(newTypeName("Enum")), List(enumType))
      addCompanionObject(consts ::: statics ::: predefs, atPos(pos) {
        ClassDef(mods, name, List(), 
                 makeTemplate(superclazz :: interfaces, body))
      })
    }

    def enumConst(enumType: Tree) = {
      annotations()
      atPos(in.currentPos) {
        val name = ident()
        if (in.token == LPAREN) {
          // skip arguments
          skipAhead()
          accept(RPAREN)
        }
        if (in.token == LBRACE) {
          // skip classbody
          skipAhead()
          accept(RBRACE)
        }
        ValDef(Modifiers(Flags.JAVA | Flags.STATIC), name, enumType, blankExpr)
      }
    }

    def typeDecl(mods: Modifiers): List[Tree] = in.token match {
      case ENUM      => enumDecl(mods)
      case INTERFACE => interfaceDecl(mods)
      case AT        => annotationDecl(mods)
      case CLASS     => classDecl(mods)
      case _         => in.nextToken; syntaxError("illegal start of type declaration", true); List(errorTypeTree)
    }

    /** CompilationUnit ::= [package QualId semi] TopStatSeq 
     */
    def compilationUnit(): Tree = {
      var pos = in.currentPos;
      val pkg: RefTree = 
        if (in.token == AT || in.token == PACKAGE) {
          annotations()
          pos = in.currentPos
          accept(PACKAGE)
          val pkg = qualId()
          accept(SEMI)
          pkg
        } else {
          Ident(nme.EMPTY_PACKAGE_NAME)
        }
      thisPackageName = gen.convertToTypeName(pkg) match {
        case Some(t)  => t.name.toTypeName
        case _        => tpnme.EMPTY
      }
      val buf = new ListBuffer[Tree]
      while (in.token == IMPORT)
        buf ++= importDecl()
      while (in.token != EOF && in.token != RBRACE) {
        while (in.token == SEMI) in.nextToken
        buf ++= typeDecl(modifiers(false))
      }
      accept(EOF)
      atPos(pos) {
        makePackaging(pkg, buf.toList)
      }
    }
  }
}

Other Scala examples (source code examples)

Here is a short list of links related to this Scala JavaParsers.scala source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.