summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2009-06-24 15:37:16 +0000
committerMartin Odersky <odersky@gmail.com>2009-06-24 15:37:16 +0000
commit410efa8317f2a244f45f33b2ae7c17be5472f5d5 (patch)
tree0cddab6b90904718b8162797656ab7076bb920ce /src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
parent1c9870541fb22ac032edaa0be0103cc1aa2c99b4 (diff)
downloadscala-410efa8317f2a244f45f33b2ae7c17be5472f5d5.tar.gz
scala-410efa8317f2a244f45f33b2ae7c17be5472f5d5.tar.bz2
scala-410efa8317f2a244f45f33b2ae7c17be5472f5d5.zip
fixed variance bug; added smart brace insertion...
fixed variance bug; added smart brace insertion to parser. moved interactive compiler interface along.
Diffstat (limited to 'src/compiler/scala/tools/nsc/ast/parser/Parsers.scala')
-rwxr-xr-xsrc/compiler/scala/tools/nsc/ast/parser/Parsers.scala64
1 files changed, 54 insertions, 10 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index fc85f7a196..6246782e9f 100755
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -59,8 +59,11 @@ self =>
case class OpInfo(operand: Tree, operator: Name, offset: Offset)
- class UnitParser(val unit: global.CompilationUnit) extends Parser {
- val in = new UnitScanner(unit)
+ class UnitParser(val unit: global.CompilationUnit, patches: List[BracePatch]) extends Parser {
+
+ def this(unit: global.CompilationUnit) = this(unit, List())
+
+ val in = new UnitScanner(unit, patches)
in.init()
def freshName(pos: Position, prefix: String): Name =
@@ -71,15 +74,45 @@ self =>
def warning(offset: Int, msg: String) { unit.warning(o2p(offset), msg) }
+ def deprecationWarning(offset: Int, msg: String) {
+ unit.deprecationWarning(o2p(offset), msg)
+ }
+
+ var smartParsing = false
+
+ val syntaxErrors = new ListBuffer[(Int, String)]
+
def incompleteInputError(msg: String) {
- unit.incompleteInputError(o2p(unit.source.asInstanceOf[BatchSourceFile].content.length - 1), msg)
+ val offset = unit.source.asInstanceOf[BatchSourceFile].content.length - 1
+ if (smartParsing) syntaxErrors += ((offset, msg))
+ else unit.incompleteInputError(o2p(offset), msg)
}
- def deprecationWarning(offset: Int, msg: String) {
- unit.deprecationWarning(o2p(offset), msg)
+ def syntaxError(offset: Int, msg: String) {
+ if (smartParsing) syntaxErrors += ((offset, msg))
+ else unit.error(o2p(offset), msg)
}
- def syntaxError(offset: Int, msg: String) { unit.error(o2p(offset), msg) }
+ /** parse unit. If there are inbalanced braces,
+ * try to correct them and reparse.
+ */
+ def smartParse(): Tree = try {
+ smartParsing = true
+ val firstTry = parse()
+ if (syntaxErrors.isEmpty) firstTry
+ else {
+ val patches = in.healBraces()
+ if (patches.isEmpty) {
+ for ((offset, msg) <- syntaxErrors) unit.error(o2p(offset), msg)
+ firstTry
+ } else {
+ println(patches)
+ new UnitParser(unit, patches).parse()
+ }
+ }
+ } finally {
+ smartParsing = false
+ }
/** the markup parser */
lazy val xmlp = new MarkupParser(this, true)
@@ -200,7 +233,9 @@ self =>
/* ------------- ERROR HANDLING ------------------------------------------- */
- protected def skip() {
+ var assumedClosingParens = collection.mutable.Map(RPAREN -> 0, RBRACKET -> 0, RBRACE -> 0)
+
+ protected def skip(targetToken: Int) {
var nparens = 0
var nbraces = 0
while (true) {
@@ -224,6 +259,7 @@ self =>
nbraces += 1
case _ =>
}
+ if (targetToken == in.token && nparens == 0 && nbraces == 0) return
in.nextToken()
}
}
@@ -248,7 +284,7 @@ self =>
lastErrorOffset = in.offset
}
if (skipIt)
- skip()
+ skip(UNDEF)
}
def warning(msg: String) { warning(in.offset, msg) }
@@ -268,13 +304,21 @@ self =>
if (in.token != token) {
val msg =
token2string(token) + " expected but " +token2string(in.token) + " found."
-
+ syntaxErrorOrIncomplete(msg, true)
if (in.token == EOF) incompleteInputError(msg)
- else syntaxError(in.offset, msg, true)
+ else syntaxError(in.offset, msg, false)
+ if ((token == RPAREN || token == RBRACE || token == RBRACKET))
+ if (in.parenBalance(token) + assumedClosingParens(token) < 0)
+ assumedClosingParens(token) += 1
+ else
+ skip(token)
+ else
+ skip(UNDEF)
}
if (in.token == token) in.nextToken()
offset
}
+
def surround[T](open: Int, close: Int)(f: => T, orElse: T): T = {
val wasOpened = in.token == open
accept(open)