From 94e3a13f24d98e3e71bc8f041df8241beb43b234 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 12 Feb 2007 11:06:34 +0000 Subject: small fixes to newline behavior. --- .../scala/tools/nsc/ast/parser/Parsers.scala | 66 +++++++++++++--------- .../scala/tools/nsc/ast/parser/Scanners.scala | 15 ++--- .../scala/tools/nsc/ast/parser/Tokens.scala | 11 ++-- .../scala/tools/nsc/util/CharArrayReader.scala | 23 +++++--- 4 files changed, 67 insertions(+), 48 deletions(-) (limited to 'src/compiler') diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index c61edbce53..c0e231de6f 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -98,6 +98,8 @@ trait Parsers requires SyntaxAnalyzer { if (nparens == 0 && nbraces == 0) return case NEWLINE => if (nparens == 0 && nbraces == 0) return + case NEWLINES => + if (nparens == 0 && nbraces == 0) return case RPAREN => nparens = nparens - 1 case RBRACE => @@ -183,7 +185,8 @@ trait Parsers requires SyntaxAnalyzer { * NewLine = `\n' // where allowed */ def acceptStatSep(): unit = - if (in.token == NEWLINE) in.nextToken() else accept(SEMI) + if (in.token == NEWLINE || in.token == NEWLINES) in.nextToken() + else accept(SEMI) def errorTypeTree = TypeTree().setType(ErrorType).setPos(in.currentPos) def errorTermTree = Literal(Constant(null)).setPos(in.currentPos) @@ -231,6 +234,11 @@ trait Parsers requires SyntaxAnalyzer { def isTypeIntro: boolean = isTypeIntroToken(in.token) + def isStatSep(token: int): boolean = + token == NEWLINE || token == NEWLINES || token == SEMI + + def isStatSep: boolean = isStatSep(in.token) + /////// COMMENT AND ATTRIBUTE COLLECTION ////////////////////////////////////// @@ -526,6 +534,12 @@ trait Parsers requires SyntaxAnalyzer { in.nextToken() } + def newLinesOpt(): unit = + if (in.token == NEWLINE || in.token == NEWLINES) { + if (settings.migrate.value) in.newNewLine = false + in.nextToken() + } + def newLineOptWhenFollowedBy(token: int): unit = { // note: next is defined here because current == NEWLINE if (in.token == NEWLINE && in.next.token == token) newLineOpt() @@ -850,7 +864,7 @@ trait Parsers requires SyntaxAnalyzer { accept(LPAREN) val cond = localExpr() accept(RPAREN) - newLineOpt() + newLinesOpt() val thenp = expr() val elsep = if (in.token == ELSE) { in.nextToken(); expr() } @@ -880,14 +894,14 @@ trait Parsers requires SyntaxAnalyzer { accept(LPAREN) val cond = noLifting(localExpr()) accept(RPAREN) - newLineOpt() + newLinesOpt() val body = expr() atPos(pos) { makeWhile(lname, cond, body) } case DO => val lname: Name = unit.fresh.newName("doWhile$") val pos = in.skipToken() val body = expr() - if (in.token == SEMI || in.token == NEWLINE) in.nextToken() + if (isStatSep) in.nextToken() accept(WHILE) accept(LPAREN) val cond = noLifting(localExpr()) @@ -899,7 +913,7 @@ trait Parsers requires SyntaxAnalyzer { accept(if (startToken == LBRACE) LBRACE else LPAREN) val enums = enumerators() accept(if (startToken == LBRACE) RBRACE else RPAREN) - newLineOpt() + newLinesOpt() if (in.token == YIELD) { in.nextToken(); makeForYield(enums, expr()) } else makeFor(enums, expr()) @@ -1189,7 +1203,7 @@ trait Parsers requires SyntaxAnalyzer { */ def enumerators(): List[Enumerator] = { val enums = new ListBuffer[Enumerator] + generator(false) - while (in.token == SEMI || in.token == NEWLINE) { + while (isStatSep) { in.nextToken() enums += (if (in.token == VAL) generator(true) else Filter(expr())) } @@ -1629,7 +1643,7 @@ trait Parsers requires SyntaxAnalyzer { param } val params = new ListBuffer[AbsTypeDef] - //newLineOptWhenFollowedBy(LBRACKET) + newLineOptWhenFollowedBy(LBRACKET) if (in.token == LBRACKET) { in.nextToken() params += typeParam() @@ -1760,7 +1774,7 @@ trait Parsers requires SyntaxAnalyzer { List(funDefOrDcl(mods)) case TYPE => in.nextToken() - newLineOpt() + newLinesOpt() List(typeDefOrDcl(mods)) case _ => List(tmplDef(mods)) @@ -1831,7 +1845,7 @@ trait Parsers requires SyntaxAnalyzer { } /** FunDef ::= FunSig `:' Type `=' Expr - | FunSig Block + * | FunSig Block * | this ParamClause ParamClauses (`=' ConstrExpr | ConstrBlock) * FunDcl ::= FunSig [`:' Type] * FunSig ::= id [FunTypeParamClause] ParamClauses @@ -1852,7 +1866,7 @@ trait Parsers requires SyntaxAnalyzer { val vparamss = paramClauses(name, implicitViewBuf.toList, false) var restype = typedOpt() val rhs = - if (in.token == SEMI || in.token == NEWLINE || in.token == RBRACE) { + if (isStatSep || in.token == RBRACE) { if (restype.isEmpty) restype = scalaUnitConstr newmods = newmods | Flags.DEFERRED EmptyTree @@ -1875,7 +1889,9 @@ trait Parsers requires SyntaxAnalyzer { def selfInvocation(vparamss: List[List[ValDef]]): Tree = atPos(accept(THIS)) { var t = Apply(Ident(nme.CONSTRUCTOR), argumentExprs()) - while (in.token == LPAREN) t = Apply(t, argumentExprs()) + while (in.token == LPAREN || in.token == LBRACE) { + t = Apply(t, argumentExprs()) + } if (!implicitClassViews.isEmpty) t = Apply(t, vparamss.last.map(vd => Ident(vd.name))) t } @@ -1886,10 +1902,8 @@ trait Parsers requires SyntaxAnalyzer { atPos(in.skipToken()) { val statlist = new ListBuffer[Tree] statlist += selfInvocation(vparamss) - val stats = - if (in.token == SEMI || in.token == NEWLINE) { - in.nextToken(); blockStatSeq(statlist) - } else statlist.toList + val stats = if (isStatSep) { in.nextToken(); blockStatSeq(statlist) } + else statlist.toList accept(RBRACE) makeBlock(stats) } @@ -1908,7 +1922,7 @@ trait Parsers requires SyntaxAnalyzer { case EQUALS => in.nextToken() AliasTypeDef(mods, name, List(), typ()) - case SUPERTYPE | SUBTYPE | SEMI | NEWLINE | COMMA | RBRACE => + case SUPERTYPE | SUBTYPE | SEMI | NEWLINE | NEWLINES | COMMA | RBRACE => typeBounds(mods | Flags.DEFERRED, name) case _ => syntaxErrorOrIncomplete("`=', `>:', or `<:' expected", true) @@ -1982,9 +1996,8 @@ trait Parsers requires SyntaxAnalyzer { atPos(in.currentPos) { def acceptEmptyTemplateBody(msg: String): unit = { if (in.token == LPAREN && settings.migrate.value) - syntaxErrorMigrate("traites may not have parameters") - if (!(in.token == SEMI || in.token == NEWLINE || - in.token == COMMA || in.token == RBRACE || in.token == EOF)) + syntaxErrorMigrate("traits may not have parameters") + if (!(isStatSep || in.token == COMMA || in.token == RBRACE || in.token == EOF)) syntaxError(msg, true) } val parents = new ListBuffer[Tree] @@ -2004,6 +2017,7 @@ trait Parsers requires SyntaxAnalyzer { } else { if (in.token == WITH && settings.migrate.value) syntaxErrorMigrate("`extends' needed before `with'") + newLineOptWhenFollowedBy(LBRACE) if (in.token != LBRACE) acceptEmptyTemplateBody("`extends' or `{' expected") argss += List() } @@ -2077,9 +2091,8 @@ trait Parsers requires SyntaxAnalyzer { in.token == LBRACKET || isModifier) { val annots = annotations() - newLineOpt() stats ++ joinComment(List(tmplDef(modifiers() withAnnotations annots))) - } else if (in.token != SEMI && in.token != NEWLINE) { + } else if (!isStatSep) { syntaxErrorOrIncomplete("expected class or object definition", true) } if (in.token != RBRACE && in.token != EOF) acceptStatSep() @@ -2103,9 +2116,8 @@ trait Parsers requires SyntaxAnalyzer { stats += expr() } else if (isDefIntro || isModifier || in.token == LBRACKET) { val annots = annotations() - newLineOpt() stats ++ joinComment(defOrDcl(modifiers() withAnnotations annots)) - } else if (in.token != SEMI && in.token != NEWLINE) { + } else if (!isStatSep) { syntaxErrorOrIncomplete("illegal start of definition", true) } if (in.token != RBRACE && in.token != EOF) acceptStatSep() @@ -2195,7 +2207,7 @@ trait Parsers requires SyntaxAnalyzer { while (in.token != RBRACE && in.token != EOF) { if (isDclIntro) { stats ++= joinComment(defOrDcl(NoMods)) - } else if (in.token != SEMI && in.token != NEWLINE) { + } else if (!isStatSep) { syntaxErrorOrIncomplete("illegal start of declaration", true) } if (in.token != RBRACE) acceptStatSep() @@ -2252,7 +2264,7 @@ trait Parsers requires SyntaxAnalyzer { localDef(NoMods) } else if (isLocalModifier) { localDef(localModifiers()) - } else if (in.token == SEMI || in.token == NEWLINE) { + } else if (isStatSep) { in.nextToken() } else { syntaxErrorOrIncomplete("illegal start of statement", true) @@ -2271,7 +2283,9 @@ trait Parsers requires SyntaxAnalyzer { if (in.token == PACKAGE) { in.nextToken() val pkg = qualId() - if (in.token == SEMI || in.token == NEWLINE || in.token == EOF) { + if (in.token == EOF) { + ts += makePackaging(pkg, List()) + } else if (isStatSep) { in.nextToken() ts += makePackaging(pkg, topStatSeq()) } else { diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala index a1ed4b088d..ff0309a470 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala @@ -183,15 +183,8 @@ trait Scanners requires SyntaxAnalyzer { next.copyFrom(this) pos = in.lineStartPos if (settings.migrate.value) newNewLine = lastToken != RBRACE && token != EOF; - token = NEWLINE - -/* - } else if (lastToken == RBRACE) { - System.out.println("failing to insert NL after RBRACE: " + sepRegions + " " + - lastPos + " " + in.lineStartPos + " " + pos) -*/ + token = if (in.lastBlankLinePos > lastPos) NEWLINES else NEWLINE } -// System.out.println("token: " + toString());//DEBUG } private def afterLineEnd() = ( @@ -450,7 +443,7 @@ trait Scanners requires SyntaxAnalyzer { def inFirstOfStat(token: int) = token match { case EOF | CASE | CATCH | ELSE | EXTENDS | FINALLY | MATCH | REQUIRES | WITH | YIELD | - COMMA | SEMI | NEWLINE | DOT | USCORE | COLON | EQUALS | ARROW | + COMMA | SEMI | NEWLINE | NEWLINES | DOT | USCORE | COLON | EQUALS | ARROW | LARROW | SUBTYPE | VIEWBOUND | SUPERTYPE | HASH | AT | RPAREN | RBRACKET | RBRACE => false @@ -942,6 +935,8 @@ trait Scanners requires SyntaxAnalyzer { "';'" case NEWLINE => "';'" + case NEWLINES => + "';'" case COMMA => "','" case CASECLASS => @@ -980,6 +975,8 @@ trait Scanners requires SyntaxAnalyzer { ";" case NEWLINE => ";" + case NEWLINES => + ";;" case COMMA => "," case _ => diff --git a/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala b/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala index 7aaae5e07a..0aed4e8eae 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala @@ -80,11 +80,12 @@ object Tokens { final val LARROW = 67 final val ARROW = 68 final val NEWLINE = 69 - final val SUBTYPE = 70 - final val SUPERTYPE = 71 - final val HASH = 72 - final val AT = 73 - final val VIEWBOUND = 74 + final val NEWLINES = 70 + final val SUBTYPE = 71 + final val SUPERTYPE = 72 + final val HASH = 73 + final val AT = 74 + final val VIEWBOUND = 75 /** parenthesis */ final val LPAREN = 90 diff --git a/src/compiler/scala/tools/nsc/util/CharArrayReader.scala b/src/compiler/scala/tools/nsc/util/CharArrayReader.scala index ffe41b0f72..cb6cf200fe 100644 --- a/src/compiler/scala/tools/nsc/util/CharArrayReader.scala +++ b/src/compiler/scala/tools/nsc/util/CharArrayReader.scala @@ -28,9 +28,21 @@ class CharArrayReader(buf: Array[char], start: int, /* startline: int, startcol: var isUnicode: boolean = _ var lastLineStartPos: int = 0 var lineStartPos: int = 0 + var lastBlankLinePos: int = 0 + + private var onlyBlankChars = false //private var nextline = startline //private var nextcol = startcol + private def markNewLine() { + lastLineStartPos = lineStartPos + if (onlyBlankChars) lastBlankLinePos = lineStartPos + lineStartPos = bp + onlyBlankChars = true + //nextline = nextline + 1; + //nextcol = 1; + } + def hasNext: boolean = bp < buf.length def last: char = if(bp > start + 2) buf(bp - 2) else ' ' // XML literals @@ -45,19 +57,13 @@ class CharArrayReader(buf: Array[char], start: int, /* startline: int, startcol: case '\t' => // nextcol = ((nextcol - 1) / tabinc * tabinc) + tabinc + 1; case CR => - //nextline = nextline + 1; - // nextcol = 1; if (buf(bp) == LF) { ch = LF bp = bp + 1 } - lastLineStartPos = lineStartPos - lineStartPos = bp + markNewLine() case LF | FF => - lastLineStartPos = lineStartPos - lineStartPos = bp - //nextline = nextline + 1 - //nextcol = 1 + markNewLine() case '\\' => def evenSlashPrefix: boolean = { var p = bp - 2 @@ -80,6 +86,7 @@ class CharArrayReader(buf: Array[char], start: int, /* startline: int, startcol: isUnicode = true } case _ => + if (ch > ' ') onlyBlankChars = false // nextcol = nextcol + 1 } } -- cgit v1.2.3