summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala')
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala153
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 == ";")
+ }
+}