summaryrefslogblamecommitdiff
path: root/sources/scala/tools/nsc/symtab/classfile/MetaParser.scala
blob: eca5da7091dfb8dadde951d8b0dc8f14c10ee237 (plain) (tree)
1
2
3
4
5
6
7
8
9




                            


                                                          
                       
                                     










































                                                                                               
                                           












                                                                 
                                                                                        
                



                                                                                          






                                                   
                               
                            
                                              









                                             
                         
                            
                                        














                                            
                                         

                                  

                                                      






























                                                                    
                          




                           
/* NSC -- new scala compiler
 * Copyright 2005 LAMP/EPFL
 * @author  Martin Odersky
 */
// $Id$
package scala.tools.nsc.symtab.classfile;

import java.util.{StringTokenizer, NoSuchElementException}
import util.ListBuffer;
import scala.tools.nsc.util.Position;

abstract class MetaParser{

  val global: Global;
  import global._;

  private var scanner: StringTokenizer = _;
  private var owner: Symbol = _;
  private var ownertype: Type = _;
  private var token: String = _;
  private var locals: Scope = null;

  def parse(meta: String, sym: Symbol, symtype: Type): unit = {
    //System.out.println("parse meta for " + sym + ":" + meta + ", locals = " + locals);//DEBUG
    this.scanner = new StringTokenizer(meta, "()[], \t<;", true);
    this.owner = sym;
    this.ownertype = symtype;
    nextToken();
    if (token == "class") parseClass()
    else if (token == "method") parseMethod()
    else if (token == "field") parseField()
    else if (token == "constr") parseConstr()
    else owner.setInfo(symtype);
  }

  protected def nextToken(): unit =
    try {
      do { token = scanner.nextToken().trim() } while (token.length() == 0)
    } catch {
      case ex: NoSuchElementException => token = ""
    }

  protected def parseType(): Type = {
    val str = token;
    nextToken();
    val sym = locals.lookup(newTypeName(str));
    if (sym != NoSymbol) sym.tpe
    else {
      val tp = definitions.getClass(str).tpe;
      if (token != "[") tp
      else {
	val args = new ListBuffer[Type];
	do {
	  nextToken(); args += parseType();
	} while (token == ",");
	nextToken();
	appliedType(tp, args.toList)
      }
    }
  }

  protected def parseTypeParam(): Symbol = {
    val vflag =
      if (token == "+") { nextToken(); Flags.COVARIANT }
      else if (token == "-") { nextToken(); Flags.CONTRAVARIANT }
      else 0;
    assert(token.startsWith("?"));
    val sym = owner.newTypeParameter(Position.NOPOS, newTypeName(token)).setFlag(vflag);
    nextToken();
    val lo = if (token == ">") { nextToken(); parseType() } else definitions.AllClass.tpe;
    val hi = if (token == "<") { nextToken(); parseType() } else definitions.AnyClass.tpe;
    sym.setInfo(TypeBounds(lo, hi));
    locals enter sym;
    sym
  }

  protected def parseTypeParams(): List[Symbol] = {
    nextToken();
    val syms = new ListBuffer[Symbol];
    if (token != "]") {
      syms += parseTypeParam();
      while (token == ",") {
        nextToken(); syms += parseTypeParam();
      }
    }
    assert(token == "]");
    syms.toList
  }

  protected def parseParams(): List[Type] = {
    nextToken();
    val tps = new ListBuffer[Type];
    if (token != ")") {
      tps += parseType();
      while (token == ",") {
        nextToken(); tps += parseType();
      }
    }
    assert(token == ")");
    tps.toList
  }

  protected def parseClass(): unit = {
    locals = new Scope();
    def parse(): Type = {
      nextToken();
      if (token == "[") {
	PolyType(parseTypeParams(), parse())
      } else if (token == "extends") {
	val tps = new ListBuffer[Type];
	do {
          nextToken(); tps += parseType()
	} while (token == "with");
	ownertype match {
          case ClassInfoType(parents, decls, clazz) =>
            ClassInfoType(tps.toList, decls, clazz)
	}
      } else ownertype
    }
    owner.setInfo(parse());
    assert(token == ";")
  }

  protected def parseMethod(): unit = {
    val globals = locals;
    locals = if (locals == null) new Scope() else new Scope(locals);
    def parse(): Type = {
      nextToken();
      if (token == "[") PolyType(parseTypeParams(), parse())
      else if (token == "(") MethodType(parseParams(), parse())
      else parseType()
    }
    owner.setInfo(parse());
    locals = globals;
    assert(token == ";")
  }

  protected def parseField(): unit = {
    nextToken();
    owner.setInfo(parseType());
    assert(token == ";")
  }

  protected def parseConstr(): unit = {
    def parse(): Type = {
      nextToken();
      if (token == "(") MethodType(parseParams(), parse())
      else owner.owner.tpe
    }
    owner.setInfo(parse());
    assert(token == ";")
  }
}