summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2011-01-08 17:20:35 +0000
committerMartin Odersky <odersky@gmail.com>2011-01-08 17:20:35 +0000
commit8752d5888450f1e188203821fe3748216e1e902f (patch)
tree89e8d5d36d971040158aa015de97ed42ffee345a /src/compiler
parent701b17de262adca8f2787f3230b158cffa332254 (diff)
downloadscala-8752d5888450f1e188203821fe3748216e1e902f.tar.gz
scala-8752d5888450f1e188203821fe3748216e1e902f.tar.bz2
scala-8752d5888450f1e188203821fe3748216e1e902f.zip
Untangling parsers from compilation units so th...
Untangling parsers from compilation units so that we can browse toplevel symbols without full compilations.
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala94
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Scanners.scala29
3 files changed, 87 insertions, 38 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
index d0265ac95c..643b1f88f4 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
@@ -47,7 +47,7 @@ trait MarkupParsers {
import global._
- class MarkupParser(parser: UnitParser, final val preserveWS: Boolean) extends scala.xml.parsing.MarkupParserCommon {
+ class MarkupParser(parser: SourceFileParser, final val preserveWS: Boolean) extends scala.xml.parsing.MarkupParserCommon {
import Tokens.{ EMPTY, LBRACE, RBRACE }
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 96bbd7fcbc..ba913bf693 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -10,7 +10,7 @@ package scala.tools.nsc
package ast.parser
import scala.collection.mutable.ListBuffer
-import util.{ OffsetPosition }
+import util.{ SourceFile, OffsetPosition, FreshNameCreator }
import scala.reflect.generic.{ ModifierFlags => Flags }
import Tokens._
import util.Chars.{ isScalaLetter }
@@ -124,29 +124,76 @@ self =>
case class OpInfo(operand: Tree, operator: Name, offset: Offset)
- class UnitParser(val unit: global.CompilationUnit, patches: List[BracePatch]) extends Parser {
-
- def this(unit: global.CompilationUnit) = this(unit, List())
+ class SourceFileParser(val source: SourceFile) extends Parser {
/** The parse starting point depends on whether the source file is self-contained:
* if not, the AST will be supplemented.
*/
def parseStartRule =
- if (unit.source.isSelfContained) () => compilationUnit()
+ if (source.isSelfContained) () => compilationUnit()
else () => scriptBody()
- val in = new UnitScanner(unit, patches)
+ def newScanner = new SourceFileScanner(source)
+
+ val in = newScanner
in.init()
+ private val globalFresh = new FreshNameCreator.Default
+
def freshName(prefix: String): Name = freshTermName(prefix)
- def freshTermName(prefix: String): TermName = unit.freshTermName(prefix)
- def freshTypeName(prefix: String): TypeName = unit.freshTypeName(prefix)
+ def freshTermName(prefix: String): TermName = newTermName(globalFresh.newName(prefix))
+ def freshTypeName(prefix: String): TypeName = newTypeName(globalFresh.newName(prefix))
+
+ def o2p(offset: Int): Position = new OffsetPosition(source, offset)
+ def r2p(start: Int, mid: Int, end: Int): Position = rangePos(source, start, mid, end)
+
+ // suppress warnings; silent abort on errors
+ def warning(offset: Int, msg: String) {}
+ def deprecationWarning(offset: Int, msg: String) {}
- def o2p(offset: Int): Position = new OffsetPosition(unit.source,offset)
- def r2p(start: Int, mid: Int, end: Int): Position = rangePos(unit.source, start, mid, end)
- def warning(offset: Int, msg: String) { unit.warning(o2p(offset), msg) }
+ def syntaxError(offset: Int, msg: String): Unit = throw new MalformedInput
+ def incompleteInputError(msg: String): Unit = throw new MalformedInput
- def deprecationWarning(offset: Int, msg: String) {
+ /** the markup parser */
+ lazy val xmlp = new MarkupParser(this, true)
+
+ object symbXMLBuilder extends SymbolicXMLBuilder(this, true) { // DEBUG choices
+ val global: self.global.type = self.global
+ def freshName(prefix: String): Name = SourceFileParser.this.freshName(prefix)
+ }
+
+ def xmlLiteral : Tree = xmlp.xLiteral
+ def xmlLiteralPattern : Tree = xmlp.xLiteralPattern
+ }
+
+ class OutlineParser(source: SourceFile) extends SourceFileParser(source) {
+
+ def skipBraces[T](body: T): T = {
+ accept(LBRACE)
+ while (in.token != EOF && in.token != RBRACE)
+ if (in.token == XMLSTART) xmlLiteral() else in.nextToken()
+ body
+ }
+
+ override def blockExpr(): Tree = skipBraces(EmptyTree)
+
+ override def templateStatSeq(isPre: Boolean) = skipBraces(emptyValDef, List())
+ }
+
+ class UnitParser(val unit: global.CompilationUnit, patches: List[BracePatch]) extends SourceFileParser(unit.source) {
+
+ def this(unit: global.CompilationUnit) = this(unit, List())
+
+ override def newScanner = new UnitScanner(unit, patches)
+
+ override def freshTermName(prefix: String): TermName = unit.freshTermName(prefix)
+ override def freshTypeName(prefix: String): TypeName = unit.freshTypeName(prefix)
+
+ override def warning(offset: Int, msg: String) {
+ unit.warning(o2p(offset), msg)
+ }
+
+ override def deprecationWarning(offset: Int, msg: String) {
unit.deprecationWarning(o2p(offset), msg)
}
@@ -165,15 +212,15 @@ self =>
for ((offset, msg) <- syntaxErrors)
unit.error(o2p(offset), msg)
- def incompleteInputError(msg: String) {
- val offset = unit.source.content.length - 1
+ override def syntaxError(offset: Int, msg: String) {
if (smartParsing) syntaxErrors += ((offset, msg))
- else unit.incompleteInputError(o2p(offset), msg)
+ else unit.error(o2p(offset), msg)
}
- def syntaxError(offset: Int, msg: String) {
+ override def incompleteInputError(msg: String) {
+ val offset = source.content.length - 1
if (smartParsing) syntaxErrors += ((offset, msg))
- else unit.error(o2p(offset), msg)
+ else unit.incompleteInputError(o2p(offset), msg)
}
/** parse unit. If there are inbalanced braces,
@@ -187,17 +234,6 @@ self =>
case patches => new UnitParser(unit, patches).parse()
}
}
-
- /** the markup parser */
- lazy val xmlp = new MarkupParser(this, true)
-
- object symbXMLBuilder extends SymbolicXMLBuilder(this, true) { // DEBUG choices
- val global: self.global.type = self.global
- def freshName(prefix: String): Name = UnitParser.this.freshName(prefix)
- }
-
- def xmlLiteral : Tree = xmlp.xLiteral
- def xmlLiteralPattern : Tree = xmlp.xLiteralPattern
}
final val Local = 0
@@ -2602,7 +2638,7 @@ self =>
* |
* @param isPre specifies whether in early initializer (true) or not (false)
*/
- def templateStatSeq(isPre : Boolean) = checkNoEscapingPlaceholders {
+ def templateStatSeq(isPre : Boolean): (ValDef, List[Tree]) = checkNoEscapingPlaceholders {
var self: ValDef = emptyValDef
val stats = new ListBuffer[Tree]
if (isExprIntro) {
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
index 26515f6e8b..504fa75f6d 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
@@ -24,7 +24,7 @@ trait ScannersCommon {
}
trait ScannerCommon extends CommonTokenData {
- // things to fill in, in addition to buf, decodeUni
+ // things to fill in, in addition to buf, decodeUni which come from CharArrayReader
def warning(off: Int, msg: String): Unit
def error (off: Int, msg: String): Unit
def incompleteInputError(off: Int, msg: String): Unit
@@ -799,7 +799,7 @@ trait Scanners extends ScannersCommon {
/** Backquoted idents like 22.`foo`. */
case '`' =>
- return setStrVal() /** Note the early return **/
+ return setStrVal() /** Note the early return */
/** These letters may be part of a literal, or a method invocation on an Int */
case 'd' | 'D' | 'f' | 'F' =>
@@ -1027,16 +1027,29 @@ trait Scanners extends ScannersCommon {
else "'<" + token + ">'"
}
+ class MalformedInput extends Exception
+
+ /** A scanner for a given source file not necessarily attached to a compilation unit.
+ * Useful for looking inside source files that aren not currently compiled to see what's there
+ */
+ class SourceFileScanner(val source: SourceFile) extends Scanner {
+ val buf = source.content
+ override val decodeUni: Boolean = !settings.nouescape.value
+
+ // suppress warnings, throw exception on errors
+ def warning(off: Offset, msg: String): Unit = {}
+ def error (off: Offset, msg: String): Unit = throw new MalformedInput
+ def incompleteInputError(off: Offset, msg: String): Unit = throw new MalformedInput
+ }
+
/** A scanner over a given compilation unit
*/
- class UnitScanner(unit: CompilationUnit, patches: List[BracePatch]) extends Scanner {
+ class UnitScanner(unit: CompilationUnit, patches: List[BracePatch]) extends SourceFileScanner(unit.source) {
def this(unit: CompilationUnit) = this(unit, List())
- val buf = unit.source.content
- override val decodeUni: Boolean = !settings.nouescape.value
- def warning(off: Offset, msg: String) = unit.warning(unit.position(off), msg)
- def error (off: Offset, msg: String) = unit.error(unit.position(off), msg)
- def incompleteInputError(off: Offset, msg: String) = unit.incompleteInputError(unit.position(off), msg)
+ override def warning(off: Offset, msg: String) = unit.warning(unit.position(off), msg)
+ override def error (off: Offset, msg: String) = unit.error(unit.position(off), msg)
+ override def incompleteInputError(off: Offset, msg: String) = unit.incompleteInputError(unit.position(off), msg)
private var bracePatches: List[BracePatch] = patches