diff options
Diffstat (limited to 'src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala new file mode 100644 index 0000000000..eca5da7091 --- /dev/null +++ b/src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala @@ -0,0 +1,153 @@ +/* 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 == ";") + } +} |