@@ -69,7 +69,7 @@ object Parsers {
6969 * if not, the AST will be supplemented.
7070 */
7171 def parser (source : SourceFile )(implicit ctx : Context ): Parser =
72- if ( source.isSelfContained) new ScriptParser (source)
72+ if source.isSelfContained then new ScriptParser (source)
7373 else new Parser (source)
7474
7575 abstract class ParserCommon (val source : SourceFile )(implicit ctx : Context ) {
@@ -181,7 +181,7 @@ object Parsers {
181181
182182/* -------------- TOKEN CLASSES ------------------------------------------- */
183183
184- def isIdent = in.token == IDENTIFIER || in.token == BACKQUOTED_IDENT
184+ def isIdent = in.isIdent
185185 def isIdent (name : Name ) = in.token == IDENTIFIER && in.name == name
186186 def isSimpleLiteral = simpleLiteralTokens contains in.token
187187 def isLiteral = literalTokens contains in.token
@@ -207,16 +207,15 @@ object Parsers {
207207 } && ! in.isSoftModifierInModifierPosition
208208
209209 def isExprIntro : Boolean =
210- canStartExpressionTokens .contains(in.token) && ! in.isSoftModifierInModifierPosition
210+ in.canStartExprTokens .contains(in.token) && ! in.isSoftModifierInModifierPosition
211211
212212 def isDefIntro (allowedMods : BitSet , excludedSoftModifiers : Set [TermName ] = Set .empty): Boolean =
213213 in.token == AT ||
214214 (defIntroTokens `contains` in.token) ||
215215 (allowedMods `contains` in.token) ||
216216 in.isSoftModifierInModifierPosition && ! excludedSoftModifiers.contains(in.name)
217217
218- def isStatSep : Boolean =
219- in.token == NEWLINE || in.token == NEWLINES || in.token == SEMI
218+ def isStatSep : Boolean = in.isNewLine || in.token == SEMI
220219
221220 /** A '$' identifier is treated as a splice if followed by a `{`.
222221 * A longer identifier starting with `$` is treated as a splice/id combination
@@ -341,10 +340,8 @@ object Parsers {
341340 /** semi = nl {nl} | `;'
342341 * nl = `\n' // where allowed
343342 */
344- def acceptStatSep (): Unit = in.token match {
345- case NEWLINE | NEWLINES => in.nextToken()
346- case _ => accept(SEMI )
347- }
343+ def acceptStatSep (): Unit =
344+ if in.isNewLine then in.nextToken() else accept(SEMI )
348345
349346 def acceptStatSepUnlessAtEnd (altEnd : Token = EOF ): Unit =
350347 if (! isStatSeqEnd)
@@ -354,7 +351,7 @@ object Parsers {
354351 case NEWLINE | NEWLINES => in.nextToken()
355352 case SEMI => in.nextToken()
356353 case _ =>
357- syntaxError(i " end of statement expected but $in found " )
354+ syntaxError(i " end of statement expected but ${showToken(in.token)} found " )
358355 in.nextToken() // needed to ensure progress; otherwise we might cycle forever
359356 accept(SEMI )
360357 }
@@ -603,9 +600,7 @@ object Parsers {
603600 val t = body()
604601 // Therefore, make sure there would be a matching <outdent>
605602 def nextIndentWidth = in.indentWidth(in.next.offset)
606- if (in.token == NEWLINE || in.token == NEWLINES )
607- && ! (nextIndentWidth < startIndentWidth)
608- then
603+ if in.isNewLine && ! (nextIndentWidth < startIndentWidth) then
609604 warning(
610605 if startIndentWidth <= nextIndentWidth then
611606 i """ Line is indented too far to the right, or a `{' is missing before:
@@ -623,7 +618,7 @@ object Parsers {
623618 * statement that's indented relative to the current region.
624619 */
625620 def checkNextNotIndented (): Unit = in.currentRegion match
626- case r : InBraces if in.token == NEWLINE || in.token == NEWLINES =>
621+ case r : IndentSignificantRegion if in.isNewLine =>
627622 val nextIndentWidth = in.indentWidth(in.next.offset)
628623 if r.indentWidth < nextIndentWidth then
629624 warning(i " Line is indented too far to the right, or a `{' is missing " , in.next.offset)
@@ -813,20 +808,20 @@ object Parsers {
813808 else span
814809 }
815810
816- /** Drop current token, which is assumed to be `then` or `do`. */
817- def dropTerminator (): Unit = {
818- var startOffset = in.offset
819- var endOffset = in.lastCharOffset
820- if ( in.isAfterLineEnd) {
821- if (testChar(endOffset, ' ' ))
822- endOffset += 1
823- }
824- else
825- if (testChar(startOffset - 1 , ' ' ) &&
826- ! overlapsPatch(source, Span (startOffset - 1 , endOffset)))
827- startOffset -= 1
828- patch(source, widenIfWholeLine( Span ( startOffset, endOffset)), " " )
829- }
811+ /** Drop current token, if it is a `then` or `do`. */
812+ def dropTerminator (): Unit =
813+ if in.token == THEN || in.token == DO then
814+ var startOffset = in.offset
815+ var endOffset = in.lastCharOffset
816+ if (in.isAfterLineEnd) {
817+ if (testChar( endOffset, ' ' ))
818+ endOffset += 1
819+ }
820+ else
821+ if (testChar (startOffset - 1 , ' ' ) &&
822+ ! overlapsPatch(source, Span ( startOffset - 1 , endOffset)))
823+ startOffset -= 1
824+ patch(source, widenIfWholeLine( Span (startOffset, endOffset)), " " )
830825
831826 /** rewrite code with (...) around the source code of `t` */
832827 def revertToParens (t : Tree ): Unit =
@@ -841,7 +836,8 @@ object Parsers {
841836 /** In the tokens following the current one, does `query` precede any of the tokens that
842837 * - must start a statement, or
843838 * - separate two statements, or
844- * - continue a statement (e.g. `else`, catch`)?
839+ * - continue a statement (e.g. `else`, catch`), or
840+ * - terminate the current scope?
845841 */
846842 def followedByToken (query : Token ): Boolean = {
847843 val lookahead = in.LookaheadScanner ()
@@ -875,7 +871,7 @@ object Parsers {
875871 }
876872 if (lookahead.token == LARROW )
877873 false // it's a pattern
878- else if (lookahead.token != IDENTIFIER && lookahead.token != BACKQUOTED_IDENT )
874+ else if (lookahead.isIdent )
879875 true // it's not a pattern since token cannot be an infix operator
880876 else
881877 followedByToken(LARROW ) // `<-` comes before possible statement starts
@@ -903,7 +899,7 @@ object Parsers {
903899 */
904900 def followingIsGivenSig () =
905901 val lookahead = in.LookaheadScanner ()
906- if lookahead.token == IDENTIFIER || lookahead.token == BACKQUOTED_IDENT then
902+ if lookahead.isIdent then
907903 lookahead.nextToken()
908904 while lookahead.token == LPAREN || lookahead.token == LBRACKET do
909905 lookahead.skipParens()
@@ -1229,13 +1225,16 @@ object Parsers {
12291225 if (in.token == NEWLINE ) in.nextToken()
12301226
12311227 def newLinesOpt (): Unit =
1232- if (in.token == NEWLINE || in.token == NEWLINES )
1233- in.nextToken()
1228+ if in.isNewLine then in.nextToken()
12341229
12351230 def newLineOptWhenFollowedBy (token : Int ): Unit =
12361231 // note: next is defined here because current == NEWLINE
12371232 if (in.token == NEWLINE && in.next.token == token) in.nextToken()
12381233
1234+ def newLinesOptWhenFollowedBy (name : Name ): Unit =
1235+ if in.isNewLine && in.next.token == IDENTIFIER && in.next.name == name then
1236+ in.nextToken()
1237+
12391238 def newLineOptWhenFollowing (p : Int => Boolean ): Unit =
12401239 // note: next is defined here because current == NEWLINE
12411240 if (in.token == NEWLINE && p(in.next.token)) newLineOpt()
@@ -1251,7 +1250,7 @@ object Parsers {
12511250 }
12521251
12531252 def possibleTemplateStart (): Unit = {
1254- in.observeIndented(noIndentTemplateTokens, nme. derives )
1253+ in.observeIndented()
12551254 newLineOptWhenFollowedBy(LBRACE )
12561255 }
12571256
@@ -1650,35 +1649,51 @@ object Parsers {
16501649
16511650/* ----------- EXPRESSIONS ------------------------------------------------ */
16521651
1652+ /** Does the current conditional expression continue after
1653+ * the initially parsed (...) region?
1654+ */
1655+ def toBeContinued (altToken : Token ): Boolean =
1656+ if in.token == altToken || in.isNewLine || in.isScala2Mode then
1657+ false // a newline token means the expression is finished
1658+ else if ! in.canStartStatTokens.contains(in.token)
1659+ || in.isLeadingInfixOperator(inConditional = true )
1660+ then
1661+ true
1662+ else
1663+ followedByToken(altToken) // scan ahead to see whether we find a `then` or `do`
1664+
16531665 def condExpr (altToken : Token ): Tree =
1654- if ( in.token == LPAREN ) {
1666+ if in.token == LPAREN then
16551667 var t : Tree = atSpan(in.offset) { Parens (inParens(exprInParens())) }
1656- if (in.token != altToken && followedByToken (altToken) )
1657- t = inSepRegion( LPAREN , RPAREN ) {
1658- newLineOpt()
1668+ val enclosedInParens = ! toBeContinued (altToken)
1669+ if ! enclosedInParens then
1670+ t = inSepRegion( LBRACE , RBRACE ) {
16591671 expr1Rest(postfixExprRest(simpleExprRest(t)), Location .ElseWhere )
16601672 }
1661- if ( in.token == altToken) {
1662- if ( rewriteToOldSyntax()) revertToParens(t)
1673+ if in.token == altToken then
1674+ if rewriteToOldSyntax() then revertToParens(t)
16631675 in.nextToken()
1664- }
1665- else {
1666- in.observeIndented(noIndentAfterConditionTokens)
1676+ else
1677+ if (altToken == THEN || enclosedInParens) && in.isNewLine then
1678+ in.observeIndented()
1679+ if ! enclosedInParens && in.token != INDENT then accept(altToken)
16671680 if (rewriteToNewSyntax(t.span))
16681681 dropParensOrBraces(t.span.start, s " ${tokenString(altToken)}" )
1669- }
16701682 t
1671- }
1672- else {
1683+ else
16731684 val t =
1674- if ( in.isNestedStart)
1685+ if in.isNestedStart then
16751686 try expr() finally newLinesOpt()
16761687 else
1677- inSepRegion(LPAREN , RPAREN )(expr())
1678- if (rewriteToOldSyntax(t.span.startPos)) revertToParens(t)
1679- accept(altToken)
1688+ inSepRegion(LBRACE , RBRACE )(expr())
1689+ if rewriteToOldSyntax(t.span.startPos) then
1690+ revertToParens(t)
1691+ if altToken == THEN && in.isNewLine then
1692+ // don't require a `then` at the end of a line
1693+ in.observeIndented()
1694+ if in.token != INDENT then accept(altToken)
16801695 t
1681- }
1696+ end condExpr
16821697
16831698 /** Expr ::= [`implicit'] FunParams =>' Expr
16841699 * | Expr1
@@ -1841,20 +1856,20 @@ object Parsers {
18411856 }
18421857 }
18431858 case _ =>
1844- if (isIdent(nme.inline) && ! in.inModifierPosition() && in.lookaheadIn(canStartExpressionTokens)) {
1859+ if isIdent(nme.inline)
1860+ && ! in.inModifierPosition()
1861+ && in.lookaheadIn(in.canStartExprTokens)
1862+ then
18451863 val start = in.skipToken()
1846- in.token match {
1864+ in.token match
18471865 case IF =>
18481866 ifExpr(start, InlineIf )
18491867 case _ =>
18501868 val t = postfixExpr()
18511869 if (in.token == MATCH ) matchExpr(t, start, InlineMatch )
1852- else {
1870+ else
18531871 syntaxErrorOrIncomplete(i " `match` or `if` expected but ${in.token} found " )
18541872 t
1855- }
1856- }
1857- }
18581873 else expr1Rest(postfixExpr(), location)
18591874 }
18601875
@@ -2001,7 +2016,7 @@ object Parsers {
20012016 def postfixExpr (): Tree = postfixExprRest(prefixExpr())
20022017
20032018 def postfixExprRest (t : Tree ): Tree =
2004- infixOps(t, canStartExpressionTokens , prefixExpr, maybePostfix = true )
2019+ infixOps(t, in.canStartExprTokens , prefixExpr, maybePostfix = true )
20052020
20062021 /** PrefixExpr ::= [`-' | `+' | `~' | `!'] SimpleExpr
20072022 */
@@ -2198,7 +2213,7 @@ object Parsers {
21982213 lookahead.nextToken()
21992214 lookahead.token != COLON
22002215 }
2201- else canStartExpressionTokens .contains(lookahead.token)
2216+ else in.canStartExprTokens .contains(lookahead.token)
22022217 }
22032218 }
22042219 if (in.token == LPAREN && (! inClassConstrAnnots || isLegalAnnotArg))
@@ -2327,7 +2342,7 @@ object Parsers {
23272342 dropParensOrBraces(start, if (in.token == YIELD || in.token == DO ) " " else " do" )
23282343 }
23292344 }
2330- in.observeIndented(noIndentAfterEnumeratorTokens )
2345+ in.observeIndented()
23312346 res
23322347 }
23332348 else {
@@ -2473,7 +2488,7 @@ object Parsers {
24732488 /** InfixPattern ::= SimplePattern {id [nl] SimplePattern}
24742489 */
24752490 def infixPattern (): Tree =
2476- infixOps(simplePattern(), canStartExpressionTokens , simplePattern, isOperator = in.name != nme.raw.BAR )
2491+ infixOps(simplePattern(), in.canStartExprTokens , simplePattern, isOperator = in.name != nme.raw.BAR )
24772492
24782493 /** SimplePattern ::= PatVar
24792494 * | Literal
@@ -3459,6 +3474,7 @@ object Parsers {
34593474 /** Template ::= InheritClauses [TemplateBody]
34603475 */
34613476 def template (constr : DefDef , isEnum : Boolean = false ): Template = {
3477+ newLinesOptWhenFollowedBy(nme.derives )
34623478 val (parents, derived) = inheritClauses()
34633479 possibleTemplateStart()
34643480 if (isEnum) {
@@ -3471,10 +3487,11 @@ object Parsers {
34713487 /** TemplateOpt = [Template]
34723488 */
34733489 def templateOpt (constr : DefDef ): Template =
3474- possibleTemplateStart( )
3490+ newLinesOptWhenFollowedBy(nme. derives )
34753491 if in.token == EXTENDS || isIdent(nme.derives ) then
34763492 template(constr)
34773493 else
3494+ possibleTemplateStart()
34783495 if in.isNestedStart then
34793496 template(constr)
34803497 else
0 commit comments