diff options
author | Martin Odersky <odersky@gmail.com> | 2011-01-08 17:20:35 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2011-01-08 17:20:35 +0000 |
commit | 8752d5888450f1e188203821fe3748216e1e902f (patch) | |
tree | 89e8d5d36d971040158aa015de97ed42ffee345a | |
parent | 701b17de262adca8f2787f3230b158cffa332254 (diff) | |
download | scala-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.
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 |