summaryrefslogtreecommitdiff
path: root/sources
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2003-11-12 18:01:30 +0000
committerMartin Odersky <odersky@gmail.com>2003-11-12 18:01:30 +0000
commitf5437e9a8bb543cf57b295739dd3abdebb7be651 (patch)
tree82d04d9b9de6e798631dfbc12fa62f0f8be3dc02 /sources
parentf8ed082d80fb662f96d9a95dad3d7481b7e88818 (diff)
downloadscala-f5437e9a8bb543cf57b295739dd3abdebb7be651.tar.gz
scala-f5437e9a8bb543cf57b295739dd3abdebb7be651.tar.bz2
scala-f5437e9a8bb543cf57b295739dd3abdebb7be651.zip
*** empty log message ***
Diffstat (limited to 'sources')
-rw-r--r--sources/scala/tools/scalac/CompilerPhases.scala20
-rw-r--r--sources/scala/tools/scalac/Global.scala28
-rw-r--r--sources/scala/tools/scalac/Main.scala39
-rw-r--r--sources/scala/tools/scalac/ast/TreeList.scala76
-rw-r--r--sources/scala/tools/scalac/ast/parser/Parser.scala1971
-rw-r--r--sources/scala/tools/scalac/ast/parser/ParserPhase.scala25
-rw-r--r--sources/scala/tools/scalac/ast/parser/Scanner.scala807
-rw-r--r--sources/scala/tools/scalac/ast/parser/TokenData.scala46
-rw-r--r--sources/scala/tools/scalac/ast/parser/Tokens.scala92
-rw-r--r--sources/scala/tools/scalac/ast/printer/HTMLPrinter.scala167
-rw-r--r--sources/scala/tools/scalac/ast/printer/TextTreePrinter.scala667
-rw-r--r--sources/scalac/CompilerPhases.java50
-rw-r--r--sources/scalac/Global.java13
-rw-r--r--sources/scalac/symtab/Symbol.java7
-rw-r--r--sources/scalac/symtab/classfile/Pickle.java6
-rw-r--r--sources/scalac/symtab/classfile/UnPickle.java11
-rw-r--r--sources/scalac/typechecker/Analyzer.java4
-rw-r--r--sources/scalac/typechecker/ConstantFolder.java6
18 files changed, 4004 insertions, 31 deletions
diff --git a/sources/scala/tools/scalac/CompilerPhases.scala b/sources/scala/tools/scalac/CompilerPhases.scala
new file mode 100644
index 0000000000..e9f5a9c665
--- /dev/null
+++ b/sources/scala/tools/scalac/CompilerPhases.scala
@@ -0,0 +1,20 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+\* */
+
+// $Id$
+
+package scala.tools.scalac;
+
+/**
+ * This class defines all compiler phases and maintains a list of
+ * active phases.
+ */
+class CompilerPhases extends scalac.CompilerPhases {
+
+ protected override def PARSER_PHASE(): Class =
+ Class.forName("scala.tools.scalac.ast.parser.ParserPhase$class");
+
+}
diff --git a/sources/scala/tools/scalac/Global.scala b/sources/scala/tools/scalac/Global.scala
new file mode 100644
index 0000000000..2daead9e55
--- /dev/null
+++ b/sources/scala/tools/scalac/Global.scala
@@ -0,0 +1,28 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+** **
+** $Id: Global.scala
+\* */
+
+package scala.tools.scalac;
+
+import ast.printer._;
+import scalac.CompilerCommand;
+import java.io.OutputStream;
+import scalac.ast.printer.TreePrinter;
+
+/** The global environment of a compiler run
+ *
+ */
+class Global(args: CompilerCommand, interpret: boolean) extends scalac.Global(args, interpret) {
+
+ def this(args: CompilerCommand) = this(args, false);
+
+ protected override def newTextTreePrinter(printStream: OutputStream): TreePrinter =
+ new TextTreePrinter(printStream);
+ protected override def newHTMLTreePrinter(printStream: OutputStream): TreePrinter =
+ new HTMLTreePrinter(printStream);
+
+}
diff --git a/sources/scala/tools/scalac/Main.scala b/sources/scala/tools/scalac/Main.scala
new file mode 100644
index 0000000000..c0a5a3ed0b
--- /dev/null
+++ b/sources/scala/tools/scalac/Main.scala
@@ -0,0 +1,39 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+** **
+** $Id$
+\* */
+
+package scala.tools.scalac;
+
+import scalac.util.Reporter;
+import scalac.CompilerCommand;
+
+/** The main class for SoCoS, a compiler for the programming
+ * language Scala.
+ *
+ * @author Matthias Zenger
+ * @version 1.0
+ */
+object Main {
+
+ val PRODUCT: String =
+ System.getProperty("scala.product", "socos");
+ val VERSION: String =
+ System.getProperty("scala.version", "unknown version");
+
+ def main(args: Array[String]): unit = {
+ val reporter = new Reporter();
+ val command = new CompilerCommand(
+ PRODUCT, VERSION, reporter, new CompilerPhases());
+ if (command.parse(args) && command.files.list.size() > 0) {
+ val global = new Global(command);
+ global.compile(command.files.toArray(), false);
+ global.stop("total");
+ global.reporter.printSummary();
+ }
+ System.exit(if (reporter.errors() > 0) 1 else 0);
+ }
+}
diff --git a/sources/scala/tools/scalac/ast/TreeList.scala b/sources/scala/tools/scalac/ast/TreeList.scala
new file mode 100644
index 0000000000..0cc2365789
--- /dev/null
+++ b/sources/scala/tools/scalac/ast/TreeList.scala
@@ -0,0 +1,76 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+** **
+\* */
+
+// $Id$
+
+package scala.tools.scalac.ast;
+
+import scalac.ast._;
+
+/** List of trees.
+ */
+
+final class TreeList(ts: Array[Tree]) {
+
+ private var trees = ts;
+ private var len = ts.length;
+
+ def this() = { this(new Array[Tree](4)); len = 0 }
+
+ def append(tree: Tree): TreeList = {
+ if (len == trees.length) {
+ val ts = new Array[Tree](if (len == 0) 4 else len * 2);
+ System.arraycopy(trees.asInstanceOf[Array[Object]], 0,
+ ts.asInstanceOf[Array[Object]], 0, len);
+ trees = ts;
+ }
+ trees(len) = tree;
+ len = len + 1;
+ this
+ }
+
+ def append(ts: Array[Tree]): unit = {
+ for (val j <- Iterator.range(0, ts.length)) do
+ append(ts(j));
+ }
+
+ def append(tl: TreeList): unit = {
+ for (val j <- Iterator.range(0, ts.length)) do
+ append(tl.trees(j));
+ }
+
+ def clear(): unit = {
+ trees = new Array[Tree](4);
+ len = 0;
+ }
+
+ def length(): int = len;
+
+ def get(i: int): Tree = trees(i);
+
+ def first(): Tree = trees(0);
+
+ def removeLast(): Tree = {
+ len = len - 1;
+ trees(len)
+ }
+
+ def toArray(): Array[Tree] = {
+ val ts = new Array[Tree](len);
+ System.arraycopy(trees.asInstanceOf[Array[Object]], 0,
+ ts.asInstanceOf[Array[Object]], 0, len);
+ ts
+ }
+
+ def copyTo[t <: Tree](ts: Array[t]): Array[t] = copyTo(ts, 0);
+
+ def copyTo[t <: Tree](ts: Array[t], from: int): Array[t] = {
+ System.arraycopy(trees.asInstanceOf[Array[java.lang.Object]], 0,
+ ts.asInstanceOf[Array[java.lang.Object]], from, len);
+ ts;
+ }
+}
diff --git a/sources/scala/tools/scalac/ast/parser/Parser.scala b/sources/scala/tools/scalac/ast/parser/Parser.scala
new file mode 100644
index 0000000000..4d7435ea70
--- /dev/null
+++ b/sources/scala/tools/scalac/ast/parser/Parser.scala
@@ -0,0 +1,1971 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+** **
+** $Id$
+\* */
+
+package scala.tools.scalac.ast.parser;
+
+import scalac.ast.parser.PatternNormalizer;
+import ch.epfl.lamp.util.Position;
+
+import java.util.{Map, Stack, ArrayList, LinkedList};
+import scalac._;
+import scalac.util._;
+
+import scalac.symtab.Modifiers;
+import scalac.ast._;
+import Tree._;
+import java.lang.{Integer, Long, Float, Double};
+import scala.Iterator;
+
+/** A recursive descent parser for the programming language Scala.
+ *
+ * @author Martin Odersky, Matthias Zenger, Burak Emir
+ * @version 1.2
+ */
+class Parser(unit: Unit) {
+
+ import Tokens._;
+ import scala.tools.scalac.ast.TreeList;
+
+ /** the lexical analyzer
+ */
+ val s = new Scanner(unit);
+
+ /** the tree factory
+ */
+ val make: TreeFactory = unit.global.make;
+
+ /** pattern checker and normalizer
+ */
+ val pN = new PatternNormalizer(unit);
+
+ /** The current nesting depths of while and do loops.
+ */
+ var loopNestingDepth = 0;
+
+ /** this is the general parse method
+ */
+ def parse(): Array[Tree] = {
+ val ts = if (s.unit.console) templateStatSeq() else compilationUnit();
+ accept(EOF);
+ ts
+ }
+
+/////// HELPER FUNCTIONS ////////////////////////////////////////////////////
+
+ def newTreeArray(trees: Tree*): Array[Tree] = {
+ val arr = new Array[Tree](trees.length);
+ var i = 0;
+ for (val t <- trees.elements) do {
+ arr(i) = t; i = i + 1;
+ }
+ arr
+ }
+
+ def newValDefArray(trees: Tree$ValDef*): Array[Tree$ValDef] = {
+ val arr = new Array[Tree$ValDef](trees.length);
+ var i = 0;
+ for (val t <- trees.elements) do {
+ arr(i) = t; i = i + 1;
+ }
+ arr
+ }
+
+ def newValDefArrayArray(trees: Array[Tree$ValDef]*): Array[Array[Tree$ValDef]] = {
+ val arr = new Array[Array[Tree$ValDef]](trees.length);
+ var i = 0;
+ for (val t <- trees.elements) do {
+ arr(i) = t; i = i + 1;
+ }
+ arr
+ }
+
+ def newCaseDefArray(trees: Tree$CaseDef*): Array[Tree$CaseDef] = {
+ val arr = new Array[Tree$CaseDef](trees.length);
+ var i = 0;
+ for (val t <- trees.elements) do {
+ arr(i) = t; i = i + 1;
+ }
+ arr
+ }
+
+ def newNameArray(trees: Name*): Array[Name] = {
+ val arr = new Array[Name](trees.length);
+ var i = 0;
+ for (val t <- trees.elements) do {
+ arr(i) = t; i = i + 1;
+ }
+ arr
+ }
+
+/////// ERROR HANDLING //////////////////////////////////////////////////////
+
+ private def skip(): unit = {
+ //System.out.println("<skipping> " + s.token2string(s.token));//DEBUG
+ var nparens = 0;
+ var nbraces = 0;
+ while (true) {
+ s.token match {
+ case EOF =>
+ return;
+ case SEMI =>
+ 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;
+ }
+ s.nextToken();
+ }
+ }
+
+ def syntaxError(msg: String, skipIt: boolean): Tree =
+ syntaxError(s.pos, msg, skipIt);
+
+ def syntaxError(pos: int, msg: String, skipIt: boolean): Tree = {
+ if (pos != s.errpos) {
+ s.unit.error(pos, msg);
+ s.errpos = pos;
+ }
+ if (skipIt) skip();
+ make.Bad(pos)
+ }
+
+ def accept(token: int): int = {
+ val pos = s.pos;
+ if (s.token != token) {
+ val errpos = if ((s.pos >>> Position.COLUMN_BITS) >
+ (s.lastpos >>> Position.COLUMN_BITS)) s.lastpos
+ else s.pos;
+ syntaxError(errpos, s.token2string(token) + " expected but " +
+ s.token2string(s.token) + " found.", true);
+ }
+ if (s.token == token) s.nextToken();
+ pos
+ }
+
+/////// TOKEN CLASSES //////////////////////////////////////////////////////
+
+ def isModifier(): boolean =
+ (s.token == ABSTRACT)
+ || (s.token == FINAL)
+ || (s.token == SEALED)
+ || (s.token == PRIVATE)
+ || (s.token == PROTECTED)
+ || (s.token == OVERRIDE);
+
+ def isLocalModifier(): boolean =
+ (s.token == ABSTRACT)
+ || (s.token == FINAL)
+ || (s.token == SEALED);
+
+ def isDefIntro(): boolean = s.token match {
+ case VAL | VAR | DEF | TYPE | OBJECT | CASEOBJECT | CLASS | CASECLASS | TRAIT =>
+ true
+ case _ =>
+ false
+ }
+
+ def isDclIntro(): boolean = s.token match {
+ case VAL | VAR | DEF | TYPE =>
+ true;
+ case _ =>
+ false
+ }
+
+ def isExprIntro(): boolean = s.token match {
+ case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT |
+ STRINGLIT | SYMBOLLIT | TRUE | FALSE | NULL | IDENTIFIER |
+ THIS | SUPER | IF | FOR | NEW | USCORE | TRY | WHILE |
+ DO | RETURN | THROW | LPAREN | LBRACE =>
+ true;
+ case _ =>
+ false;
+ }
+
+/////// COMMENT COLLECTION ///////////////////////////////////////////////////
+
+ /** keep the comments associated with a given tree
+ */
+ protected val mapTreeComment: Map = unit.global.mapTreeComment;
+
+ /** stack of comments
+ */
+ protected val commentStack = new Stack();
+
+ /** positive if we are inside a block
+ */
+ protected var local = 0;
+
+ /** push last encountered comment and reset the buffer
+ */
+ protected def pushComment(): unit = {
+ if (local == 0) {
+ commentStack.push(if (s.docBuffer == null) null else s.docBuffer.toString());
+ s.docBuffer = null;
+ }
+ }
+
+ /** pop a comment from the stack and associate it with the given tree
+ */
+ protected def popComment(tree: Tree): Tree = {
+ if (local == 0)
+ if (!commentStack.empty())
+ mapTreeComment.put(tree, commentStack.pop().asInstanceOf[String]);
+ tree
+ }
+
+/////// TREE CONSTRUCTION ////////////////////////////////////////////////////
+
+ /** Name supply
+ */
+ var freshCnt = 0;
+
+ def fresh(): Name = {
+ val n = Name.fromString("x$" + freshCnt);
+ freshCnt = freshCnt + 1;
+ n
+ }
+
+ /** Create tree representing binary operation expression or pattern.
+ */
+ def makeBinop(isExpr: boolean, pos: int, left: Tree, op: Name, right: Tree): Tree =
+ if (isExpr) {
+ if (op.isLeftAssoc()) {
+ make.Apply(
+ pos,
+ make.Select(pos, left, NameTransformer.encode(op)),
+ newTreeArray(right));
+ } else {
+ val x: Name = fresh();
+ make.Block(
+ pos,
+ newTreeArray(
+ make.ValDef(pos, 0, x, Tree.Empty, left),
+ make.Apply(
+ pos,
+ make.Select(pos, right, NameTransformer.encode(op)),
+ newTreeArray(make.Ident(left.pos, x)))));
+ }
+ } else {
+ make.Apply(
+ pos,
+ make.Ident(pos, NameTransformer.encode(op).toTypeName()),
+ newTreeArray(left, right));
+ }
+
+ def scalaDot(pos: int, name: Name): Tree =
+ make.Select(pos, make.Ident(pos, Names.scala), name);
+
+ def scalaRuntimeDot(pos: int, name: Name): Tree =
+ make.Select(pos, scalaDot(pos, Names.runtime), name);
+
+ def ScalaRunTimeDot(pos: int, name: Name): Tree =
+ make.Select(pos, scalaRuntimeDot(pos, Names.ScalaRunTime), name);
+
+ def scalaBooleanDot(pos: int, name: Name): Tree =
+ make.Select(pos, scalaDot(pos, Names.Boolean), name);
+
+ def scalaObjectConstr(pos: int): Tree =
+ make.Apply(
+ pos, scalaDot(pos, Names.Object.toTypeName()), Tree.EMPTY_ARRAY);
+
+ /** Create tree for for-comprehension <for (enums) do body> or
+ * <for (enums) yield body> where mapName and flatmapName are chosen
+ * corresponding to whether this is a for-do or a for-yield.
+ */
+ def makeFor(pos: int, enums: Array[Tree], mapName: Name, flatmapName: Name, body: Tree): Tree = {
+
+ def makeFor1(pos: int, name: Name, pat: Tree, rhs: Tree, body: Tree): Tree =
+ make.Apply(
+ pos, make.Select(pos, rhs, name),
+ newTreeArray(makeForCont(pos, pat, body)));
+
+ def makeForCont(pos: int, pat: Tree, body: Tree): Tree = {
+ pat match {
+ case Tree$Ident(name1) =>
+ if (name1.isVariable())
+ make.Function(
+ pos,
+ newValDefArray(
+ make.ValDef(
+ pat.pos, Modifiers.PARAM, name1, Tree.Empty, Tree.Empty)),
+ body);
+ }
+ make.Visitor(pos, newCaseDefArray(
+ make.CaseDef(pos, pat, Tree.Empty, body)));
+ }
+
+ enums(0) match {
+ case Tree$PatDef(mods, pat, rhs) =>
+ if (enums.length == 1) {
+ makeFor1(pos, mapName, pat, rhs, body);
+ } else {
+ val newenums = new Array[Tree](enums.length - 1);
+ enums(1) match {
+ case Tree$PatDef(mods2, pat, rhs) =>
+ System.arraycopy(enums, 1, newenums, 0, newenums.length);
+ makeFor1(
+ pos, flatmapName, pat, rhs,
+ makeFor(enums(1).pos, newenums, mapName, flatmapName, body));
+ case _ =>
+ System.arraycopy(enums, 2, newenums, 1, newenums.length - 1);
+ newenums(0) = make.PatDef(
+ enums(0).pos, mods, pat,
+ makeFor1(enums(1).pos, Names.filter, pat.duplicate(), rhs, enums(1)));
+ makeFor(pos, newenums, mapName, flatmapName, body);
+ }
+ }
+ case _ =>
+ throw new ApplicationError();
+ }
+ }
+
+ def makeTry(pos: int, body: Tree, catcher: Tree, finalizer: Tree): Tree = {
+ var t = body;
+ if (catcher != Tree.Empty)
+ t = make.Apply(
+ pos,
+ make.Select(
+ pos,
+ make.Apply(
+ pos, ScalaRunTimeDot(pos, Names.Try), newTreeArray(t)),
+ Names.Catch),
+ newTreeArray(catcher));
+ if (finalizer != Tree.Empty)
+ t = make.Apply(
+ pos,
+ make.Select(
+ pos,
+ make.Apply(
+ pos, ScalaRunTimeDot(pos, Names.Try), newTreeArray(t)),
+ Names.Finally),
+ newTreeArray(finalizer));
+ t
+ }
+
+ def makeWhile(pos: int, lname: Name, cond: Tree, body: Tree): Tree = {
+ val continu = make.Apply(
+ pos, make.Ident(pos, lname), Tree.EMPTY_ARRAY);
+ val rhs = make.If(
+ pos,
+ cond,
+ make.Block(body.pos, newTreeArray(body, continu)),
+ make.Block(pos, Tree.EMPTY_ARRAY));
+ make.LabelDef(pos, lname, new Array[Tree$Ident](0), rhs);
+ }
+
+ def makeDoWhile(pos: int, lname: Name, body: Tree, cond: Tree): Tree = {
+ val continu = make.Apply(
+ pos, make.Ident(pos, lname), Tree.EMPTY_ARRAY);
+ val rhs = make.Block(
+ body.pos,
+ newTreeArray(
+ body,
+ make.If(
+ cond.pos,
+ cond,
+ continu,
+ make.Block(pos, Tree.EMPTY_ARRAY))));
+ make.LabelDef(pos, lname, new Array[Tree$Ident](0), rhs)
+ }
+
+ /** Convert tree to formal parameter list
+ */
+ def convertToParams(t: Tree): Array[Tree$ValDef] = {
+ t match {
+ case Tree$Function(params, Tree.Empty) =>
+ params
+ case Tree$Ident(_) | Tree$Typed(Tree$Ident(_), _) =>
+ newValDefArray(convertToParam(t));
+ case Tree$Block(stats) =>
+ if (stats.length == 0) Tree.ValDef_EMPTY_ARRAY;
+ }
+ syntaxError(t.pos, "malformed formal parameter list", false);
+ Tree.ValDef_EMPTY_ARRAY;
+ }
+
+ /** Convert list of trees to formal parameter list
+ */
+ def convertToParams(ts: Array[Tree]): Array[Tree$ValDef] = {
+ val res = new Array[Tree$ValDef](ts.length);
+ for (val i <- Iterator.range(0, res.length)) do
+ res(i) = convertToParam(ts(i));
+ res;
+ }
+
+ /** Convert tree to formal parameter
+ */
+ def convertToParam(tree: Tree): Tree$ValDef = tree match {
+ case Tree$Ident(name) =>
+ make.ValDef(
+ tree.pos, Modifiers.PARAM, name, Tree.Empty, Tree.Empty)
+ case Tree$Typed(Tree$Ident(name), tpe) =>
+ make.ValDef(
+ tree.pos, Modifiers.PARAM, name, tpe, Tree.Empty)
+ case _ =>
+ val tpe = syntaxError(tree.pos, "not a legal formal parameter", false);
+ make.ValDef(
+ tree.pos, Modifiers.PARAM, Names.ERROR, tpe, Tree.Empty)
+ }
+
+ /** Convert (qual)ident to type identifier
+ */
+ def convertToTypeId(t: Tree): Tree = t match {
+ case Tree$Ident(name) =>
+ make.Ident(t.pos, name.toTypeName())
+ case Tree$Select(qual, name) =>
+ make.Select(t.pos, qual, name.toTypeName())
+ case _ =>
+ t
+ }
+
+ /** Convert (qual)ident to constructor identifier
+ */
+ def convertToConstr(t: Tree): Tree = t match {
+ case Tree$Ident(name) =>
+ make.Ident(t.pos, name.toTypeName())
+ case Tree$Select(qual, name) =>
+ make.Select(t.pos, qual, name.toTypeName())
+ case _ =>
+ syntaxError(t.pos, "class constructor expected", false)
+ }
+
+ /** Complete unapplied constructor with `()' arguments
+ */
+ def applyConstr(t: Tree): Tree = t match {
+ case Tree$Apply(_, _) =>
+ t
+ case _ =>
+ make.Apply(t.pos, t, Tree.EMPTY_ARRAY)
+ }
+
+/////// OPERAND/OPERATOR STACK /////////////////////////////////////////////////
+
+ var operands = new Array[Tree](8);
+ var positions = new Array[int](8);
+ var operators = new Array[Name](8);
+ var sp = 0;
+
+ def push(od: Tree, pos: int, op: Name): unit = {
+ if (sp == operands.length) {
+ val operands1 = new Array[Tree](sp * 2);
+ System.arraycopy(operands, 0, operands1, 0, sp);
+ operands = operands1;
+ val positions1 = new Array[int](sp * 2);
+ System.arraycopy(positions, 0, positions1, 0, sp);
+ positions = positions1;
+ val operators1 = new Array[Name](sp * 2);
+ System.arraycopy(operators, 0, operators1, 0, sp);
+ operators = operators1;
+ }
+ operands(sp) = od;
+ positions(sp) = pos;
+ operators(sp) = op;
+ sp = sp + 1;
+ }
+
+ def reduceStack(isExpr: boolean, base: int, _top: Tree, prec: int, leftAssoc: boolean): Tree = {
+ var top = _top;
+ if (sp != base &&
+ operators(sp-1).precedence() == prec &&
+ operators(sp-1).isLeftAssoc() != leftAssoc) {
+ syntaxError(
+ positions(sp-1),
+ "left- and right-associative operators with same precedence may not be mixed",
+ false);
+ }
+ while (sp != base &&
+ (prec < operators(sp-1).precedence() ||
+ (leftAssoc && prec == operators(sp-1).precedence()))) {
+ sp = sp - 1;
+ top = makeBinop(isExpr, positions(sp), operands(sp), operators(sp), top);
+ }
+ top
+ }
+
+/////// IDENTIFIERS AND LITERALS ////////////////////////////////////////////////////////////
+
+ final val MINUS = Name.fromString("-");
+ final val PLUS = Name.fromString("+");
+ final val BANG = Name.fromString("!");
+ final val TILDE = Name.fromString("~");
+ final val STAR = Name.fromString("*");
+ final val BAR = Name.fromString("|");
+ final val OPT = Name.fromString("?");
+
+ def ident(): Name =
+ if (s.token == IDENTIFIER) {
+ val name = NameTransformer.encode(s.name);
+ s.nextToken();
+ name
+ } else {
+ accept(IDENTIFIER);
+ Names.ERROR
+ }
+
+ /** StableRef ::= StableId
+ * | [Ident `.'] this
+ * SimpleType ::= StableRef [`.' type]
+ */
+ def stableRef(thisOK: boolean, typeOK: boolean): Tree = {
+ var t: Tree = null;
+ if (s.token == THIS) {
+ t = make.This(s.skipToken(), TypeNames.EMPTY);
+ if (!thisOK || s.token == DOT)
+ t = selectors(accept(DOT), t, typeOK);
+ } else if (s.token == SUPER) {
+ t = make.Super(
+ s.skipToken(), TypeNames.EMPTY, mixinQualifierOpt());
+ t = make.Select(accept(DOT), t, ident());
+ if (s.token == DOT)
+ t = selectors(s.skipToken(), t, typeOK);
+ } else {
+ val i: Tree$Ident = make.Ident(s.pos, ident());
+ t = i;
+ if (s.token == DOT) {
+ val pos = s.skipToken();
+ if (s.token == THIS) {
+ s.nextToken();
+ t = make.This(i.pos, i.name.toTypeName());
+ if (!thisOK || s.token == DOT)
+ t = selectors(accept(DOT), t, typeOK);
+ } else if (s.token == SUPER) {
+ s.nextToken();
+ t = make.Super(
+ i.pos, i.name.toTypeName(), mixinQualifierOpt());
+ t = make.Select(accept(DOT), t, ident());
+ if (s.token == DOT)
+ t = selectors(s.skipToken(), t, typeOK);
+ } else {
+ t = selectors(pos, t, typeOK);
+ }
+ }
+ }
+ t
+ }
+
+ def selectors(pos: int, t: Tree, typeOK: boolean): Tree =
+ if (typeOK && s.token == TYPE) {
+ s.nextToken();
+ make.SingletonType(pos, t);
+ } else {
+ val t1 = make.Select(pos, t, ident());
+ if (s.token == DOT) selectors(s.skipToken(), t1, typeOK);
+ else t1
+ }
+
+ /** MixinQualifier ::= `[' Id `]'
+ */
+ def mixinQualifierOpt(): Name =
+ if (s.token == LBRACKET) {
+ s.nextToken();
+ val name = ident().toTypeName();
+ accept(RBRACKET);
+ name
+ } else {
+ TypeNames.EMPTY
+ }
+
+ /** StableId ::= Id
+ * | StableRef `.' Id
+ * | [Id '.'] super [MixinQualifier] ` `.' Id
+ */
+ def stableId(): Tree =
+ stableRef(false, false);
+
+ /** QualId ::= Id {`.' Id}
+ */
+ def qualId(): Tree = {
+ val id = make.Ident(s.pos, ident());
+ if (s.token == DOT) selectors(s.skipToken(), id, false)
+ else id
+ }
+
+ /** SimpleExpr ::= literal
+ * | symbol [ArgumentExprs]
+ * | null
+ */
+ def literal(isPattern: boolean): Tree = {
+ def litToTree() = s.token match {
+ case CHARLIT =>
+ make.Literal(s.pos, new Character(s.intVal.asInstanceOf[char]))
+ case INTLIT =>
+ make.Literal(s.pos, new Integer(s.intVal.asInstanceOf[int]))
+ case LONGLIT =>
+ make.Literal(s.pos, new Long(s.intVal))
+ case FLOATLIT =>
+ make.Literal(s.pos, new Float(s.floatVal.asInstanceOf[float]))
+ case DOUBLELIT =>
+ make.Literal(s.pos, new Double(s.floatVal))
+ case STRINGLIT =>
+ make.Literal(s.pos, s.name.toString())
+ case TRUE =>
+ make.Literal(s.pos, java.lang.Boolean.TRUE)
+ case FALSE =>
+ make.Literal(s.pos, java.lang.Boolean.FALSE)
+ case NULL =>
+ make.Ident(s.pos, Names.null_)
+ case SYMBOLLIT =>
+ var symt = scalaDot(s.pos, Names.Symbol);
+ if (isPattern) symt = convertToTypeId(symt);
+ make.Apply(
+ s.pos, symt, newTreeArray(make.Literal(s.pos, s.name.toString())));
+ case _ =>
+ syntaxError("illegal literal", true)
+ }
+
+ val isSymLit = s.token == SYMBOLLIT;
+ val t = litToTree();
+ s.nextToken();
+ if (isSymLit && (s.token == LPAREN || s.token == LBRACE)) {
+ var labt = scalaDot(s.pos, Names.Labelled);
+ if (isPattern) labt = convertToTypeId(labt);
+ val listt = if (isPattern) scalaDot(s.pos, Names.List.toTypeName())
+ else make.Select(s.pos, scalaDot(s.pos, Names.Predef), Names.List);
+ make.Apply(
+ s.pos, labt, newTreeArray(t, make.Apply(s.pos, listt, argumentExprs())));
+ }
+ t
+ }
+
+//////// TYPES ///////////////////////////////////////////////////////////////
+
+ /** TypedOpt ::= [`:' Type]
+ */
+ def typedOpt(): Tree =
+ if (s.token == COLON) {
+ s.nextToken();
+ typ()
+ } else {
+ Tree.Empty
+ }
+
+ /** SimpleTypedOpt ::= [`:' SimpleType]
+ */
+ def simpleTypedOpt(): Tree =
+ if (s.token == COLON) {
+ s.nextToken();
+ simpleType()
+ } else {
+ Tree.Empty
+ }
+
+ /** Types ::= Type {`,' Type}
+ */
+ def types(): Array[Tree] = {
+ val ts = new TreeList();
+ ts.append(typ());
+ while (s.token == COMMA) {
+ s.nextToken();
+ ts.append(typ());
+ }
+ ts.toArray()
+ }
+
+ /** Type ::= Type1 `=>' Type
+ * | `(' [Types] `)' `=>' Type
+ * | Type1
+ */
+ def typ(): Tree =
+ if (s.token == LPAREN) {
+ s.nextToken();
+ if (s.token == RPAREN) {
+ s.nextToken();
+ val pos = accept(ARROW);
+ make.FunType(pos, Tree.EMPTY_ARRAY, typ());
+ } else {
+ val t = typ();
+ if (s.token == COMMA) {
+ s.nextToken();
+ val ts = new TreeList();
+ ts.append(t);
+ ts.append(types());
+ accept(RPAREN);
+ val pos = accept(ARROW);
+ make.FunType(pos, ts.toArray(), typ());
+ } else {
+ accept(RPAREN);
+ t
+ }
+ }
+ } else {
+ val t = type1();
+ if (s.token == ARROW)
+ make.FunType(s.skipToken(), newTreeArray(t), typ())
+ else
+ t
+ }
+
+ /** Type1 ::= SimpleType {with SimpleType} [Refinement]
+ */
+ def type1(): Tree = {
+ val pos = s.pos;
+ val t = simpleType();
+ if (s.token == WITH || s.token == LBRACE) {
+ val ts = new TreeList();
+ ts.append(t);
+ while (s.token == WITH) {
+ s.nextToken();
+ ts.append(simpleType());
+ }
+ val rs = if (s.token == LBRACE) refinement() else Tree.EMPTY_ARRAY;
+ make.CompoundType(pos, ts.toArray(), rs)
+ } else {
+ t
+ }
+ }
+
+ /** SimpleType ::= SimpleType TypeArgs
+ * | SimpleType `#' Id
+ * | StableId
+ * | StableRef `.' type
+ * | `(' Type `)'
+ */
+ def simpleType(): Tree = {
+ val pos = s.pos;
+ var t: Tree =
+ if (s.token == LPAREN) {
+ s.nextToken();
+ val t = typ();
+ accept(RPAREN);
+ t
+ } else {
+ convertToTypeId(stableRef(false, true));
+ }
+ while (true) {
+ if (s.token == HASH)
+ t = make.SelectFromType(s.skipToken(), t, ident().toTypeName());
+ else if (s.token == LBRACKET)
+ t = make.AppliedType(pos, t, typeArgs());
+ else
+ return t;
+ }
+ null; //dummy
+ }
+
+ /** TypeArgs ::= `[' Types `]'
+ */
+ def typeArgs(): Array[Tree] = {
+ accept(LBRACKET);
+ val ts = types();
+ accept(RBRACKET);
+ ts
+ }
+
+//////// EXPRESSIONS ////////////////////////////////////////////////////////
+
+ /** EqualsExpr ::= `=' Expr
+ */
+ def equalsExpr(): Tree = {
+ accept(EQUALS);
+ expr()
+ }
+
+ /** Exprs ::= Expr {`,' Expr}
+ * | Expr `:' `_' `*'
+ */
+ def exprs(): Array[Tree] = {
+ val ts = new TreeList();
+ ts.append(expr(true));
+ while (s.token == COMMA) {
+ s.nextToken();
+ ts.append(expr());
+ }
+ ts.toArray()
+ }
+
+ /** Expr ::= Bindings `=>' Expr
+ * | if `(' Expr `)' Expr [[`;'] else Expr]
+ * | try `{' block `}' [catch Expr] [finally Expr]
+ * | while `(' Expr `)' Expr
+ * | do Expr [`;'] while `(' Expr `)'
+ * | for `(' Enumerators `)' (do | yield) Expr
+ * | throw Expr
+ * | return [Expr]
+ * | [SimpleExpr `.'] Id `=' Expr
+ * | SimpleExpr ArgumentExprs `=' Expr
+ * | PostfixExpr [`:' Type1]
+ * Bindings ::= Id [`:' Type1]
+ * | `(' [Binding {`,' Binding}] `)'
+ * Binding ::= Id [`:' Type]
+ */
+
+ def expr(): Tree =
+ expr(false);
+
+ def expr(isArgument: boolean): Tree = {
+ if (s.token == IF) {
+ val pos = s.skipToken();
+ accept(LPAREN);
+ val cond = expr();
+ accept(RPAREN);
+ val thenp = expr();
+ val elsep =
+ if (s.token == ELSE) { s.nextToken(); expr() }
+ else Tree.Empty;
+ make.If(pos, cond, thenp, elsep)
+ } else if (s.token == TRY) {
+ val pos = s.skipToken();
+ accept(LBRACE);
+ val body = block(pos);
+ accept(RBRACE);
+ val catcher =
+ if (s.token == CATCH) { s.nextToken(); expr() }
+ else Tree.Empty;
+ val finalizer =
+ if (s.token == FINALLY) { s.nextToken(); expr() }
+ else Tree.Empty;
+ makeTry(pos, body, catcher, finalizer)
+ } else if (s.token == WHILE) {
+ val lname = Name.fromString("label$" + loopNestingDepth);
+ loopNestingDepth = loopNestingDepth + 1;
+ val pos = s.skipToken();
+ accept(LPAREN);
+ val cond = expr();
+ accept(RPAREN);
+ val body = expr();
+ loopNestingDepth = loopNestingDepth - 1;
+ makeWhile(pos, lname, cond, body)
+ } else if (s.token == DO) {
+ val lname = Name.fromString("label$" + loopNestingDepth);
+ loopNestingDepth = loopNestingDepth + 1;
+ val pos = s.skipToken();
+ val body = expr();
+ if (s.token == SEMI) s.nextToken();
+ accept(WHILE);
+ accept(LPAREN);
+ val cond = expr();
+ accept(RPAREN);
+ loopNestingDepth = loopNestingDepth - 1;
+ makeDoWhile(pos, lname, body, cond)
+ } else if (s.token == FOR) {
+ s.nextToken();
+ accept(LPAREN);
+ val enums = enumerators();
+ accept(RPAREN);
+ if (s.token == DO) {
+ makeFor(s.skipToken(), enums, Names.foreach, Names.foreach, expr())
+ } else if (s.token == YIELD) {
+ makeFor(s.skipToken(), enums, Names.map, Names.flatmap, expr())
+ } else {
+ syntaxError("`do' or `yield' expected", true)
+ }
+ } else if (s.token == RETURN) {
+ val pos = s.skipToken();
+ val e =
+ if (isExprIntro()) expr()
+ else make.Block(pos, Tree.EMPTY_ARRAY);
+ make.Return(pos, e)
+ } else if (s.token == THROW) {
+ val pos = s.skipToken();
+ make.Throw(pos, expr())
+ } else {
+ var t = postfixExpr();
+ if (s.token == EQUALS) {
+ t match {
+ case Tree$Ident(_) | Tree$Select(_, _) | Tree$Apply(_, _) =>
+ t = make.Assign(s.skipToken(), t, expr());
+ }
+ } else if (s.token == COLON) {
+ val pos = s.skipToken();
+ if (isArgument && s.token == USCORE) {
+ val pos1 = s.skipToken();
+ if (s.token == IDENTIFIER && s.name == Names.STAR) {
+ s.nextToken();
+ t = make.Typed(
+ pos, t, make.Ident(pos1, TypeNames.WILDCARD_STAR));
+ } else {
+ syntaxError(s.pos, "`*' expected", true);
+ }
+ } else {
+ val tp = type1();
+ t = make.Typed(pos, t, tp);
+ }
+ }
+ if (s.token == ARROW) {
+ t = make.Function(s.skipToken(), convertToParams(t), expr());
+ }
+ t
+ }
+ }
+
+ /** PostfixExpr ::= InfixExpr [Id]
+ * InfixExpr ::= PrefixExpr
+ * | InfixExpr Id InfixExpr
+ */
+ def postfixExpr(): Tree = {
+ val base = sp;
+ var top = prefixExpr();
+ while (s.token == IDENTIFIER) {
+ top = reduceStack(
+ true, base, top, s.name.precedence(), s.name.isLeftAssoc());
+ push(top, s.pos, s.name);
+ ident();
+ if (isExprIntro()) {
+ top = prefixExpr();
+ } else {
+ sp = sp - 1;
+ val pos = positions(sp);
+ val postOp = operators(sp);
+ top = reduceStack(true, base, operands(sp), 0, true);
+ return make.Select(pos, top, NameTransformer.encode(postOp));
+ }
+ }
+ reduceStack(true, base, top, 0, true)
+ }
+
+ /** PrefixExpr ::= [`-' | `+' | `~' | `!'] SimpleExpr
+ */
+ def prefixExpr(): Tree =
+ if (s.token == IDENTIFIER &&
+ (s.name == MINUS ||
+ s.name == PLUS ||
+ s.name == TILDE ||
+ s.name == BANG)) {
+ val name = ident();
+ make.Select(s.pos, simpleExpr(), name);
+ } else {
+ simpleExpr()
+ }
+
+ /* SimpleExpr ::= literal
+ * | StableRef
+ * | `(' [Expr] `)'
+ * | BlockExpr
+ * | new Template
+ * | SimpleExpr `.' Id
+ * | SimpleExpr TypeArgs
+ * | SimpleExpr ArgumentExprs
+ */
+ def simpleExpr(): Tree = {
+ var t: Tree = null;
+ s.token match {
+ case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT | STRINGLIT |
+ SYMBOLLIT | TRUE | FALSE | NULL =>
+ t = literal(false);
+ case IDENTIFIER | THIS | SUPER =>
+ t = stableRef(true, false);
+ case LPAREN =>
+ val pos = s.skipToken();
+ if (s.token == RPAREN) {
+ s.nextToken();
+ t = make.Block(pos, Tree.EMPTY_ARRAY);
+ } else {
+ t = expr();
+ if (s.token == COMMA) {
+ val commapos = s.skipToken();
+ val ts = new TreeList();
+ ts.append(t);
+ ts.append(exprs());
+ accept(RPAREN);
+ if (s.token == ARROW) {
+ t = make.Function(
+ pos, convertToParams(ts.toArray()), Tree.Empty);
+ } else {
+ t = syntaxError(commapos, "`)' expected", false);
+ }
+ } else {
+ accept(RPAREN);
+ }
+ }
+ case LBRACE =>
+ t = blockExpr();
+ case NEW =>
+ t = make.New(s.skipToken(), template());
+ case _ =>
+ return syntaxError("illegal start of expression", true);
+ }
+ while (true) {
+ s.token match {
+ case DOT =>
+ t = make.Select(s.skipToken(), t, ident());
+ case LBRACKET =>
+ t match {
+ case Tree$Ident(_) | Tree$Select(_, _) =>
+ t = make.TypeApply(s.pos, t, typeArgs());
+ case _ =>
+ return t;
+ }
+ case LPAREN | LBRACE =>
+ t = make.Apply(s.pos, t, argumentExprs());
+ case _ =>
+ return t;
+ }
+ }
+ null;//dummy
+ }
+
+ /** ArgumentExprs ::= `(' [Exprs] `)'
+ * | BlockExpr
+ */
+ def argumentExprs(): Array[Tree] = {
+ var ts = Tree.EMPTY_ARRAY;
+ if (s.token == LBRACE) {
+ ts = newTreeArray(blockExpr());
+ } else {
+ accept(LPAREN);
+ if (s.token != RPAREN)
+ ts = exprs();
+ accept(RPAREN);
+ }
+ ts
+ }
+
+ /** BlockExpr ::= `{' CaseClause {CaseClause} `}'
+ * | `{' Block `}'
+ */
+ def blockExpr(): Tree = {
+ local = local + 1;
+ val pos = accept(LBRACE);
+ val res =
+ if (s.token == CASE) {
+ val stats = new TreeList();
+ do {
+ stats.append(caseClause());
+ } while (s.token == CASE);
+ make.Visitor(pos,
+ stats.copyTo(new Array[Tree$CaseDef](stats.length()))
+ .asInstanceOf[Array[Tree$CaseDef]])
+ } else {
+ block(pos);
+ }
+ accept(RBRACE);
+ local = local - 1;
+ res
+ }
+
+ /** Block ::= BlockStatSeq
+ */
+ def block(pos: int): Tree = {
+ val stats = blockStatSeq(new TreeList());
+ if (stats.length == 1 && stats(0).isTerm()) stats(0)
+ else make.Block(pos, stats)
+ }
+
+ /** caseClause : =>= case Pattern [if PostfixExpr] `=>' Block
+ */
+ def caseClause(): Tree = {
+ val pos = accept(CASE);
+ val pat = validPattern();
+ val guard =
+ if (s.token == IF) { s.nextToken(); postfixExpr() }
+ else Tree.Empty;
+ make.CaseDef(pos, pat, guard, block(accept(ARROW)))
+ }
+
+ /** Enumerators ::= Generator {`;' Enumerator}
+ * Enumerator ::= Generator
+ * | Expr
+ */
+ def enumerators(): Array[Tree] = {
+ val enums = new TreeList();
+ enums.append(generator());
+ while (s.token == SEMI) {
+ s.nextToken();
+ if (s.token == VAL) enums.append(generator());
+ else enums.append(expr());
+ }
+ enums.toArray()
+ }
+
+ /** Generator ::= val Pattern1 `<-' Expr
+ */
+ def generator(): Tree = {
+ val pos = accept(VAL);
+ val pat = validPattern1();
+ accept(LARROW);
+ var rhs = expr();
+ if (!TreeInfo.isVarPattern(pat))
+ rhs = make.Apply(
+ rhs.pos,
+ make.Select(rhs.pos, rhs, Names.filter),
+ newTreeArray(
+ make.Visitor(
+ rhs.pos,
+ newCaseDefArray(
+ make.CaseDef(
+ rhs.pos, pat.duplicate(),
+ Tree.Empty, make.Literal(s.pos, java.lang.Boolean.TRUE)),
+ make.CaseDef(
+ rhs.pos, make.Ident(rhs.pos, Names.PATTERN_WILDCARD),
+ Tree.Empty, make.Literal(s.pos, java.lang.Boolean.FALSE))))));
+ make.PatDef(pos, 0, pat, rhs)
+ }
+
+//////// PATTERNS ////////////////////////////////////////////////////////////
+
+ /** Pattern ( see pattern() ) which is checked for validity
+ */
+ def validPattern(): Tree = {
+ val pos = s.pos;
+ val pat = pattern();
+ if (this.pN.check(pat)) { // reports syntax errors as side effect
+ // normalize
+ pN.wrapAlternative(pN.elimSequence(pN.flattenSequence(pat)))
+ } else {
+ make.Bad(pos)
+ }
+ }
+
+ /** Pattern1 ( see pattern1() ) which is checked for validity
+ */
+ def validPattern1(): Tree = {
+ val pos = s.pos;
+ val pat = pattern1();
+ if(this.pN.check(pat)) { // reports syntax errors as side effect
+ pN.wrapAlternative(pN.elimSequence(pN.flattenSequence(pat)))
+ } else {
+ make.Bad(pos)
+ }
+ }
+
+ /** Patterns ::= Pattern {`,' Pattern}
+ */
+ def patterns(): Array[Tree] = {
+ val ts = new TreeList();
+ ts.append(pattern());
+ while (s.token == COMMA) {
+ s.nextToken();
+ ts.append(pattern());
+ }
+ ts.toArray()
+ }
+
+ /** Pattern ::= Pattern1 { `|' Pattern1 }
+ */
+ def pattern(): Tree = {
+ val pos = s.pos;
+ val first = pattern1();
+ if (s.token == IDENTIFIER && s.name == BAR) {
+ val choices = new TreeList();
+ choices.append( first );
+ while (s.token == IDENTIFIER && s.name == BAR) {
+ s.nextToken();
+ choices.append(pattern1());
+ }
+ val tarr = choices.toArray();
+ val ts = pN.flattenAlternativeChildren(tarr);
+ return pN.flattenAlternative(make.Alternative(pos, ts.toArray()));
+ }
+ first
+ }
+
+ /** Pattern1 ::= varid `:' Type1
+ * | `_' `:' Type1
+ * | Pattern2
+ */
+ def pattern1(): Tree = {
+ val p = pattern2();
+ if (s.token == COLON && TreeInfo.isVarPattern(p))
+ make.Typed(s.skipToken(), p, type1())
+ else p
+ }
+
+ /* Pattern2 ::= varid [ @ Pattern3 ]
+ * | Pattern3
+ */
+ def pattern2(): Tree = {
+ val p = pattern3();
+ if (s.token == AT && TreeInfo.isVarPattern(p)) {
+ p match {
+ case Tree$Ident(name) =>
+ if (name == Names.PATTERN_WILDCARD) return pattern3()
+ }
+ make.Bind(s.skipToken(), p.asInstanceOf[Tree$Ident].name, pattern3());
+ } else {
+ p
+ }
+ }
+
+ /* Pattern3 ::= SimplePattern [ '*' | '?' | '+' ]
+ * | SimplePattern {Id SimplePattern} // op2 must not be empty
+ */
+ def pattern3(): Tree = {
+ val base = sp;
+ var top = simplePattern();
+ if (s.token == IDENTIFIER) {
+ if (s.name == STAR) { /* p* becomes z@( |(p,z)) */
+ s.nextToken();
+ val zname = fresh();
+ val zvar = make.Ident(s.pos, zname);
+ return make.Bind(
+ s.pos, zname,
+ pN.flattenAlternative(
+ make.Alternative(s.pos, newTreeArray(
+ make.Sequence(s.pos, Tree.EMPTY_ARRAY),
+ pN.flattenSequence(make.Sequence(s.pos, newTreeArray(
+ top, zvar)))))));
+ } else if (s.name == PLUS) { /* p+ becomes z@(p,(z| )) */
+ s.nextToken();
+ val zname = fresh();
+ val zvar = make.Ident(s.pos, zname);
+ return make.Bind(
+ s.pos, zname,
+ pN.flattenSequence(make.Sequence(s.pos, newTreeArray(
+ top,
+ pN.flattenAlternative(make.Alternative(s.pos, newTreeArray(
+ zvar, make.Sequence(s.pos, Tree.EMPTY_ARRAY))))))));
+ } else if (s.name == OPT) { /* p? becomes (p| ) */
+ s.nextToken();
+ return pN.flattenAlternative(make.Alternative(s.pos, newTreeArray(
+ top,
+ make.Sequence(s.pos, Tree.EMPTY_ARRAY))));
+ }
+ }
+ while ((s.token == IDENTIFIER) && (s.name != BAR)) {
+ val tokn = s.name; // for error message
+ top = reduceStack(
+ false, base, top, s.name.precedence(), s.name.isLeftAssoc());
+ push(top, s.pos, s.name);
+ ident();
+ top = simplePattern();
+ if (TreeInfo.isEmptySequence(top)) {
+ syntaxError(top.pos, "2nd argument to binary op "+ s.name + " may not be empty sequence pattern", false);
+ }
+ }
+ reduceStack(false, base, top, 0, true)
+ }
+
+ /** SimplePattern ::= varid
+ * | `_'
+ * | literal
+ * | StableId [ `(' [Patterns] `)' ]
+ * | `(' [Patterns] `)'
+ * | (word: empty - nothing)
+ */
+ def simplePattern(): Tree = s.token match {
+ case RPAREN | COMMA =>
+ make.Sequence(s.pos, Tree.EMPTY_ARRAY) // ((nothing))
+ case IDENTIFIER | THIS =>
+ if (s.name == BAR) {
+ make.Sequence(s.pos, Tree.EMPTY_ARRAY); // ((nothing))
+ } else {
+ var t = stableId();
+ while (s.token == LPAREN) {
+ var ts = Tree.EMPTY_ARRAY;
+ accept(LPAREN);
+ if (s.token != RPAREN)
+ ts = patterns();
+ accept(RPAREN);
+ t = make.Apply(s.pos, convertToTypeId(t), ts);
+ }
+ t
+ }
+ case USCORE =>
+ make.Ident(s.skipToken(), Names.PATTERN_WILDCARD)
+ case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT | STRINGLIT | SYMBOLLIT | TRUE | FALSE | NULL =>
+ literal(true)
+ case LPAREN =>
+ val p = s.pos;
+ s.nextToken();
+ val ts = if (s.token == RPAREN) Tree.EMPTY_ARRAY else patterns();
+ var t: Tree = null;
+ if (ts.length == 1 && !ts(0).isInstanceOf[Tree$Alternative]) {
+ t = ts(0);
+ } else {
+ t = pN.flattenSequence(make.Sequence(s.pos, ts));
+ t = pN.elimSequence(t);
+ }
+ accept(RPAREN);
+ t
+ case _ =>
+ syntaxError("illegal start of pattern", true)
+ }
+
+////////// MODIFIERS ////////////////////////////////////////////////////////////
+
+ /** Modifiers ::= {Modifier}
+ * Modifier ::= final
+ * | private
+ * | protected
+ * | override
+ * | abstract
+ */
+ def modifiers(): int = {
+ pushComment();
+ var mods = 0;
+ while (true) {
+ var mod = 0;
+ s.token match {
+ case ABSTRACT =>
+ mod = Modifiers.ABSTRACT;
+ case FINAL =>
+ mod = Modifiers.FINAL;
+ case SEALED =>
+ mod = Modifiers.SEALED;
+ case PRIVATE =>
+ mod = Modifiers.PRIVATE;
+ case PROTECTED =>
+ mod = Modifiers.PROTECTED;
+ case OVERRIDE =>
+ mod = Modifiers.OVERRIDE;
+ case _ =>
+ return mods;
+ }
+ if ((mods & mod) != 0)
+ syntaxError(s.pos, "repeated modifier", false);
+ mods = mods | mod;
+ s.nextToken();
+ }
+ 0 //dummy
+ }
+
+ /** LocalModifiers ::= {LocalModifier}
+ * LocalModifier ::= final
+ * | private
+ */
+ def localClassModifiers(): int = {
+ var mods = 0;
+ while (true) {
+ var mod = 0;
+ s.token match {
+ case ABSTRACT =>
+ mod = Modifiers.ABSTRACT;
+ case FINAL =>
+ mod = Modifiers.FINAL;
+ case SEALED =>
+ mod = Modifiers.SEALED;
+ case _ =>
+ return mods;
+ }
+ if ((mods & mod) != 0)
+ syntaxError(s.pos, "repeated modifier", false);
+ mods = mods | mod;
+ s.nextToken();
+ }
+ 0 //dummy
+ }
+
+//////// PARAMETERS //////////////////////////////////////////////////////////
+
+ /** ParamClauses ::= {ParamClause}
+ */
+ def paramClauses(): Array[Array[Tree$ValDef]] = {
+ val ts = new ArrayList();
+ while (s.token == LPAREN)
+ ts.add(paramClause());
+ ts.toArray(new Array[Array[Tree$ValDef]](ts.size()).asInstanceOf[Array[java.lang.Object]])
+ .asInstanceOf[Array[Array[Tree$ValDef]]]
+ }
+
+ /** ParamClauseOpt ::= [ParamClause]
+ */
+ def paramClauseOpt(): Array[Array[Tree$ValDef]] =
+ if (s.token == LPAREN) newValDefArrayArray(paramClause())
+ else Tree.ValDef_EMPTY_ARRAY_ARRAY;
+
+ /** ParamClause ::= `(' [Param {`,' Param}] `)'
+ */
+ def paramClause(): Array[Tree$ValDef] = {
+ val pos = accept(LPAREN);
+ val params = new TreeList();
+ if (s.token != RPAREN) {
+ params.append(param());
+ while (s.token == COMMA) {
+ s.nextToken();
+ params.append(param());
+ }
+ }
+ accept(RPAREN);
+ params.copyTo(new Array[Tree$ValDef](params.length()))
+ .asInstanceOf[Array[Tree$ValDef]]
+ }
+
+ /** Param ::= [def] Id `:' Type [`*']
+ */
+ def param(): Tree$ValDef = {
+ val pos = s.pos;
+ var mods = Modifiers.PARAM;
+ if (s.token == DEF) {
+ mods = mods | Modifiers.DEF;
+ s.nextToken();
+ }
+ val name = ident();
+ accept(COLON);
+ var tp = typ();
+ if (s.token == IDENTIFIER && s.name == STAR) {
+ s.nextToken();
+ mods = mods | Modifiers.REPEATED;
+ tp = make.AppliedType(
+ tp.pos,
+ scalaDot(tp.pos, Names.Seq.toTypeName()),
+ newTreeArray(tp));
+ }
+ make.ValDef(pos, mods, name, tp, Tree.Empty)
+ }
+
+ /** TypeParamClauseOpt ::= [`[' TypeParam {`,' TypeParam} `]']
+ * FunTypeParamClauseOpt ::= [`[' FunTypeParam {`,' FunTypeParam} `]']
+ */
+ def typeParamClauseOpt(variant: boolean): Array[Tree$AbsTypeDef] = {
+ val params = new TreeList();
+ if (s.token == LBRACKET) {
+ s.nextToken();
+ params.append(typeParam(variant));
+ while (s.token == COMMA) {
+ s.nextToken();
+ params.append(typeParam(variant));
+ }
+ accept(RBRACKET);
+ }
+ params.copyTo(new Array[Tree$AbsTypeDef](params.length()))
+ .asInstanceOf[Array[Tree$AbsTypeDef]];
+ }
+
+ /** TypeParam ::= [`+' | `-'] FunTypeParam
+ * FunTypeParam ::= Id TypeBounds
+ */
+ def typeParam(variant: boolean): Tree = {
+ var mods = Modifiers.PARAM;
+ if (variant && s.token == IDENTIFIER) {
+ if (s.name == PLUS) {
+ s.nextToken();
+ mods = mods | Modifiers.COVARIANT;
+ } else if (s.name == MINUS) {
+ s.nextToken();
+ mods = mods | Modifiers.CONTRAVARIANT;
+ }
+ }
+ typeBounds(s.pos, mods, ident())
+ }
+
+ /** TypeBounds ::= [`>:' Type] [`<:' Type]
+ */
+ def typeBounds(pos: int, mods: int, name: Name): Tree = {
+ val lobound =
+ if (s.token == SUPERTYPE) { s.nextToken(); typ() }
+ else scalaDot(pos, Names.All.toTypeName());
+ val hibound =
+ if (s.token == SUBTYPE) { s.nextToken(); typ() }
+ else scalaDot(pos, Names.Any.toTypeName());
+ make.AbsTypeDef(pos, mods, name.toTypeName(), hibound, lobound)
+ }
+
+//////// DEFS ////////////////////////////////////////////////////////////////
+
+ /** Import ::= import ImportExpr {`,' ImportExpr}
+ */
+ def importClause(): Array[Tree] = {
+ accept(IMPORT);
+ val ts = new TreeList();
+ ts.append(importExpr());
+ while (s.token == COMMA) {
+ s.nextToken();
+ ts.append(importExpr());
+ }
+ ts.toArray()
+ }
+
+ /** ImportRef ::= StableId `.' (Id | `_' | ImportSelectors)
+ */
+ def importExpr(): Tree = {
+ var t: Tree = null;
+ val startpos = s.pos;
+ var pos = 0;
+ if (s.token == THIS) {
+ t = make.This(s.skipToken(), TypeNames.EMPTY);
+ t = make.Select(accept(DOT), t, ident());
+ pos = accept(DOT);
+ } else {
+ val i: Tree$Ident = make.Ident(s.pos, ident());
+ pos = accept(DOT);
+ if (s.token == THIS) {
+ s.nextToken();
+ t = make.This(i.pos, i.name.toTypeName());
+ t = make.Select(accept(DOT), t, ident());
+ pos = accept(DOT);
+ } else {
+ t = i;
+ }
+ }
+ while (true) {
+ if (s.token == USCORE) {
+ s.nextToken();
+ return make.Import(startpos, t, newNameArray(Names.IMPORT_WILDCARD));
+ } else if (s.token == LBRACE) {
+ return make.Import(startpos, t, importSelectors());
+ } else {
+ val name = ident();
+ if (s.token == DOT) {
+ t = make.Select(pos, t, name);
+ pos = accept(DOT);
+ } else {
+ return make.Import(startpos, t, newNameArray(name, name));
+ }
+ }
+ }
+ null //dummy
+ }
+
+ /** ImportSelectors ::= `{' {ImportSelector `,'} (ImportSelector | `_') `}'
+ */
+ def importSelectors(): Array[Name] = {
+ val names = new LinkedList();
+ accept(LBRACE);
+ var isLast = importSelector(names);
+ while (!isLast && s.token == COMMA) {
+ s.nextToken();
+ isLast = importSelector(names);
+ }
+ accept(RBRACE);
+ names.toArray(new Array[Name](0).asInstanceOf[Array[java.lang.Object]]).asInstanceOf[Array[Name]]
+ }
+
+ /** ImportSelector ::= Id [`=>' Id | `=>' `_']
+ */
+ def importSelector(names: LinkedList/*<Name>*/): boolean =
+ if (s.token == USCORE) {
+ s.nextToken();
+ names.add(Names.IMPORT_WILDCARD);
+ true
+ } else {
+ val name = ident();
+ names.add(name);
+ if (s.token == ARROW) {
+ s.nextToken();
+ if (s.token == USCORE) {
+ s.nextToken();
+ names.add(Names.IMPORT_WILDCARD);
+ } else {
+ names.add(ident());
+ }
+ } else {
+ names.add(name);
+ }
+ false
+ }
+
+ /** Def ::= val PatDef {`,' PatDef}
+ * | var VarDef {`,' VarDef}
+ * | def FunDef {`,' FunDef}
+ * | type TypeDef {`,' TypeDef}
+ * | ClsDef
+ * Dcl ::= val ValDcl {`,' ValDcl}
+ * | var ValDcl {`,' ValDcl}
+ * | def FunDcl {`,' FunDcl}
+ * | type TypeDcl {`,' TypeDcl}
+ */
+ def defOrDcl(mods: int): Array[Tree] = {
+ val ts = new TreeList();
+ s.token match {
+ case VAL =>
+ do {
+ s.nextToken();
+ ts.append(popComment(patDefOrDcl(mods)));
+ } while (s.token == COMMA);
+ ts.toArray()
+ case VAR =>
+ do {
+ s.nextToken();
+ ts.append(popComment(varDefOrDcl(mods)));
+ } while (s.token == COMMA);
+ ts.toArray()
+ case DEF =>
+ do {
+ s.nextToken();
+ ts.append(popComment(funDefOrDcl(mods)));
+ } while (s.token == COMMA);
+ ts.toArray()
+ case TYPE =>
+ do {
+ s.nextToken();
+ ts.append(popComment(typeDefOrDcl(mods)));
+ } while (s.token == COMMA);
+ ts.toArray()
+ case _ =>
+ clsDef(mods)
+ }
+ }
+
+ /** ClsDef ::= ([case] class | trait) ClassDef {`,' ClassDef}
+ * | [case] object ObjectDef {`,' ObjectDef}
+ */
+ def clsDef(_mods: int): Array[Tree] = {
+ var mods = _mods;
+ val ts = new TreeList();
+ s.token match {
+ case CLASS | CASECLASS | TRAIT =>
+ if (s.token == CASECLASS)
+ mods = mods | Modifiers.CASE;
+ else if (s.token == TRAIT)
+ mods = mods | Modifiers.TRAIT | Modifiers.ABSTRACT;
+ do {
+ s.nextToken();
+ ts.append(classDef(mods));
+ } while (s.token == COMMA);
+ ts.toArray()
+ case OBJECT | CASEOBJECT =>
+ if (s.token == CASEOBJECT)
+ mods = mods | Modifiers.CASE;
+ do {
+ s.nextToken();
+ ts.append(objectDef(mods));
+ } while (s.token == COMMA);
+ ts.toArray()
+ case _ =>
+ newTreeArray(syntaxError("illegal start of definition", true))
+ }
+ }
+
+ /** PatDef ::= Pattern2 [`:' Type] `=' Expr
+ * ValDcl ::= Id `:' Type
+ */
+ def patDefOrDcl(mods: int): Tree = {
+ val pos = s.pos;
+ val pat = pattern2();
+ val tp = if (s.token == COLON) typedOpt() else Tree.Empty;
+ pat match {
+ case Tree$Ident(name) =>
+ if (tp == Tree.Empty || s.token == EQUALS)
+ make.ValDef(pos, mods, name, tp, equalsExpr())
+ else
+ make.ValDef(pos, mods | Modifiers.DEFERRED, name, tp, Tree.Empty)
+ case _ =>
+ make.PatDef(pos, mods, pat, equalsExpr())
+ }
+ }
+
+ /** VarDef ::= Id [`:' Type] `=' Expr
+ * | Id `:' Type `=' `_'
+ * VarDcl ::= Id `:' Type
+ */
+ def varDefOrDcl(mods: int): Tree = {
+ val pos = s.pos;
+ val name = ident();
+ val tp = typedOpt();
+ if (tp == Tree.Empty || s.token == EQUALS) {
+ accept(EQUALS);
+ val rhs =
+ if (tp != Tree.Empty && s.token == USCORE) { s.nextToken(); Tree.Empty }
+ else expr();
+ make.ValDef(pos, mods | Modifiers.MUTABLE, name, tp, rhs)
+ } else {
+ make.ValDef(pos, mods | Modifiers.MUTABLE | Modifiers.DEFERRED,
+ name, tp, Tree.Empty);
+ }
+ }
+
+ /** FunDef ::= Id [FunTypeParamClause] {ParamClauses} [`:' Type] `=' Expr
+ * | this ParamClause `=' ConstrExpr
+ * FunDcl ::= Id [FunTypeParamClause] {ParamClauses} `:' Type
+ */
+ def funDefOrDcl(mods: int): Tree = {
+ val pos = s.pos;
+ if (s.token == THIS) {
+ s.nextToken();
+ val vparams = newValDefArrayArray{paramClause()};
+ accept(EQUALS);
+ make.DefDef(
+ pos, mods, Names.CONSTRUCTOR,
+ Tree.AbsTypeDef_EMPTY_ARRAY, vparams, Tree.Empty,
+ constrExpr());
+ } else {
+ val name = ident();
+ val tparams = typeParamClauseOpt(false);
+ val vparams = paramClauses();
+ val restype = typedOpt();
+ if (s.token == EQUALS || restype == Tree.Empty)
+ make.DefDef(pos, mods, name, tparams, vparams, restype, equalsExpr());
+ else
+ make.DefDef(pos, mods | Modifiers.DEFERRED, name,
+ tparams, vparams, restype, Tree.Empty);
+ }
+ }
+
+ /** ConstrExpr ::= SelfInvocation
+ * | `{' SelfInvocation {`;' BlockStat} `}'
+ * SelfInvocation ::= this ArgumentExpr
+ */
+ def constrExpr(): Tree =
+ if (s.token == LBRACE) {
+ val pos = s.skipToken();
+ val statlist = new TreeList();
+ statlist.append(selfInvocation());
+ val stats =
+ if (s.token == SEMI) { s.nextToken(); blockStatSeq(statlist) }
+ else statlist.toArray();
+ accept(RBRACE);
+ make.Block(pos, stats)
+ } else {
+ selfInvocation()
+ }
+
+ /** SelfInvocation ::= this ArgumentExprs
+ */
+ def selfInvocation(): Tree = {
+ val pos = s.pos;
+ accept(THIS);
+ make.Apply(
+ s.pos, make.Ident(pos, Names.CONSTRUCTOR), argumentExprs());
+ }
+
+ /** TypeDef ::= Id `=' Type
+ * TypeDcl ::= Id TypeBounds
+ */
+ def typeDefOrDcl(mods: int): Tree = {
+ val pos = s.pos;
+ val name = ident().toTypeName();
+ s.token match {
+ case LBRACKET =>
+ val tparams = typeParamClauseOpt(true);
+ accept(EQUALS);
+ make.AliasTypeDef(pos, mods, name, tparams, typ())
+ case EQUALS =>
+ s.nextToken();
+ make.AliasTypeDef(pos, mods, name, Tree.AbsTypeDef_EMPTY_ARRAY, typ())
+ case SUPERTYPE | SUBTYPE | SEMI | COMMA | RBRACE =>
+ typeBounds(pos, mods | Modifiers.DEFERRED, name)
+ case _ =>
+ syntaxError("`=', `>:', or `<:' expected", true)
+ }
+ }
+
+ /** ClassDef ::= Id [TypeParamClause] [ParamClause] [`:' SimpleType] ClassTemplate
+ */
+ def classDef(mods: int): Tree = {
+ val pos = s.pos;
+ val clazzname = ident().toTypeName();
+ val tparams = typeParamClauseOpt(true);
+ val params = paramClauseOpt();
+ val result = new TreeList();
+ popComment(make.ClassDef(pos, mods, clazzname, tparams, params,
+ simpleTypedOpt(), classTemplate()))
+ }
+
+ /** ObjectDef ::= Id [`:' SimpleType] ClassTemplate
+ */
+ def objectDef(mods: int): Tree =
+ popComment(make.ModuleDef(
+ s.pos, mods, ident(), simpleTypedOpt(), classTemplate()));
+
+ /** ClassTemplate ::= [`extends' Constr] {`with' Constr} [TemplateBody]
+ */
+ def classTemplate(): Tree$Template = {
+ val pos = s.pos;
+ if (s.token == EXTENDS) {
+ s.nextToken();
+ template()
+ } else if (s.token == WITH) {
+ s.nextToken();
+ val parents = new TreeList();
+ parents.append(scalaObjectConstr(pos));
+ template(parents)
+ } else if (s.token == LBRACE) {
+ make.Template(
+ pos, newTreeArray(scalaObjectConstr(pos)), templateBody());
+ } else {
+ if (!(s.token == SEMI || s.token == COMMA || s.token == RBRACE))
+ syntaxError("`extends' or `{' expected", true);
+ make.Template(
+ pos, newTreeArray(scalaObjectConstr(pos)), Tree.EMPTY_ARRAY);
+ }
+ }
+
+////////// TEMPLATES ////////////////////////////////////////////////////////////
+
+
+ /** Template ::= Constr {`with' Constr} [TemplateBody]
+ */
+ def template(): Tree$Template =
+ template(new TreeList());
+
+ def template(parents: TreeList): Tree$Template = {
+ val pos = s.pos;
+ parents.append(constr());
+ while (s.token == WITH) {
+ s.nextToken();
+ parents.append(constr());
+ }
+ val stats = if (s.token == LBRACE) templateBody() else Tree.EMPTY_ARRAY;
+ make.Template(pos, parents.toArray(), stats)
+ }
+
+ /** Constr ::= StableId [TypeArgs] [`(' [Exprs] `)']
+ */
+ def constr(): Tree = {
+ var t: Tree = convertToConstr(stableId());
+ if (s.token == LBRACKET)
+ t = make.AppliedType(s.pos, t, typeArgs());
+ if (s.token == LPAREN)
+ t = make.Apply(s.pos, t, argumentExprs());
+ applyConstr(t)
+ }
+
+ /** TemplateBody ::= `{' [TemplateStat {`;' TemplateStat}] `}'
+ */
+ def templateBody(): Array[Tree] = {
+ accept(LBRACE);
+ var body = templateStatSeq();
+ if (body.length == 0)
+ body = newTreeArray(Tree.Empty);
+ accept(RBRACE);
+ body
+ }
+
+ /** Refinement ::= `{' [RefineStat {`;' RefineStat}] `}'
+ */
+ def refinement(): Array[Tree] = {
+ accept(LBRACE);
+ val body = refineStatSeq();
+ accept(RBRACE);
+ body
+ }
+
+/////// STATSEQS //////////////////////////////////////////////////////////////
+
+ /** Packaging ::= package QualId `{' TopStatSeq `}'
+ */
+ def packaging(): Tree = {
+ val pos = accept(PACKAGE);
+ val pkg = qualId();
+ accept(LBRACE);
+ val stats = topStatSeq();
+ accept(RBRACE);
+ make.PackageDef(pos, pkg, make.Template(pos, Tree.EMPTY_ARRAY, stats));
+ }
+
+ /** TopStatSeq ::= [TopStat {`;' TopStat}]
+ * TopStat ::= Modifiers ClsDef
+ * | Packaging
+ * | Import
+ * |
+ */
+ def topStatSeq(): Array[Tree] = {
+ val stats = new TreeList();
+ while (s.token != RBRACE && s.token != EOF) {
+ if (s.token == PACKAGE) {
+ stats.append(packaging());
+ } else if (s.token == IMPORT) {
+ stats.append(importClause());
+ } else if (s.token == CLASS ||
+ s.token == CASECLASS ||
+ s.token == TRAIT ||
+ s.token == OBJECT ||
+ s.token == CASEOBJECT ||
+ isModifier()) {
+ stats.append(clsDef(modifiers()));
+ } else if (s.token != SEMI) {
+ syntaxError("illegal start of class or object definition", true);
+ }
+ if (s.token != RBRACE && s.token != EOF) accept(SEMI);
+ }
+ stats.toArray()
+ }
+
+ /** TemplateStatSeq ::= TemplateStat {`;' TemplateStat}
+ * TemplateStat ::= Import
+ * | Modifiers Def
+ * | Modifiers Dcl
+ * | Expr
+ * |
+ */
+ def templateStatSeq(): Array[Tree] = {
+ val stats = new TreeList();
+ while (s.token != RBRACE && s.token != EOF) {
+ if (s.token == IMPORT) {
+ stats.append(importClause());
+ } else if (isExprIntro()) {
+ stats.append(expr());
+ } else if (isDefIntro() || isModifier()) {
+ stats.append(defOrDcl(modifiers()));
+ } else if (s.token != SEMI) {
+ syntaxError("illegal start of definition", true);
+ }
+ if (s.token != RBRACE) accept(SEMI);
+ }
+ stats.toArray()
+ }
+
+ /** RefineStatSeq ::= RefineStat {`;' RefineStat}
+ * RefineStat ::= Dcl
+ * | type TypeDef {`,' TypeDef}
+ * |
+ */
+ def refineStatSeq(): Array[Tree] = {
+ val stats = new TreeList();
+ while (s.token != RBRACE && s.token != EOF) {
+ if (isDclIntro()) {
+ stats.append(defOrDcl(0));
+ } else if (s.token != SEMI) {
+ syntaxError("illegal start of declaration", true);
+ }
+ if (s.token != RBRACE) accept(SEMI);
+ }
+ stats.toArray()
+ }
+
+ /** BlockStatSeq ::= { BlockStat `;' } [Expr]
+ * BlockStat ::= Import
+ * | Def
+ * | LocalModifiers ClsDef
+ * | Expr
+ * |
+ */
+ def blockStatSeq(stats: TreeList): Array[Tree] = {
+ while ((s.token != RBRACE) && (s.token != EOF) && (s.token != CASE)) {
+ if (s.token == IMPORT) {
+ stats.append(importClause());
+ accept(SEMI);
+ } else if (isExprIntro()) {
+ stats.append(expr());
+ if (s.token != RBRACE && s.token != CASE) accept(SEMI);
+ } else if (isDefIntro()) {
+ stats.append(defOrDcl(0));
+ accept(SEMI);
+ if (s.token == RBRACE || s.token == CASE) {
+ stats.append(make.Block(s.pos, Tree.EMPTY_ARRAY));
+ }
+ } else if (isLocalModifier()) {
+ stats.append(clsDef(localClassModifiers()));
+ accept(SEMI);
+ if (s.token == RBRACE || s.token == CASE) {
+ stats.append(make.Block(s.pos, Tree.EMPTY_ARRAY));
+ }
+ } else if (s.token == SEMI) {
+ s.nextToken();
+ } else {
+ syntaxError("illegal start of statement", true);
+ }
+ }
+ stats.toArray()
+ }
+
+ /** CompilationUnit ::= [ package QualId ( `;' | `{' TopStatSeq `}' ) ] TopStatSeq .
+ */
+ def compilationUnit(): Array[Tree] = {
+ if (s.token == PACKAGE) {
+ val pos = s.skipToken();
+ val pkg = qualId();
+ if (s.token == SEMI) {
+ s.nextToken();
+ newTreeArray(
+ make.PackageDef(
+ pos, pkg, make.Template(pos, Tree.EMPTY_ARRAY, topStatSeq())));
+ } else {
+ val stats = new TreeList();
+ accept(LBRACE);
+ stats.append(
+ make.PackageDef(
+ pos, pkg, make.Template(pos, Tree.EMPTY_ARRAY, topStatSeq())));
+ accept(RBRACE);
+ stats.append(topStatSeq());
+ stats.toArray()
+ }
+ } else {
+ topStatSeq()
+ }
+ }
+}
+
+
diff --git a/sources/scala/tools/scalac/ast/parser/ParserPhase.scala b/sources/scala/tools/scalac/ast/parser/ParserPhase.scala
new file mode 100644
index 0000000000..af445714c4
--- /dev/null
+++ b/sources/scala/tools/scalac/ast/parser/ParserPhase.scala
@@ -0,0 +1,25 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+\* */
+
+// $Id$
+
+package scala.tools.scalac.ast.parser;
+
+import scalac.Global;
+import scalac.Phase;
+import scalac.PhaseDescriptor;
+import scalac.Unit;
+
+class ParserPhase(global: Global, descriptor: PhaseDescriptor) extends Phase(global, descriptor) {
+
+ def apply(units: Array[Unit]): unit = {
+ for (val i <- Iterator.range(0, units.length)) do {
+ global.start();
+ units(i).body = new Parser(units(i)).parse();
+ global.stop("parsed " + units(i).source);
+ }
+ }
+}
diff --git a/sources/scala/tools/scalac/ast/parser/Scanner.scala b/sources/scala/tools/scalac/ast/parser/Scanner.scala
new file mode 100644
index 0000000000..ac3adb4d8b
--- /dev/null
+++ b/sources/scala/tools/scalac/ast/parser/Scanner.scala
@@ -0,0 +1,807 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+** **
+** $Id$
+\* */
+
+package scala.tools.scalac.ast.parser;
+
+import ch.epfl.lamp.util.Position;
+import ch.epfl.lamp.util.SourceFile;
+
+import scalac._;
+import scalac.util.Name;
+import scalac.ast.parser.SourceRepresentation;
+
+
+/** A scanner for the programming language Scala.
+ *
+ * @author Matthias Zenger, Martin Odersky
+ * @version 1.0
+ */
+class Scanner(_unit: Unit) extends TokenData {
+
+ import Tokens._;
+ import java.lang.{Integer, Long, Float, Double}
+
+ val unit = _unit;
+
+ /** buffer for the documentation comment
+ */
+ var docBuffer: StringBuffer = null;
+
+ /** add the given character to the documentation buffer
+ */
+ protected def addCharToDoc(ch: byte): unit =
+ if (docBuffer != null)
+ docBuffer.append(ch.asInstanceOf[char]);
+
+ /** layout & character constants
+ */
+ val tabinc = 8;
+ val LF = SourceFile.LF;
+ val FF = SourceFile.FF;
+ val CR = SourceFile.CR;
+ val SU = SourceFile.SU;
+
+ /** the names of all tokens
+ */
+ var tokenName = new Array[Name](128);
+ var numToken = 0;
+
+ /** keyword array; maps from name indices to tokens
+ */
+ var key: Array[byte] = _;
+ var maxKey = 0;
+
+ /** we need one token lookahead
+ */
+ val next = new TokenData(), prev = new TokenData();
+
+ /** the first character position after the previous token
+ */
+ var lastpos = 0;
+
+ /** the last error position
+ */
+ var errpos = -1;
+
+ /** the input buffer:
+ */
+ var buf: Array[byte] = unit.source.bytes();
+ var bp: int = -1;
+
+ /** the current character
+ */
+ var ch: byte = _;
+
+ /** the line and column position of the current character
+ */
+ var cline: int = 1;
+ var ccol: int = 0;
+
+ /** a buffer for character and string literals
+ */
+ var lit = new Array[byte](64);
+ var litlen: int = _;
+
+
+ /** INIT: Construct a scanner from a file input stream.
+ */
+ token = EMPTY;
+ nextch();
+ init();
+ nextToken();
+
+ def nextch(): unit = {
+ bp = bp + 1; ch = buf(bp); ccol = ccol + 1;
+ }
+
+ /** read next token and return last position
+ */
+ def skipToken(): int = {
+ val p = pos; nextToken(); p
+ }
+
+ def nextToken(): unit = {
+ if (token == RBRACE) {
+ val prevpos = pos;
+ fetchToken();
+ token match {
+ case ELSE | EXTENDS | WITH | YIELD | CATCH | FINALLY |
+ COMMA | SEMI | DOT | COLON | EQUALS | ARROW |
+ LARROW | SUBTYPE | SUPERTYPE | HASH | AT |
+ RPAREN | RBRACKET | RBRACE =>
+ case _ =>
+ if (token == EOF ||
+ ((pos >>> Position.COLUMN_BITS) >
+ (prevpos >>> Position.COLUMN_BITS))) {
+ next.copyFrom(this);
+ this.token = SEMI;
+ this.pos = prevpos;
+ }
+ }
+ } else {
+ if (next.token == EMPTY) {
+ fetchToken()
+ } else {
+ copyFrom(next);
+ next.token = EMPTY
+ }
+ if (token == CASE) {
+ prev.copyFrom(this);
+ fetchToken();
+ if (token == CLASS) {
+ token = CASECLASS;
+ } else if (token == OBJECT) {
+ token = CASEOBJECT;
+ } else {
+ next.copyFrom(this);
+ this.copyFrom(prev);
+ }
+ } else if (token == SEMI) {
+ prev.copyFrom(this);
+ fetchToken();
+ if (token != ELSE) {
+ next.copyFrom(this);
+ this.copyFrom(prev);
+ }
+ }
+ //System.out.println("<" + token2string(token) + ">");//DEBUG
+ }
+ }
+
+ /** read next token
+ */
+ private def fetchToken(): unit = {
+ if (token == EOF) return;
+ lastpos = Position.encode(cline, ccol);
+ var index = bp;
+ while (true) {
+ ch match {
+ case ' ' =>
+ nextch();
+ case '\t' =>
+ ccol = ((ccol - 1) / tabinc * tabinc) + tabinc;
+ nextch();
+ case CR =>
+ cline = cline + 1;
+ ccol = 0;
+ nextch();
+ if (ch == LF) {
+ ccol = 0;
+ nextch();
+ }
+ case LF | FF =>
+ cline = cline + 1;
+ ccol = 0;
+ nextch();
+ case _ =>
+ pos = Position.encode(cline, ccol);
+ index = bp;
+ ch match {
+ case 'A' | 'B' | 'C' | 'D' | 'E' |
+ 'F' | 'G' | 'H' | 'I' | 'J' |
+ 'K' | 'L' | 'M' | 'N' | 'O' |
+ 'P' | 'Q' | 'R' | 'S' | 'T' |
+ 'U' | 'V' | 'W' | 'X' | 'Y' |
+ 'Z' | '$' | '_' |
+ 'a' | 'b' | 'c' | 'd' | 'e' |
+ 'f' | 'g' | 'h' | 'i' | 'j' |
+ 'k' | 'l' | 'm' | 'n' | 'o' |
+ 'p' | 'q' | 'r' | 's' | 't' |
+ 'u' | 'v' | 'w' | 'x' | 'y' | // scala-mode: need to understand multi-line case patterns
+ 'z' =>
+ nextch();
+ getIdentRest(index); // scala-mode: wrong indent for multi-line case blocks
+ return;
+ case '~' | '!' | '@' | '#' | '%' |
+ '^' | '*' | '+' | '-' | '<' |
+ '>' | '?' | ':' |
+ '=' | '&' | '|' =>
+ nextch();
+ getOperatorRest(index);
+ return;
+ case '\\' =>
+ nextch();
+ if (ch == '"') { //"
+ getStringLit();
+ token = IDENTIFIER;
+ } else
+ syntaxError(pos, "illegal character");
+ return;
+ case '/' =>
+ nextch();
+ if (!skipComment()) {
+ getOperatorRest(index);
+ return;
+ }
+ case '0' =>
+ nextch();
+ if (ch == 'x' || ch == 'X') {
+ nextch();
+ getNumber(index + 2, 16);
+ } else {
+ getNumber(index, 8);
+ }
+ return; // scala-mode: return is a keyword
+ case '1' | '2' | '3' | '4' |
+ '5' | '6' | '7' | '8' | '9' =>
+ getNumber(index, 10);
+ return;
+ case '\"' => //" scala-mode: need to understand literals
+ getStringLit();
+ return;
+ case '\'' =>
+ nextch();
+ litlen = 0;
+ ch match {
+ case 'A' | 'B' | 'C' | 'D' | 'E' |
+ 'F' | 'G' | 'H' | 'I' | 'J' |
+ 'K' | 'L' | 'M' | 'N' | 'O' |
+ 'P' | 'Q' | 'R' | 'S' | 'T' |
+ 'U' | 'V' | 'W' | 'X' | 'Y' |
+ 'Z' | '$' | '_' |
+ 'a' | 'b' | 'c' | 'd' | 'e' |
+ 'f' | 'g' | 'h' | 'i' | 'j' |
+ 'k' | 'l' | 'm' | 'n' | 'o' |
+ 'p' | 'q' | 'r' | 's' | 't' |
+ 'u' | 'v' | 'w' | 'x' | 'y' |
+ 'z' =>
+ putch(ch);
+ nextch();
+ if (ch != '\'') {
+ getIdentRest(index);
+ token = SYMBOLLIT;
+ return;
+ }
+ case _ =>
+ getlitch();
+ }
+ if (ch == '\'') {
+ nextch();
+ token = CHARLIT;
+ val ascii = new Array[byte](litlen * 2);
+ val alen = SourceRepresentation.source2ascii(lit, 0, litlen, ascii);
+ if (alen > 0)
+ intVal = SourceRepresentation.ascii2string(ascii, 0, alen).charAt(0);
+ else
+ intVal = 0;
+ } else {
+ syntaxError("unclosed character literal");
+ }
+ return;
+ case '.' =>
+ nextch();
+ if (('0' <= ch) && (ch <= '9')) getFraction(index);
+ else token = DOT;
+ return;
+ case ';' =>
+ nextch(); token = SEMI;
+ return;
+ case ',' =>
+ nextch(); token = COMMA;
+ return;
+ case '(' => //scala-mode: need to understand character quotes
+ nextch(); token = LPAREN;
+ return;
+ case '{' =>
+ nextch(); token = LBRACE;
+ return;
+ case ')' =>
+ nextch(); token = RPAREN;
+ return;
+ case '}' =>
+ nextch(); token = RBRACE;
+ return;
+ case '[' =>
+ nextch(); token = LBRACKET;
+ return;
+ case ']' =>
+ nextch(); token = RBRACKET;
+ return;
+ case SU =>
+ token = EOF;
+ return;
+ case _ =>
+ nextch();
+ syntaxError("illegal character");
+ return;
+ }
+ }
+ }
+ }
+
+ private def skipComment(): boolean = {
+ if (ch == '/') {
+ do {
+ nextch();
+ } while ((ch != CR) && (ch != LF) && (ch != SU));
+ true
+ } else if (ch == '*') {
+ docBuffer = null;
+ var openComments = 1;
+ nextch();
+ if (ch == '*') {
+ docBuffer = new StringBuffer("/**");
+ }
+ while (openComments > 0) {
+ do {
+ do {
+ if (ch == CR) {
+ cline = cline + 1;
+ ccol = 0;
+ nextch(); addCharToDoc(ch);
+ if (ch == LF) {
+ ccol = 0;
+ nextch(); addCharToDoc(ch);
+ }
+ } else if (ch == LF) {
+ cline = cline + 1;
+ ccol = 0;
+ nextch(); addCharToDoc(ch);
+ } else if (ch == '\t') {
+ ccol = ((ccol - 1) / tabinc * tabinc) + tabinc;
+ nextch(); addCharToDoc(ch);
+ } else if (ch == '/') {
+ nextch(); addCharToDoc(ch);
+ if (ch == '*') {
+ nextch(); addCharToDoc(ch);
+ openComments = openComments + 1;
+ }
+ } else {
+ nextch(); addCharToDoc(ch);
+ }
+ } while ((ch != '*') && (ch != SU));
+ while (ch == '*') {
+ nextch(); addCharToDoc(ch);
+ }
+ } while (ch != '/' && ch != SU);
+ if (ch == '/') {
+ nextch();
+ openComments = openComments - 1;
+ } else {
+ syntaxError("unclosed comment");
+ true;
+ }
+ }
+ true
+ } else {
+ false
+ }
+ }
+
+ private def getIdentRest(index: int): unit = {
+ while (true) {
+ ch match {
+ case 'A' | 'B' | 'C' | 'D' | 'E' |
+ 'F' | 'G' | 'H' | 'I' | 'J' |
+ 'K' | 'L' | 'M' | 'N' | 'O' |
+ 'P' | 'Q' | 'R' | 'S' | 'T' |
+ 'U' | 'V' | 'W' | 'X' | 'Y' |
+ 'Z' | '$' |
+ 'a' | 'b' | 'c' | 'd' | 'e' |
+ 'f' | 'g' | 'h' | 'i' | 'j' |
+ 'k' | 'l' | 'm' | 'n' | 'o' |
+ 'p' | 'q' | 'r' | 's' | 't' |
+ 'u' | 'v' | 'w' | 'x' | 'y' |
+ 'z' |
+ '0' | '1' | '2' | '3' | '4' |
+ '5' | '6' | '7' | '8' | '9' =>
+ nextch();
+ case '_' =>
+ nextch();
+ getIdentOrOperatorRest(index);
+ return;
+ case _ =>
+ treatIdent(index, bp);
+ return;
+ }
+ }
+ }
+
+ private def getOperatorRest(index: int): unit = {
+ while (true) {
+ ch match {
+ case '~' | '!' | '@' | '#' | '%' |
+ '^' | '*' | '+' | '-' | '<' |
+ '>' | '?' | ':' | '=' | '&' | '|' =>
+ nextch();
+ case '/' =>
+ val lastbp = bp;
+ nextch();
+ if (skipComment()) {
+ treatIdent(index, lastbp);
+ return;
+ }
+ case _ =>
+ treatIdent(index, bp);
+ return;
+ }
+ }
+ }
+
+ private def getIdentOrOperatorRest(index: int): unit = {
+ ch match {
+ case 'A' | 'B' | 'C' | 'D' | 'E' |
+ 'F' | 'G' | 'H' | 'I' | 'J' |
+ 'K' | 'L' | 'M' | 'N' | 'O' |
+ 'P' | 'Q' | 'R' | 'S' | 'T' |
+ 'U' | 'V' | 'W' | 'X' | 'Y' |
+ 'Z' | '$' | '_' |
+ 'a' | 'b' | 'c' | 'd' | 'e' |
+ 'f' | 'g' | 'h' | 'i' | 'j' |
+ 'k' | 'l' | 'm' | 'n' | 'o' |
+ 'p' | 'q' | 'r' | 's' | 't' |
+ 'u' | 'v' | 'w' | 'x' | 'y' |
+ 'z' |
+ '0' | '1' | '2' | '3' | '4' |
+ '5' | '6' | '7' | '8' | '9' =>
+ getIdentRest(index);
+ case '~' | '!' | '@' | '#' | '%' |
+ '^' | '*' | '+' | '-' | '<' |
+ '>' | '?' | ':' |
+ '=' | '&' | '|' | '/' =>
+ getOperatorRest(index);
+ case _ =>
+ treatIdent(index, bp);
+ }
+ }
+
+ private def getStringLit(): unit = {
+ nextch();
+ litlen = 0;
+ while (ch != '\"'/*"*/ && ch != CR && ch != LF && ch != SU)
+ getlitch();
+ if (ch == '\"'/*"*/) {
+ token = STRINGLIT;
+ name = Name.fromSource(lit, 0, litlen);
+ nextch();
+ } else {
+ syntaxError("unclosed character literal");
+ }
+ }
+
+ /** returns true if argument corresponds to a keyword.
+ * Used in dtd2scala tool.
+ */
+ def isKeyword(str: String) = Name.fromString(str).index <= maxKey;
+
+ def treatIdent(start: int, end: int) = {
+ name = Name.fromAscii(buf, start, end - start);
+ token = if (name.index <= maxKey) key(name.index) else IDENTIFIER;
+ }
+
+ /** generate an error at the given position
+ */
+ def syntaxError(pos: int, msg: String) = {
+ unit.error(pos, msg);
+ token = ERROR;
+ errpos = pos;
+ }
+
+ /** generate an error at the current token position
+ */
+ def syntaxError(msg: String): unit = syntaxError(pos, msg);
+
+ /** append characteter to "lit" buffer
+ */
+ protected def putch(c: byte) = {
+ if (litlen == lit.length) {
+ val newlit = new Array[byte](lit.length * 2);
+ System.arraycopy(lit, 0, newlit, 0, lit.length);
+ lit = newlit;
+ }
+ lit(litlen) = c;
+ litlen = litlen + 1;
+ }
+
+ /** return true iff next 6 characters are a valid unicode sequence:
+ */
+ protected def isUnicode() =
+ (bp + 6) < buf.length &&
+ (buf(bp) == '\\') &&
+ (buf(bp+1) == 'u') &&
+ (SourceRepresentation.digit2int(buf(bp+2), 16) >= 0) &&
+ (SourceRepresentation.digit2int(buf(bp+3), 16) >= 0) &&
+ (SourceRepresentation.digit2int(buf(bp+4), 16) >= 0) &&
+ (SourceRepresentation.digit2int(buf(bp+5), 16) >= 0);
+
+ /** read next character in character or string literal:
+ */
+ protected def getlitch() =
+ if (ch == '\\') {
+ if (isUnicode()) {
+ putch(ch); nextch();
+ putch(ch); nextch();
+ putch(ch); nextch();
+ putch(ch); nextch();
+ putch(ch); nextch();
+ putch(ch); nextch();
+ } else {
+ nextch();
+ if ('0' <= ch && ch <= '7') {
+ val leadch: byte = ch;
+ var oct: int = SourceRepresentation.digit2int(ch, 8);
+ nextch();
+ if ('0' <= ch && ch <= '7') {
+ oct = oct * 8 + SourceRepresentation.digit2int(ch, 8);
+ nextch();
+ if (leadch <= '3' && '0' <= ch && ch <= '7') {
+ oct = oct * 8 + SourceRepresentation.digit2int(ch, 8);
+ nextch();
+ }
+ }
+ putch(oct.asInstanceOf[byte]);
+ } else if (ch != SU) {
+ ch match {
+ case 'b' | 't' | 'n' | 'f' | 'r' | '\"' /*"*/ | '\'' | '\\' =>
+ putch('\\'.asInstanceOf[byte]);
+ putch(ch);
+ case _ =>
+ syntaxError(Position.encode(cline, ccol) - 1, "invalid escape character");
+ putch(ch);
+ }
+ nextch();
+ }
+ }
+ } else if (ch != SU) {
+ putch(ch);
+ nextch();
+ }
+
+ /** read fractional part of floating point number;
+ * Then floatVal := buf[index..], converted to a floating point number.
+ */
+ protected def getFraction(index: int) = {
+ while (SourceRepresentation.digit2int(ch, 10) >= 0) {
+ nextch();
+ }
+ token = DOUBLELIT;
+ if ((ch == 'e') || (ch == 'E')) {
+ nextch();
+ if ((ch == '+') || (ch == '-')) {
+ val sign: byte = ch;
+ nextch();
+ if (('0' > ch) || (ch > '9')) {
+ ch = sign;
+ bp = bp - 1;
+ ccol = ccol - 1;
+ }
+ }
+ while (SourceRepresentation.digit2int(ch, 10) >= 0) {
+ nextch();
+ }
+ }
+ var limit = Double.MAX_VALUE;
+ if ((ch == 'd') || (ch == 'D')) {
+ nextch();
+ } else if ((ch == 'f') || (ch == 'F')) {
+ token = FLOATLIT;
+ limit = Float.MAX_VALUE;
+ nextch();
+ }
+ try {
+ floatVal = Double.valueOf(new String(buf, index, bp - index)).doubleValue();
+ if (floatVal > limit)
+ syntaxError("floating point number too large");
+ } catch {
+ case _: NumberFormatException =>
+ syntaxError("malformed floating point number");
+ }
+ }
+
+ /** intVal := buf(index..index+len-1), converted to an integer number.
+ * base = the base of the number; one of 8, 10, 16.
+ * max = the maximal number before an overflow.
+ */
+ protected def makeInt (index: int, len: int, base: int, max: long): unit = {
+ intVal = 0;
+ val divider = if (base == 10) 1 else 2;
+ var i = 0;
+ while (i < len) {
+ val d = SourceRepresentation.digit2int(buf(index + i), base);
+ if (d < 0) {
+ syntaxError("malformed integer number");
+ return;
+ }
+ if (intVal < 0 ||
+ max / (base / divider) < intVal ||
+ max - (d / divider) < (intVal * (base / divider) - 0)) {
+ syntaxError("integer number too large");
+ return;
+ }
+ intVal = intVal * base + d;
+ i = i + 1;
+ }
+ }
+
+ /** read a number,
+ * and convert buf[index..], setting either intVal or floatVal.
+ * base = the base of the number; one of 8, 10, 16.
+ */
+ protected def getNumber(index: int, base: int) = {
+ while (SourceRepresentation.digit2int(ch, if (base == 8) 10 else base) >= 0) {
+ nextch();
+ }
+ if (base <= 10 && ch == '.') {
+ nextch();
+ if ((ch >= '0') && (ch <= '9'))
+ getFraction(index);
+ else {
+ bp = bp - 1;
+ ch = buf(bp);
+ ccol = ccol - 1;
+ makeInt(index, bp - index, base, Integer.MAX_VALUE);
+ intVal = intVal.asInstanceOf[int];
+ token = INTLIT;
+ }
+ } else if (base <= 10 &&
+ (ch == 'e' || ch == 'E' ||
+ ch == 'f' || ch == 'F' ||
+ ch == 'd' || ch == 'D')) {
+ getFraction(index);
+ } else {
+ if (ch == 'l' || ch == 'L') {
+ makeInt(index, bp - index, base, Long.MAX_VALUE);
+ nextch();
+ token = LONGLIT;
+ } else {
+ makeInt(index, bp - index, base, Integer.MAX_VALUE);
+ intVal = intVal.asInstanceOf[int];
+ token = INTLIT;
+ }
+ }
+ }
+
+ def name2token(name: Name): int =
+ if (name.index <= maxKey) key(name.index) else IDENTIFIER;
+
+ def token2string(token: int): String = token match {
+ case IDENTIFIER =>
+ "identifier"
+ case CHARLIT =>
+ "character literal"
+ case INTLIT =>
+ "integer literal"
+ case LONGLIT =>
+ "long literal"
+ case FLOATLIT =>
+ "float literal"
+ case DOUBLELIT =>
+ "double literal"
+ case STRINGLIT =>
+ "string literal"
+ case SYMBOLLIT =>
+ "symbol literal"
+ case LPAREN =>
+ "'('"
+ case RPAREN =>
+ "')'"
+ case LBRACE =>
+ "'{'"
+ case RBRACE =>
+ "'}'"
+ case LBRACKET =>
+ "'['"
+ case RBRACKET =>
+ "']'"
+ case EOF =>
+ "eof"
+ case ERROR =>
+ "something"
+ case SEMI =>
+ "''"
+ case COMMA =>
+ "','"
+ case CASECLASS =>
+ "case class"
+ case CASEOBJECT =>
+ "case object"
+ case _ =>
+ try {
+ "'" + tokenName(token).toString() + "'"
+ } catch {
+ case _: ArrayIndexOutOfBoundsException =>
+ "'<" + token + ">'"
+ case _: NullPointerException =>
+ "'<(" + token + ")>'"
+ }
+ }
+
+ override def toString() = token match {
+ case IDENTIFIER =>
+ "id(" + name + ")"
+ case CHARLIT =>
+ "char(" + intVal + ")"
+ case INTLIT =>
+ "int(" + intVal + ")"
+ case LONGLIT =>
+ "long(" + intVal + ")"
+ case FLOATLIT =>
+ "float(" + floatVal + ")"
+ case DOUBLELIT =>
+ "double(" + floatVal + ")"
+ case STRINGLIT =>
+ "string(" + name + ")"
+ case SEMI =>
+ ";"
+ case COMMA =>
+ ","
+ case _ =>
+ token2string(token)
+ }
+
+ protected def enterKeyword(s: String, tokenId: int) = {
+ while (tokenId > tokenName.length) {
+ val newTokName = new Array[Name](tokenName.length * 2);
+ System.arraycopy(tokenName, 0, newTokName, 0, newTokName.length);
+ tokenName = newTokName;
+ }
+ val n = Name.fromString(s);
+ tokenName(tokenId) = n;
+ if (n.index > maxKey) maxKey = n.index;
+ if (tokenId >= numToken) numToken = tokenId + 1;
+ }
+
+ protected def init() = {
+ initKeywords();
+ key = new Array[byte](maxKey+1);
+ for (val i <- Iterator.range(0, maxKey)) do
+ key(i) = IDENTIFIER;
+ for (val j <- Iterator.range(0, numToken)) do
+ if (tokenName(j) != null) key(tokenName(j).index) = j.asInstanceOf[byte];
+ }
+
+ protected def initKeywords() = {
+ enterKeyword("abstract", ABSTRACT);
+ enterKeyword("case", CASE);
+ enterKeyword("class", CLASS);
+ enterKeyword("catch", CATCH);
+ enterKeyword("def", DEF);
+ enterKeyword("do", DO);
+ enterKeyword("else", ELSE);
+ enterKeyword("extends", EXTENDS);
+ enterKeyword("false", FALSE);
+ enterKeyword("final", FINAL);
+ enterKeyword("finally", FINALLY);
+ enterKeyword("for", FOR);
+ enterKeyword("if", IF);
+ enterKeyword("import", IMPORT);
+ enterKeyword("new", NEW);
+ enterKeyword("null", NULL);
+ enterKeyword("object", OBJECT);
+ enterKeyword("override", OVERRIDE);
+ enterKeyword("package", PACKAGE);
+ enterKeyword("private", PRIVATE);
+ enterKeyword("protected", PROTECTED);
+ enterKeyword("return", RETURN);
+ enterKeyword("sealed", SEALED);
+ enterKeyword("super", SUPER);
+ enterKeyword("this", THIS);
+ enterKeyword("throw", THROW);
+ enterKeyword("trait", TRAIT);
+ enterKeyword("true", TRUE);
+ enterKeyword("try", TRY);
+ enterKeyword("type", TYPE);
+ enterKeyword("val", VAL);
+ enterKeyword("var", VAR);
+ enterKeyword("with", WITH);
+ enterKeyword("while", WHILE);
+ enterKeyword("yield", YIELD);
+ enterKeyword(".", DOT);
+ enterKeyword("_", USCORE);
+ enterKeyword(":", COLON);
+ enterKeyword("=", EQUALS);
+ enterKeyword("=>", ARROW);
+ enterKeyword("<-", LARROW);
+ enterKeyword("<:", SUBTYPE);
+ enterKeyword(">:", SUPERTYPE);
+ enterKeyword("#", HASH);
+ enterKeyword("@", AT);
+ }
+}
+
+
diff --git a/sources/scala/tools/scalac/ast/parser/TokenData.scala b/sources/scala/tools/scalac/ast/parser/TokenData.scala
new file mode 100644
index 0000000000..65ed04e34c
--- /dev/null
+++ b/sources/scala/tools/scalac/ast/parser/TokenData.scala
@@ -0,0 +1,46 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+** **
+** $Id$
+\* */
+
+package scala.tools.scalac.ast.parser;
+
+import scalac.util.Name;
+
+/** A class for representing a token's data.
+ *
+ * @author Matthias Zenger
+ * @version 1.0
+ */
+class TokenData {
+
+ import Tokens._;
+
+ /** the next token
+ */
+ var token: int = EMPTY;
+
+ /** the token's position. pos = line << Position.LINESHIFT + col
+ */
+ var pos: int = 0;
+
+ /** the name of an identifier or token
+ */
+ var name: Name = null;
+
+ /** the value of a number
+ */
+ var intVal: long = 0;
+ var floatVal: double = 0;
+
+ def copyFrom(td: TokenData) = {
+ this.token = td.token;
+ this.pos = td.pos;
+ this.name = td.name;
+ this.intVal = td.intVal;
+ this.floatVal = td.floatVal;
+ }
+}
diff --git a/sources/scala/tools/scalac/ast/parser/Tokens.scala b/sources/scala/tools/scalac/ast/parser/Tokens.scala
new file mode 100644
index 0000000000..76d5732ed8
--- /dev/null
+++ b/sources/scala/tools/scalac/ast/parser/Tokens.scala
@@ -0,0 +1,92 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+** **
+** $Id$
+\* */
+
+package scala.tools.scalac.ast.parser;
+
+object Tokens {
+ val EMPTY = -3,
+ UNDEF = -2,
+ ERROR = -1,
+ EOF = 0,
+
+ /* literals */
+ CHARLIT = 1,
+ INTLIT = 2,
+ LONGLIT = 3,
+ FLOATLIT = 4,
+ DOUBLELIT = 5,
+ STRINGLIT = 6,
+ SYMBOLLIT = 7,
+
+ /* identifier */
+ IDENTIFIER = 10,
+
+ /* keywords */
+ IF = 20,
+ FOR = 21,
+ ELSE = 22,
+ THIS = 23,
+ NULL = 24,
+ NEW = 25,
+ WITH = 26,
+ SUPER = 27,
+ CASE = 28,
+ CASECLASS = 29,
+ CASEOBJECT = 30,
+ VAL = 31,
+ ABSTRACT = 32,
+ FINAL = 33,
+ PRIVATE = 34,
+ PROTECTED = 35,
+ OVERRIDE = 36,
+ VAR = 37,
+ DEF = 38,
+ TYPE = 39,
+ EXTENDS = 40,
+ TRUE = 41,
+ FALSE = 42,
+ OBJECT = 43,
+ CLASS = 44,
+
+ IMPORT = 46,
+ PACKAGE = 47,
+ YIELD = 48,
+ DO = 49,
+ TRAIT = 50,
+ SEALED = 51,
+ THROW = 52,
+ TRY = 53,
+ CATCH = 54,
+ FINALLY = 55,
+ WHILE = 56,
+ RETURN = 57,
+
+ /* special symbols */
+ COMMA = 61,
+ SEMI = 62,
+ DOT = 63,
+ USCORE = 64,
+ COLON = 65,
+ EQUALS = 66,
+ LARROW = 67,
+ ARROW = 68,
+ SUBTYPE = 69,
+ SUPERTYPE = 70,
+ HASH = 71,
+ AT = 72,
+
+ /* parenthesis */
+ LPAREN = 90,
+ RPAREN = 91,
+ LBRACKET = 92,
+ RBRACKET = 93,
+ LBRACE = 94,
+ RBRACE = 95;
+}
+
+
diff --git a/sources/scala/tools/scalac/ast/printer/HTMLPrinter.scala b/sources/scala/tools/scalac/ast/printer/HTMLPrinter.scala
new file mode 100644
index 0000000000..2373c10e8e
--- /dev/null
+++ b/sources/scala/tools/scalac/ast/printer/HTMLPrinter.scala
@@ -0,0 +1,167 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+** **
+\* */
+
+// $Id$
+
+package scala.tools.scalac.ast.printer;
+
+import scalac.Unit;
+import scalac.symtab.Symbol;
+
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.lang.Math;
+import java.util.HashMap;
+import scalac.ast.Tree;
+
+/**
+ * HTML pretty printer for Scala abstract syntax trees.
+ *
+ * @author Michel Schinz
+ * @version 1.0
+ */
+
+class HTMLTreePrinter(stream: OutputStream) extends TextTreePrinter(stream) {
+ protected var outSectionLevel = 1;
+ protected var started = false;
+
+ override def begin(): unit = {
+ assert(!started);
+
+ super.begin();
+ out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
+ out.println("<html>");
+ out.println("<head>");
+ out.println("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\">");
+ out.println("<link rel=\"stylesheet\" href=\"scala.css\" type=\"text/css\">");
+ out.println("<title>Scala tree</title>");
+ out.println("</head>");
+ out.println("<body>");
+
+ started = true;
+ }
+
+ override def end(): unit = {
+ assert(started);
+
+ out.println("</body>");
+ out.println("</html>");
+ super.end();
+
+ started = false;
+ }
+
+ override def beginSection(level: int, title: String) = {
+ outSectionLevel = Math.min(level, 4);
+ beginSection1(outSectionLevel, title);
+ }
+
+ protected def beginSection1(level: int, title: String): unit = {
+ if (level == 1)
+ out.println("<hr/>");
+ val tag: String = "h" + level;
+ startTag(tag);
+ print(Simple(title));
+ endTag(tag);
+ }
+
+ protected def startTag(tag: String): unit = {
+ out.print('<'); out.print(tag); out.print('>');
+ }
+
+ protected def startTag(tag: String, attr1: String, val1: String): unit = {
+ out.print('<');
+ out.print(tag);
+ out.print(' ');
+ out.print(attr1);
+ out.print("=\"");
+ out.print(val1);
+ out.print("\">");
+ }
+
+ protected def endTag(tag: String): unit = {
+ out.print("</"); out.print(tag); out.print(">");
+ }
+
+ protected def startSpan(cls: String): unit = {
+ startTag("span", "class", cls);
+ }
+
+ protected def endSpan(): unit = {
+ endTag("span");
+ }
+
+ override protected def printString(str: String): unit = {
+ for (val i <- Iterator.range(0, str.length())) do {
+ val c = str.charAt(i);
+ val entity: String = c match {
+ case '<' => "lt";
+ case '>' => "gt";
+ case '&' => "amp";
+ case _ => null
+ }
+ if (entity != null) {
+ out.print('&');
+ out.print(entity);
+ out.print(';');
+ } else {
+ out.print(c);
+ }
+ }
+ }
+
+ protected val symAnchors = new HashMap/*<Symbol,Integer>*/();
+
+ protected def symbolAnchor(sym: Symbol, usage: SymbolUsage): String = {
+ var anchorId = symAnchors.get(sym).asInstanceOf[Integer];
+ if (anchorId == null) {
+ anchorId = new Integer(symAnchors.size());
+ symAnchors.put(sym, anchorId);
+ }
+ if (usage == Definition)
+ return anchorId.toString();
+ else
+ return "#" + anchorId.toString();
+ }
+
+ override protected def print(text: Text): unit = text match {
+ case Keyword(name) =>
+ startSpan("kw");
+ printString(name);
+ endSpan();
+ case Literal(str) =>
+ startSpan("lit");
+ printString(str);
+ endSpan();
+ case Identifier(symbol, name, usage) =>
+ val defined = (usage == Definition);
+ if (defined) startSpan("idDef");
+ if (symbol != null) {
+ val attr = if (defined) "name" else "href";
+ startTag("a", attr, symbolAnchor(symbol, usage));
+ }
+ printString(name);
+ if (symbol != null)
+ endTag("a");
+ if (defined) endSpan();
+ case _ =>
+ super.print(text);
+ }
+
+ override def print(unit: Unit) = super.print(unit);
+ override def print(str: String) = super.print(str);
+ override def print(tree: Tree) = super.print(tree);
+
+ override protected def printUnitHeader(unit: Unit): unit = {
+ beginSection1(outSectionLevel + 1, unit.source.toString());
+ startTag("pre");
+ }
+
+ override protected def printUnitFooter(unit: Unit): unit = {
+ endTag("pre");
+ }
+}
diff --git a/sources/scala/tools/scalac/ast/printer/TextTreePrinter.scala b/sources/scala/tools/scalac/ast/printer/TextTreePrinter.scala
new file mode 100644
index 0000000000..28ff80c93a
--- /dev/null
+++ b/sources/scala/tools/scalac/ast/printer/TextTreePrinter.scala
@@ -0,0 +1,667 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+** **
+\* */
+
+// $Id$
+
+package scala.tools.scalac.ast.printer;
+
+import scalac.ast.printer._;
+import scalac.ast._;
+import scalac.symtab._;
+import scalac.util.Debug;
+import scalac.Global;
+import scalac.Unit;
+import scalac.util.Name;
+import scalac.util.TypeNames;
+
+import java.io._;
+
+/**
+ * Text pretty printer for Scala abstract syntax trees.
+ *
+ * @author Michel Schinz, Matthias Zenger
+ * @version 1.0
+ */
+class TextTreePrinter(_out: PrintWriter, autoFlush: boolean) with TreePrinter {
+
+ val out = _out;
+
+ def this(stream: OutputStream, autoFlush: boolean) =
+ this(new PrintWriter(stream), autoFlush);
+
+ def this(stream: OutputStream) = this(stream, false);
+
+ def this(stream: Writer, autoFlush: boolean) =
+ this(new PrintWriter(stream), autoFlush);
+
+ def this(stream: Writer) = this(stream, false);
+
+ def this() = this(System.out);
+
+ protected var indentMargin = 0;
+ protected val INDENT_STEP = 2;
+ protected var INDENT_STRING =
+ " ";
+ protected val MAX_INDENT = INDENT_STRING.length();
+
+ def begin() = ();
+ def end() = flush();
+ def flush() = out.flush();
+
+ def print(str: String) = {
+ out.print(str);
+ if (autoFlush) flush();
+ this
+ }
+
+ def println() = {
+ out.println();
+ if (autoFlush) flush();
+ this
+ }
+
+ def beginSection(level: int, title: String) = {
+ out.println("[[" + title + "]]");
+ flush();
+ }
+
+ protected def indent() = {
+ indentMargin = indentMargin + Math.min(MAX_INDENT, INDENT_STEP);
+ }
+
+ protected def undent() = {
+ indentMargin = indentMargin - Math.max(0, INDENT_STEP);
+ }
+
+ protected def printString(str: String) = {
+ out.print(str);
+ if (autoFlush) flush();
+ }
+
+ protected def printNewLine() = {
+ out.println();
+ while (indentMargin > INDENT_STRING.length()) {
+ INDENT_STRING = INDENT_STRING + INDENT_STRING;
+ }
+ if (indentMargin > 0)
+ out.write(INDENT_STRING, 0, indentMargin);
+ if (autoFlush) flush();
+ }
+
+ abstract class Text;
+ case object None extends Text;
+ case object Space extends Text;
+ case object Newline extends Text;
+ case class Simple(str: String) extends Text;
+ case class Literal(str: String) extends Text;
+ case class Keyword(name: String) extends Text;
+ case class Identifier(symbol: Symbol, name: String, usage: SymbolUsage)
+ extends Text;
+ case class Sequence(elements: List[Text]) extends Text;
+
+ abstract class SymbolUsage;
+ case object Definition extends SymbolUsage;
+ case object Use extends SymbolUsage;
+
+ protected def print(text: Text): unit = text match {
+ case None => ;
+ case Space => printString(" ")
+ case Newline => printNewLine()
+ case Simple(str) => printString(str)
+ case Literal(str) => printString(str)
+ case Keyword(name) => printString(name)
+ case Identifier(sym, name, _) =>
+ printString(name);
+ if (sym != null && Global.instance.uniqid)
+ printString("#" + Global.instance.uniqueID.id(sym))
+ case Sequence(elements) => print(elements)
+ }
+
+ protected def print(texts: List[Text]): unit =
+ for (val text <- texts) do print(text);
+
+ protected final val KW_ABSTRACT = Keyword("abstract");
+ protected final val KW_CASE = Keyword("case");
+ protected final val KW_CLASS = Keyword("class");
+ protected final val KW_DEF = Keyword("def");
+ protected final val KW_DO = Keyword("do");
+ protected final val KW_ELSE = Keyword("else");
+ protected final val KW_EXTENDS = Keyword("extends");
+ protected final val KW_FINAL = Keyword("final");
+ protected final val KW_SEALED = Keyword("sealed");
+ protected final val KW_FOR = Keyword("for");
+ protected final val KW_IF = Keyword("if");
+ protected final val KW_IMPORT = Keyword("import");
+ protected final val KW_INTERFACE = Keyword("interface");
+ protected final val KW_OBJECT = Keyword("object");
+ protected final val KW_NEW = Keyword("new");
+ protected final val KW_NULL = Keyword("null");
+ protected final val KW_OUTER = Keyword("outer");
+ protected final val KW_OVERRIDE = Keyword("override");
+ protected final val KW_PACKAGE = Keyword("package");
+ protected final val KW_PRIVATE = Keyword("private");
+ protected final val KW_PROTECTED = Keyword("protected");
+ protected final val KW_RETURN = Keyword("return");
+ protected final val KW_STATIC = Keyword("static");
+ protected final val KW_SUPER = Keyword("super");
+ protected final val KW_THIS = Keyword("this");
+ protected final val KW_TYPE = Keyword("type");
+ protected final val KW_VAL = Keyword("val");
+ protected final val KW_VAR = Keyword("var");
+ protected final val KW_WITH = Keyword("with");
+ protected final val KW_YIELD = Keyword("yield");
+
+ protected final val TXT_ERROR = Simple("<error>");
+ protected final val TXT_UNKNOWN = Simple("<unknown>");
+ protected final val TXT_NULL = Simple("<null>");
+ protected final val TXT_OBJECT_COMMENT = Simple("/*object*/ ");
+ protected final val TXT_EMPTY = Simple("<empty>");
+
+ protected final val TXT_QUOTE = Simple("\"");
+ protected final val TXT_PLUS = Simple("+");
+ protected final val TXT_COLON = Simple(":");
+ protected final val TXT_SEMICOLON = Simple(";");
+ protected final val TXT_DOT = Simple(".");
+ protected final val TXT_COMMA = Simple(",");
+ protected final val TXT_EQUAL = Simple("=");
+ protected final val TXT_SUPERTYPE = Simple(">:");
+ protected final val TXT_SUBTYPE = Simple("<:");
+ protected final val TXT_HASH = Simple("#");
+ protected final val TXT_RIGHT_ARROW = Simple("=>");
+ protected final val TXT_LEFT_PAREN = Simple("(");
+ protected final val TXT_RIGHT_PAREN = Simple(")");
+ protected final val TXT_LEFT_BRACE = Simple("{");
+ protected final val TXT_RIGHT_BRACE = Simple("}");
+ protected final val TXT_LEFT_BRACKET = Simple("[");
+ protected final val TXT_RIGHT_BRACKET = Simple("]");
+ protected final val TXT_BAR = Simple("|");
+ protected final val TXT_AT = Simple("@");
+
+ protected final val TXT_WITH_SP =
+ Sequence(List(Space, KW_WITH, Space));
+ protected final val TXT_BLOCK_BEGIN =
+ Sequence(List(TXT_LEFT_BRACE, Newline));
+ protected final val TXT_BLOCK_END =
+ Sequence(List(Newline, TXT_RIGHT_BRACE));
+ protected final val TXT_BLOCK_SEP =
+ Sequence(List(TXT_SEMICOLON, Newline));
+ protected final val TXT_COMMA_SP =
+ Sequence(List(TXT_COMMA, Space));
+ protected final val TXT_ELSE_NL =
+ Sequence(List(KW_ELSE, Newline));
+ protected final val TXT_BAR_SP =
+ Sequence(List(Space, TXT_BAR, Space));
+
+ def print(unit: Unit): unit = {
+ printUnitHeader(unit);
+ if (unit.body != null) {
+ for (val i <- Iterator.range(0, unit.body.length)) do {
+ print(unit.body(i));
+ print(TXT_BLOCK_SEP);
+ }
+ } else {
+ print(TXT_NULL);
+ }
+ printUnitFooter(unit);
+ flush();
+ }
+
+ protected def printUnitHeader(unit: Unit): unit =
+ print(Simple("// Scala source: " + unit.source + "\n"));
+
+ protected def printUnitFooter(unit: Unit): unit =
+ print(Newline);
+
+ def print(tree: Tree): TreePrinter = {
+ tree match {
+ case Tree$Bad() =>
+ print(TXT_ERROR);
+
+ case Tree.Empty =>
+ print(TXT_EMPTY);
+
+ case Tree$ClassDef(mods, name, tparams, vparams, tpe, impl) =>
+ printModifiers(mods);
+ print(if ((mods & Modifiers.INTERFACE) != 0) KW_INTERFACE else KW_CLASS);
+ print(Space);
+ printSymbolDefinition(tree.symbol(), name);
+ printParams(tparams);
+ printParams(vparams);
+ printOpt(TXT_COLON, tpe, false);
+ printTemplate(KW_EXTENDS, impl, true);
+
+ case Tree$PackageDef(packaged, impl) =>
+ print(KW_PACKAGE);
+ print(Space);
+ print(packaged);
+ printTemplate(KW_WITH, impl, true);
+
+ case Tree$ModuleDef(mods, name, tpe, impl) =>
+ printModifiers(mods);
+ print(KW_OBJECT);
+ print(Space);
+ printSymbolDefinition(tree.symbol(), name);
+ printOpt(TXT_COLON, tpe, false);
+ printTemplate(KW_EXTENDS, impl, true);
+
+ case Tree$ValDef(mods, name, tpe, rhs) =>
+ printModifiers(mods);
+ if ((mods & Modifiers.MUTABLE) != 0) {
+ print(KW_VAR);
+ } else {
+ if ((mods & Modifiers.MODUL) != 0) print(TXT_OBJECT_COMMENT);
+ print(KW_VAL);
+ }
+ print(Space);
+ printSymbolDefinition(tree.symbol(), name);
+ printOpt(TXT_COLON, tpe, false);
+ if ((mods & Modifiers.DEFERRED) == 0) {
+ print(Space); print(TXT_EQUAL); print(Space);
+ if (rhs == Tree.Empty) print("_");
+ else print(rhs);
+ }
+
+ case Tree$PatDef(mods, pat, rhs) =>
+ printModifiers(mods);
+ print(KW_VAL);
+ print(Space);
+ print(pat);
+ printOpt(TXT_EQUAL, rhs, true);
+
+ case Tree$DefDef(mods, name, tparams, vparams, tpe, rhs) =>
+ printModifiers(mods);
+ print(KW_DEF);
+ print(Space);
+ if (name.isTypeName()) print(KW_THIS);
+ else printSymbolDefinition(tree.symbol(), name);
+ printParams(tparams);
+ printParams(vparams);
+ printOpt(TXT_COLON, tpe, false);
+ printOpt(TXT_EQUAL, rhs, true);
+
+ case Tree$AbsTypeDef(mods, name, rhs, lobound) =>
+ printModifiers(mods);
+ print(KW_TYPE);
+ print(Space);
+ printSymbolDefinition(tree.symbol(), name);
+ printBounds(lobound, rhs);
+
+ case Tree$AliasTypeDef(mods, name, tparams, rhs) =>
+ printModifiers(mods);
+ print(KW_TYPE);
+ print(Space);
+ printSymbolDefinition(tree.symbol(), name);
+ printParams(tparams);
+ printOpt(TXT_EQUAL, rhs, true);
+
+ case Tree$Import(expr, selectors) =>
+ print(KW_IMPORT);
+ print(Space);
+ print(expr);
+ print(TXT_DOT);
+ print(TXT_LEFT_BRACE);
+ var i = 0;
+ while (i < selectors.length) {
+ if (i > 0) print(TXT_COMMA_SP);
+ print(selectors(i).toString());
+ if (i + 1 < selectors.length && selectors(i) != selectors(i+1)) {
+ print(TXT_RIGHT_ARROW);
+ print(selectors(i+1).toString());
+ }
+ i = i + 2;
+ }
+ print(TXT_RIGHT_BRACE);
+
+ case Tree$CaseDef(pat, guard, body) =>
+ print(KW_CASE);
+ print(Space);
+ print(pat);
+ printOpt(KW_IF, guard, true);
+ print(Space);
+ print(TXT_RIGHT_ARROW);
+ print(Space);
+ print(body);
+
+ case Tree$LabelDef(name, params, rhs) =>
+ printSymbolDefinition(tree.symbol(), name);
+ printArray(params.asInstanceOf[Array[Tree]], TXT_LEFT_PAREN, TXT_RIGHT_PAREN, TXT_COMMA_SP);
+ print(rhs);
+
+ case Tree$Block(stats) =>
+ printArray(stats, TXT_BLOCK_BEGIN, TXT_BLOCK_END, TXT_BLOCK_SEP);
+ printType(tree);
+
+ case Tree$Sequence(trees) =>
+ printArray(trees, TXT_LEFT_BRACKET, TXT_RIGHT_BRACKET, TXT_COMMA_SP);
+
+ case Tree$Alternative(trees) =>
+ printArray(trees, TXT_LEFT_PAREN, TXT_RIGHT_PAREN, TXT_BAR_SP);
+
+ case Tree$Bind(name, t) =>
+ printSymbolDefinition(tree.symbol(), name);
+ print(Space);
+ print(TXT_AT);
+ print(Space);
+ print( t );
+
+ case Tree$Visitor(cases) =>
+ printArray(cases.asInstanceOf[Array[Tree]], TXT_BLOCK_BEGIN, TXT_BLOCK_END, Newline);
+
+ case Tree$Function(vparams, body) =>
+ print(TXT_LEFT_PAREN);
+ printParams(vparams);
+ print(Space);
+ print(TXT_RIGHT_ARROW);
+ print(Space);
+ print(body);
+ print(TXT_RIGHT_PAREN);
+
+ case Tree$Assign(lhs, rhs) =>
+ print(lhs);
+ print(Space);
+ print(TXT_EQUAL);
+ print(Space);
+ print(rhs);
+
+ case Tree$If(cond, thenp, elsep) =>
+ print(KW_IF);
+ print(Space);
+ print(TXT_LEFT_PAREN);
+ print(cond);
+ print(TXT_RIGHT_PAREN);
+ indent(); print(Newline);
+ print(thenp);
+ undent(); print(Newline);
+ indent(); printOpt(TXT_ELSE_NL, elsep, false); undent();
+ printType(tree);
+
+ case Tree$Switch(expr, tags, bodies, defaultBody) =>
+ print("<switch>");
+ print(Space);
+ print(TXT_LEFT_PAREN);
+ print(expr);
+ print(TXT_RIGHT_PAREN);
+ print(Space);
+ indent();
+ print(TXT_BLOCK_BEGIN);
+
+ for (val i <- Iterator.range(0, tags.length)) do {
+ print(KW_CASE);
+ print(Space);
+ print("" + tags(i));
+ print(Space);
+ print(TXT_RIGHT_ARROW);
+ print(Space);
+ print(bodies(i));
+ print(Newline);
+ }
+ print("<default> => ");
+ print(defaultBody);
+ undent();
+ print(TXT_BLOCK_END);
+
+ case Tree$Return(expr) =>
+ print(KW_RETURN);
+ print(Space);
+ print(expr);
+
+ case Tree$New(templ) =>
+ printTemplate(KW_NEW, templ, false);
+ printType(tree);
+
+ case Tree$Typed(expr, tpe) =>
+ print(TXT_LEFT_PAREN);
+ print(expr);
+ print(TXT_RIGHT_PAREN);
+ print(Space);
+ print(TXT_COLON);
+ print(Space);
+ print(tpe);
+ printType(tree);
+
+ case Tree$TypeApply(fun, targs) =>
+ print(fun);
+ printArray(targs, TXT_LEFT_BRACKET, TXT_RIGHT_BRACKET, TXT_COMMA_SP);
+ printType(tree);
+
+ case Tree$Apply(fun, vargs) =>
+ if (fun.isInstanceOf[Tree$TypeTerm])
+ print(fun.\"type"/*"*/.resultType().symbol().fullName().toString());
+ else
+ print(fun);
+ printArray(vargs, TXT_LEFT_PAREN, TXT_RIGHT_PAREN, TXT_COMMA_SP);
+ printType(tree);
+
+ case Tree$Super(qualifier, mixin) =>
+ if (qualifier != TypeNames.EMPTY) {
+ printSymbolUse(tree.symbol(), qualifier);
+ print(TXT_DOT);
+ }
+ print(KW_SUPER);
+ if (mixin != TypeNames.EMPTY) {
+ print(TXT_LEFT_PAREN);
+ print(mixin.toString());
+ print(TXT_RIGHT_PAREN);
+ }
+ printType(tree);
+
+ case Tree$This(name) =>
+ if (name != TypeNames.EMPTY) {
+ printSymbolUse(tree.symbol(), name);
+ print(TXT_DOT);
+ }
+ print(KW_THIS);
+ printType(tree);
+
+ case Tree$Select(qualifier, name) =>
+ print(qualifier);
+ print(TXT_DOT);
+ printSymbolUse(tree.symbol(), name);
+ printType(tree);
+
+ case Tree$Ident(name) =>
+ printSymbolUse(tree.symbol(), name);
+ printType(tree);
+
+ case Tree$Literal(obj) =>
+ val str = obj match {
+ case s: String => "\"" + s + "\"";
+ case c: Character => "\'" + c + "\'";
+ case _ => String.valueOf(obj);
+ }
+ print(Literal(str));
+ printType(tree);
+
+ case Tree$TypeTerm() =>
+ print(tree.\"type"/*"*/.toString());
+
+ case Tree$SingletonType(ref) =>
+ print(ref);
+ print(TXT_DOT); print(KW_TYPE);
+
+ case Tree$SelectFromType(qualifier, selector) =>
+ print(qualifier);
+ print(Space); print(TXT_HASH); print(Space);
+ printSymbolUse(tree.symbol(), selector);
+
+ case Tree$FunType(argtpes, restpe) =>
+ printArray(argtpes, TXT_LEFT_PAREN, TXT_RIGHT_PAREN, TXT_COMMA_SP);
+ print(TXT_RIGHT_ARROW);
+ print(restpe);
+
+ case Tree$CompoundType(baseTypes, refinements) =>
+ printArray(baseTypes, None, None, TXT_WITH_SP);
+ printArray(refinements, TXT_BLOCK_BEGIN, TXT_BLOCK_END, Newline);
+
+ case Tree$AppliedType(tpe, args) =>
+ print(tpe);
+ indent();
+ print(TXT_LEFT_BRACKET);
+ for (val i <- Iterator.range(0, args.length)) do {
+ if (i > 0) print(TXT_COMMA_SP);
+ print(args(i));
+ }
+ undent();
+ print(TXT_RIGHT_BRACKET);
+
+ case Tree$Template(parents, body) =>
+ Debug.abort("unexpected case: template");
+
+ case _ =>
+ print(TXT_UNKNOWN);
+ }
+ if (autoFlush)
+ flush();
+ return this;
+ }
+
+ // Printing helpers
+
+ protected def printArray(trees: Array[Tree], open: Text, close: Text, sep: Text): unit = {
+ indent();
+ print(open);
+ for (val i <- Iterator.range(0, trees.length)) do {
+ if (i > 0) print(sep);
+ print(trees(i));
+ }
+ undent();
+ print(close);
+ }
+
+ protected def printOpt(prefix: Text, tree: Tree, spaceBefore: boolean): unit =
+ if (tree != Tree.Empty) {
+ if (spaceBefore)
+ print(Space);
+ print(prefix);
+ print(Space);
+ print(tree);
+ }
+
+ // Printing of symbols
+
+ protected def symbolString(symbol: Symbol, name: Name): String =
+ if (symbol != null) symbol.simpleName().toString()
+ else name.toString();
+
+ protected def printSymbolDefinition(symbol: Symbol, name: Name): unit =
+ print(Identifier(symbol, symbolString(symbol, name), Definition));
+
+ protected def printSymbolUse(symbol: Symbol, name: Name): unit =
+ print(Identifier(symbol, symbolString(symbol, name), Use));
+
+ // Printing of trees
+
+ protected def printType(tree: Tree): unit =
+ if (Global.instance.printtypes) {
+ print(TXT_LEFT_BRACE);
+ print(if (tree.\"type"/*"*/ != null) Simple(tree.\"type"/*"*/.toString())
+ else TXT_NULL);
+ print(TXT_RIGHT_BRACE);
+ }
+
+ protected def printModifiers(flags: int): unit = {
+ if ((flags & Modifiers.ABSTRACT) != 0) {
+ print(KW_ABSTRACT);
+ print(Space);
+ }
+ if ((flags & Modifiers.FINAL) != 0) {
+ print(KW_FINAL);
+ print(Space);
+ }
+ if ((flags & Modifiers.SEALED) != 0) {
+ print(KW_SEALED);
+ print(Space);
+ }
+ if ((flags & Modifiers.PRIVATE) != 0) {
+ print(KW_PRIVATE);
+ print(Space);
+ }
+ if ((flags & Modifiers.PROTECTED) != 0) {
+ print(KW_PROTECTED);
+ print(Space);
+ }
+ if ((flags & Modifiers.OVERRIDE) != 0) {
+ print(KW_OVERRIDE);
+ print(Space);
+ }
+ if ((flags & Modifiers.CASE) != 0) {
+ print(KW_CASE);
+ print(Space);
+ }
+ if ((flags & Modifiers.DEF) != 0) {
+ print(KW_DEF);
+ print(Space);
+ }
+ if ((flags & Modifiers.STATIC) != 0) {
+ print(KW_STATIC);
+ print(Space);
+ }
+ }
+
+ protected def printTemplate(prefix: Text,
+ templ: Tree$Template,
+ spaceBefore: boolean): unit = {
+ if (! (templ.parents.length == 0
+ || (templ.parents.length == 1
+ && templ.parents(0) == Tree.Empty))) {
+ if (spaceBefore)
+ print(Space);
+ print(prefix);
+ print(Space);
+ printArray(templ.parents, None, None, TXT_WITH_SP);
+ }
+ if (templ.body.length > 0) {
+ print(Space);
+ printArray(templ.body, TXT_BLOCK_BEGIN, TXT_BLOCK_END, TXT_BLOCK_SEP);
+ }
+ }
+
+ protected def printParams(tparams: Array[Tree$AbsTypeDef]): unit =
+ if (tparams.length > 0) {
+ print(TXT_LEFT_BRACKET);
+ for (val i <- Iterator.range(0, tparams.length)) do {
+ if (i > 0) print(TXT_COMMA_SP);
+ printParam(tparams(i));
+ }
+ print(TXT_RIGHT_BRACKET);
+ }
+
+ protected def printParams(vparamss: Array[Array[Tree$ValDef]]): unit =
+ for (val i <- Iterator.range(0, vparamss.length)) do
+ printParams(vparamss(i));
+
+ protected def printParams(vparams: Array[Tree$ValDef]): unit = {
+ print(TXT_LEFT_PAREN);
+ for (val i <- Iterator.range(0, vparams.length)) do {
+ if (i > 0) print(TXT_COMMA_SP);
+ printParam(vparams(i));
+ }
+ print(TXT_RIGHT_PAREN);
+ }
+
+ protected def printParam(tree: Tree): unit = tree match {
+ case Tree$AbsTypeDef(mods, name, bound, lobound) =>
+ printModifiers(mods);
+ printSymbolDefinition(tree.symbol(), name);
+ printBounds(lobound, bound);
+
+ case Tree$ValDef(mods, name, tpe, Tree.Empty) =>
+ printModifiers(mods);
+ printSymbolDefinition(tree.symbol(), name);
+ printOpt(TXT_COLON, tpe, false);
+
+ case _ =>
+ Debug.abort("bad parameter: " + tree);
+ }
+
+ protected def printBounds(lobound: Tree, hibound: Tree): unit = {
+ if (!"scala.All".equals(lobound.toString()))
+ printOpt(TXT_SUPERTYPE, lobound, true);
+ if (!"scala.Any".equals(hibound.toString()))
+ printOpt(TXT_SUBTYPE, hibound, true);
+ }
+}
diff --git a/sources/scalac/CompilerPhases.java b/sources/scalac/CompilerPhases.java
index 93007eda28..e0329bc7e6 100644
--- a/sources/scalac/CompilerPhases.java
+++ b/sources/scalac/CompilerPhases.java
@@ -46,6 +46,24 @@ public class CompilerPhases {
/** The list containing the active phases */
private final List phases;
+ /** Phase names, can be overridden to install .
+ */
+ protected Class PARSER_PHASE() { return scalac.ast.parser.ParserPhase.class; }
+ protected Class ANALYZER_PHASE() { return scalac.typechecker.AnalyzerPhase.class; }
+ protected Class REFCHECK_PHASE() { return scalac.typechecker.RefCheckPhase.class; }
+ protected Class UNCURRY_PHASE() { return scalac.transformer.UnCurryPhase.class; }
+ protected Class TRANSMATCH_PHASE() { return scalac.transformer.TransMatchPhase.class; }
+ protected Class LAMBDALIFT_PHASE() { return scalac.transformer.LambdaLiftPhase.class; }
+ protected Class EXPLICITOUTER_PHASE() { return scalac.transformer.ExplicitOuterClassesPhase.class; }
+ protected Class ADDACCESSORS_PHASE() { return scalac.transformer.AddAccessorsPhase.class; }
+ protected Class TAILCALL_PHASE() { return scalac.transformer.TailCallPhase.class; }
+ protected Class ADDINTERFACES_PHASE() { return scalac.transformer.AddInterfacesPhase.class; }
+ protected Class EXPANDMIXIN_PHASE() { return scalac.transformer.ExpandMixinsPhase.class; }
+ protected Class ADDCONSTRUCTORS_PHASE() { return scalac.transformer.AddConstructorsPhase.class; }
+ protected Class ERASURE_PHASE() { return scalac.transformer.ErasurePhase.class; }
+ protected Class GENMSIL_PHASE() { return scalac.backend.msil.GenMSILPhase.class; }
+ protected Class GENJVM_PHASE() { return scalac.backend.jvm.GenJVMPhase.class; }
+
//########################################################################
// Public Constructors
@@ -57,27 +75,27 @@ public class CompilerPhases {
"initial",
"initializing compiler",
"initializing compiler",
- scalac.util.EmptyPhase.class),
+ scalac.util.EmptyPhase.class),
this.PARSER = new PhaseDescriptor(
"parse",
"parse source files",
"parsed",
- scalac.ast.parser.ParserPhase.class),
+ PARSER_PHASE()),
this.ANALYZER = new PhaseDescriptor(
"analyze",
"name and type analysis",
"type checking",
- scalac.typechecker.AnalyzerPhase.class),
+ ANALYZER_PHASE()),
this.REFCHECK = new PhaseDescriptor(
"refcheck",
"reference checking",
"reference checking",
- scalac.typechecker.RefCheckPhase.class),
+ REFCHECK_PHASE()),
this.UNCURRY = new PhaseDescriptor(
"uncurry",
"uncurry function types and applications",
"uncurried",
- scalac.transformer.UnCurryPhase.class),
+ UNCURRY_PHASE()),
// this.OPTIMIZE = new PhaseDescriptor(
// "optimize",
// "tree-optimizer",
@@ -87,57 +105,57 @@ public class CompilerPhases {
"transmatch",
"translate match expressions",
"translated pattern matching",
- scalac.transformer.TransMatchPhase.class),
+ TRANSMATCH_PHASE()),
this.LAMBDALIFT = new PhaseDescriptor(
"lambdalift",
"lambda lifter",
"lambda lifting",
- scalac.transformer.LambdaLiftPhase.class),
+ LAMBDALIFT_PHASE()),
this.EXPLICITOUTER = new PhaseDescriptor(
"explicitouterclasses",
"make links from inner classes to enclosing one explicit",
"made outer links explicit",
- scalac.transformer.ExplicitOuterClassesPhase.class),
+ EXPLICITOUTER_PHASE()),
this.ADDACCESSORS = new PhaseDescriptor(
"addaccessors",
"add accessors for constructor arguments",
"added accessors",
- scalac.transformer.AddAccessorsPhase.class),
+ ADDACCESSORS_PHASE()),
this.TAILCALL = new PhaseDescriptor(
"tailcall",
"add tail-calls",
"added tail-calls",
- scalac.transformer.TailCallPhase.class),
+ TAILCALL_PHASE()),
this.ADDINTERFACES = new PhaseDescriptor(
"addinterfaces",
"add one interface per class",
"added interfaces",
- scalac.transformer.AddInterfacesPhase.class),
+ ADDINTERFACES_PHASE()),
this.EXPANDMIXIN = new PhaseDescriptor(
"expandmixins",
"expand mixins by code copying",
"expanded mixins",
- scalac.transformer.ExpandMixinsPhase.class),
+ EXPANDMIXIN_PHASE()),
this.ADDCONSTRUCTORS = new PhaseDescriptor(
"addconstructors",
"add explicit constructor for each class",
"added constructors",
- scalac.transformer.AddConstructorsPhase.class),
+ ADDCONSTRUCTORS_PHASE()),
this.ERASURE = new PhaseDescriptor(
"erasure",
"type eraser",
"erased types",
- scalac.transformer.ErasurePhase.class),
+ ERASURE_PHASE()),
this.GENMSIL = new PhaseDescriptor(
"genmsil",
"generate MSIL code",
"generated MSIL code",
- scalac.backend.msil.GenMSILPhase.class),
+ GENMSIL_PHASE()),
this.GENJVM = new PhaseDescriptor(
"genjvm",
"generate JVM bytecodes",
"generated JVM code",
- scalac.backend.jvm.GenJVMPhase.class),
+ GENJVM_PHASE()),
this.TERMINAL = new PhaseDescriptor(
"terminal",
"compilation terminated",
diff --git a/sources/scalac/Global.java b/sources/scalac/Global.java
index 9bf7dc9492..eeba341b3f 100644
--- a/sources/scalac/Global.java
+++ b/sources/scalac/Global.java
@@ -159,6 +159,15 @@ public class Global {
this(args, false);
}
+ /** hooks for installing printers
+ */
+ protected TreePrinter newTextTreePrinter(OutputStream printStream) {
+ return new TextTreePrinter(printStream);
+ }
+ protected TreePrinter newHTMLTreePrinter(OutputStream printStream) {
+ return new HTMLTreePrinter(printStream);
+ }
+
/**
* Creates an instance variable.
*
@@ -199,9 +208,9 @@ public class Global {
}
String printerName = args.printer.value.intern();
if (printerName == PRINTER_TEXT)
- this.printer = new TextTreePrinter(printStream);
+ this.printer = newTextTreePrinter(printStream);
else
- this.printer = new HTMLTreePrinter(printStream);
+ this.printer = newHTMLTreePrinter(printStream);
this.debugPrinter = new TextTreePrinter(System.err, true);
this.freshNameCreator = new FreshNameCreator();
this.make = new DefaultTreeFactory();
diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java
index 6d441e5f29..fa2bdbe0ca 100644
--- a/sources/scalac/symtab/Symbol.java
+++ b/sources/scalac/symtab/Symbol.java
@@ -1278,6 +1278,11 @@ public class TermSymbol extends Symbol {
return sym;
}
+ public TermSymbol makeConstructor(ClassSymbol clazz) {
+ this.clazz = clazz;
+ return this;
+ }
+
public static TermSymbol newJavaConstructor(Symbol clazz) {
return newConstructor(clazz, clazz.flags & (ACCESSFLAGS | JAVA));
}
@@ -1840,7 +1845,7 @@ public class ClassSymbol extends TypeSymbol {
}
for (int i = 0; i < index; i++)
sym = it.next();
- System.out.println("field accessor = " + sym);
+ //System.out.println("field accessor = " + sym);//DEBUG
}
assert sym != null : this;
return sym;
diff --git a/sources/scalac/symtab/classfile/Pickle.java b/sources/scalac/symtab/classfile/Pickle.java
index 871a417509..3a3747822b 100644
--- a/sources/scalac/symtab/classfile/Pickle.java
+++ b/sources/scalac/symtab/classfile/Pickle.java
@@ -133,7 +133,8 @@ public class Pickle implements Kinds, Modifiers, EntryTags {
putSymbol(it.next());
break;
case VAL:
- if (sym.isPrimaryConstructor())
+ if (sym.isConstructor() &&
+ sym == sym.constructorClass().allConstructors())
putSymbol(sym.constructorClass());
else if (sym.isModule())
putSymbol(sym.moduleClass());
@@ -341,7 +342,8 @@ public class Pickle implements Kinds, Modifiers, EntryTags {
writeRef(sym.allConstructors());
break;
case VAL:
- if (sym.isPrimaryConstructor())
+ if (sym.isConstructor() &&
+ sym == sym.constructorClass().allConstructors())
writeRef(sym.constructorClass());
else if (sym.isModule())
writeRef(sym.moduleClass());
diff --git a/sources/scalac/symtab/classfile/UnPickle.java b/sources/scalac/symtab/classfile/UnPickle.java
index e4413be233..905e5a8b22 100644
--- a/sources/scalac/symtab/classfile/UnPickle.java
+++ b/sources/scalac/symtab/classfile/UnPickle.java
@@ -246,18 +246,17 @@ public class UnPickle implements Kinds, Modifiers, EntryTags, TypeTags {
sym.setFirstInfo(getType(inforef));
sym.setTypeOfThis(readTypeRef());
Symbol constr = readSymbolRef();
- if (constr != sym.primaryConstructor()) {
- assert constr.type() instanceof Type.OverloadedType
- : sym + " " + constr + ":" + constr.type();
- constr.copyTo(sym.allConstructors());
- }
+ assert constr == sym.allConstructors();
+ Symbol[] alts = constr.alternativeSymbols();
+ for (int i = 0; i < alts.length; i++)
+ ((TermSymbol)alts[i]).makeConstructor((ClassSymbol)sym);
break;
case VALsym:
if (bp < end) {
Symbol tsym = readSymbolRef();
if (name == Names.CONSTRUCTOR) {
- entries[n] = sym = tsym.primaryConstructor();
+ entries[n] = sym = tsym.allConstructors();
sym.flags = flags;
} else {
assert (flags & MODUL) != 0 : name;
diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java
index 64181df003..eff8af583f 100644
--- a/sources/scalac/typechecker/Analyzer.java
+++ b/sources/scalac/typechecker/Analyzer.java
@@ -2101,7 +2101,9 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
return copy.Assign(tree, lhs1, rhs1)
.setType(definitions.UNIT_TYPE());
} else {
- return error(tree.pos, "assignment to non-variable");
+ if (lhs1.type != Type.ErrorType)
+ error(tree.pos, "assignment to non-variable ");
+ return errorTree(tree.pos);
}
case If(Tree cond, Tree thenp, Tree elsep):
diff --git a/sources/scalac/typechecker/ConstantFolder.java b/sources/scalac/typechecker/ConstantFolder.java
index 9131609c7d..125253a1b0 100644
--- a/sources/scalac/typechecker/ConstantFolder.java
+++ b/sources/scalac/typechecker/ConstantFolder.java
@@ -177,7 +177,7 @@ class ConstantFolder implements /*imports*/ TypeTags {
}
return (value != null) ? Type.constantType(value) : Type.NoType;
} catch (ArithmeticException e) {
- ana.unit.error(pos, e.toString());
+ ana.unit.warning(pos, e.toString());
return Type.NoType;
}
}
@@ -223,7 +223,7 @@ class ConstantFolder implements /*imports*/ TypeTags {
}
return (value != null) ? Type.constantType(value) : Type.NoType;
} catch (ArithmeticException e) {
- ana.unit.error(pos, e.toString());
+ ana.unit.warning(pos, e.toString());
return Type.NoType;
}
}
@@ -262,7 +262,7 @@ class ConstantFolder implements /*imports*/ TypeTags {
return (value != null) ? new ConstantType(argtype, value)
: Type.NoType;
} catch (ClassCastException e) {
- ana.unit.error(pos, e.toString());
+ ana.unit.warning(pos, e.toString());
return Type.NoType;
}
}