aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/parsing/Parsers.scala
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/src/dotty/tools/dotc/parsing/Parsers.scala')
-rw-r--r--compiler/src/dotty/tools/dotc/parsing/Parsers.scala164
1 files changed, 107 insertions, 57 deletions
diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala
index 8cc60c984..76f82d8af 100644
--- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala
+++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala
@@ -146,6 +146,7 @@ object Parsers {
def isNumericLit = numericLitTokens contains in.token
def isModifier = modifierTokens contains in.token
def isExprIntro = canStartExpressionTokens contains in.token
+ def isBindingIntro = canStartBindingTokens contains in.token
def isTemplateIntro = templateIntroTokens contains in.token
def isDclIntro = dclIntroTokens contains in.token
def isStatSeqEnd = in.token == RBRACE || in.token == EOF
@@ -597,7 +598,7 @@ object Parsers {
val isNegated = negOffset < in.offset
atPos(negOffset) {
if (in.token == SYMBOLLIT) atPos(in.skipToken()) { SymbolLit(in.strVal) }
- else if (in.token == INTERPOLATIONID) interpolatedString()
+ else if (in.token == INTERPOLATIONID) interpolatedString(inPattern)
else finish(in.token match {
case CHARLIT => in.charVal
case INTLIT => in.intVal(isNegated).toInt
@@ -621,10 +622,14 @@ object Parsers {
in.nextToken()
while (in.token == STRINGPART) {
segmentBuf += Thicket(
- literal(),
+ literal(inPattern = inPattern),
atPos(in.offset) {
if (in.token == IDENTIFIER)
termIdent()
+ else if (in.token == USCORE && inPattern) {
+ in.nextToken()
+ Ident(nme.WILDCARD)
+ }
else if (in.token == THIS) {
in.nextToken()
This(EmptyTypeIdent)
@@ -633,12 +638,12 @@ object Parsers {
if (inPattern) Block(Nil, inBraces(pattern()))
else expr()
else {
- ctx.error(InterpolatedStringError())
+ ctx.error(InterpolatedStringError(), source atPos Position(in.offset))
EmptyTree
}
})
}
- if (in.token == STRINGLIT) segmentBuf += literal()
+ if (in.token == STRINGLIT) segmentBuf += literal(inPattern = inPattern)
InterpolatedString(interpolator, segmentBuf.toList)
}
@@ -677,7 +682,7 @@ object Parsers {
}
}
- /** Type ::= FunArgTypes `=>' Type
+ /** Type ::= [`implicit'] FunArgTypes `=>' Type
* | HkTypeParamClause `->' Type
* | InfixType
* FunArgTypes ::= InfixType
@@ -685,20 +690,26 @@ object Parsers {
*/
def typ(): Tree = {
val start = in.offset
+ val isImplicit = in.token == IMPLICIT
+ if (isImplicit) in.nextToken()
+ def functionRest(params: List[Tree]): Tree =
+ atPos(start, accept(ARROW)) {
+ val t = typ()
+ if (isImplicit) new ImplicitFunction(params, t) else Function(params, t)
+ }
val t =
if (in.token == LPAREN) {
in.nextToken()
if (in.token == RPAREN) {
in.nextToken()
- atPos(start, accept(ARROW)) { Function(Nil, typ()) }
+ functionRest(Nil)
}
else {
openParens.change(LPAREN, 1)
val ts = commaSeparated(funArgType)
openParens.change(LPAREN, -1)
accept(RPAREN)
- if (in.token == ARROW)
- atPos(start, in.skipToken()) { Function(ts, typ()) }
+ if (isImplicit || in.token == ARROW) functionRest(ts)
else {
for (t <- ts)
if (t.isInstanceOf[ByNameTypeTree])
@@ -718,7 +729,7 @@ object Parsers {
else infixType()
in.token match {
- case ARROW => atPos(start, in.skipToken()) { Function(List(t), typ()) }
+ case ARROW => functionRest(t :: Nil)
case FORSOME => syntaxError("existential types no longer supported; use a wildcard type or dependent type instead"); t
case _ => t
}
@@ -941,14 +952,14 @@ object Parsers {
}
}
- /** Expr ::= FunParams `=>' Expr
+ /** Expr ::= [`implicit'] FunParams `=>' Expr
* | Expr1
* FunParams ::= Bindings
- * | [`implicit'] Id
+ * | Id
* | `_'
* ExprInParens ::= PostfixExpr `:' Type
* | Expr
- * BlockResult ::= (FunParams | [`implicit'] Id `:' InfixType) => Block
+ * BlockResult ::= [`implicit'] FunParams `=>' Block
* | Expr1
* Expr1 ::= `if' `(' Expr `)' {nl} Expr [[semi] else Expr]
* | `if' Expr `then' Expr [[semi] else Expr]
@@ -975,22 +986,27 @@ object Parsers {
def expr(): Tree = expr(Location.ElseWhere)
def expr(location: Location.Value): Tree = {
- val saved = placeholderParams
- placeholderParams = Nil
- val t = expr1(location)
- if (in.token == ARROW) {
- placeholderParams = saved
- closureRest(startOffset(t), location, convertToParams(t))
- }
- else if (isWildcard(t)) {
- placeholderParams = placeholderParams ::: saved
- t
+ val start = in.offset
+ if (in.token == IMPLICIT)
+ implicitClosure(start, location, implicitMods())
+ else {
+ val saved = placeholderParams
+ placeholderParams = Nil
+ val t = expr1(location)
+ if (in.token == ARROW) {
+ placeholderParams = saved
+ closureRest(start, location, convertToParams(t))
+ }
+ else if (isWildcard(t)) {
+ placeholderParams = placeholderParams ::: saved
+ t
+ }
+ else
+ try
+ if (placeholderParams.isEmpty) t
+ else new WildcardFunction(placeholderParams.reverse, t)
+ finally placeholderParams = saved
}
- else
- try
- if (placeholderParams.isEmpty) t
- else new WildcardFunction(placeholderParams.reverse, t)
- finally placeholderParams = saved
}
def expr1(location: Location.Value = Location.ElseWhere): Tree = in.token match {
@@ -1056,8 +1072,6 @@ object Parsers {
atPos(in.skipToken()) { Return(if (isExprIntro) expr() else EmptyTree, EmptyTree) }
case FOR =>
forExpr()
- case IMPLICIT =>
- implicitClosure(in.skipToken(), location)
case _ =>
expr1Rest(postfixExpr(), location)
}
@@ -1105,20 +1119,53 @@ object Parsers {
}
}
+ /** FunParams ::= Bindings
+ * | Id
+ * | `_'
+ * Bindings ::= `(' [Binding {`,' Binding}] `)'
+ */
+ def funParams(mods: Modifiers, location: Location.Value): List[Tree] =
+ if (in.token == LPAREN)
+ inParens(if (in.token == RPAREN) Nil else commaSeparated(() => binding(mods)))
+ else {
+ val start = in.offset
+ val name = bindingName()
+ val t =
+ if (in.token == COLON && location == Location.InBlock) {
+ if (false) // Don't error yet, as the alternative syntax "implicit (x: T) => ... "
+ // is not supported by Scala2.x
+ migrationWarningOrError(s"This syntax is no longer supported; parameter needs to be enclosed in (...)")
+
+ in.nextToken()
+ val t = infixType()
+
+ if (false && in.isScala2Mode) {
+ patch(source, Position(start), "(")
+ patch(source, Position(in.lastOffset), ")")
+ }
+ t
+ }
+ else TypeTree()
+ (atPos(start) { makeParameter(name, t, mods) }) :: Nil
+ }
+
+ /** Binding ::= (Id | `_') [`:' Type]
+ */
+ def binding(mods: Modifiers): Tree =
+ atPos(in.offset) { makeParameter(bindingName(), typedOpt(), mods) }
+
+ def bindingName(): TermName =
+ if (in.token == USCORE) {
+ in.nextToken()
+ ctx.freshName(nme.USCORE_PARAM_PREFIX).toTermName
+ }
+ else ident()
+
/** Expr ::= implicit Id `=>' Expr
- * BlockResult ::= implicit Id [`:' InfixType] `=>' Block
- */
- def implicitClosure(start: Int, location: Location.Value, implicitMod: Option[Mod] = None): Tree = {
- var mods = atPos(start) { Modifiers(Implicit) }
- if (implicitMod.nonEmpty) mods = mods.withAddedMod(implicitMod.get)
- val id = termIdent()
- val paramExpr =
- if (location == Location.InBlock && in.token == COLON)
- atPos(startOffset(id), in.skipToken()) { Typed(id, infixType()) }
- else
- id
- closureRest(start, location, convertToParam(paramExpr, mods) :: Nil)
- }
+ * BlockResult ::= implicit Id [`:' InfixType] `=>' Block // Scala2 only
+ */
+ def implicitClosure(start: Int, location: Location.Value, implicitMods: Modifiers): Tree =
+ closureRest(start, location, funParams(implicitMods, location))
def closureRest(start: Int, location: Location.Value, params: List[Tree]): Tree =
atPos(start, in.offset) {
@@ -1444,7 +1491,7 @@ object Parsers {
case XMLSTART =>
xmlLiteralPattern()
case _ =>
- if (isLiteral) literal()
+ if (isLiteral) literal(inPattern = true)
else {
syntaxErrorOrIncomplete(IllegalStartOfSimplePattern())
errorTermTree
@@ -1479,7 +1526,7 @@ object Parsers {
private def modOfToken(tok: Int): Mod = tok match {
case ABSTRACT => Mod.Abstract()
case FINAL => Mod.Final()
- case IMPLICIT => Mod.Implicit(ImplicitCommon)
+ case IMPLICIT => Mod.Implicit()
case INLINE => Mod.Inline()
case LAZY => Mod.Lazy()
case OVERRIDE => Mod.Override()
@@ -1572,6 +1619,9 @@ object Parsers {
normalize(loop(start))
}
+ def implicitMods(): Modifiers =
+ addMod(EmptyModifiers, atPos(accept(IMPLICIT)) { Mod.Implicit() })
+
/** Wrap annotation or constructor in New(...).<init> */
def wrapNew(tpt: Tree) = Select(New(tpt), nme.CONSTRUCTOR)
@@ -1677,9 +1727,9 @@ object Parsers {
* Param ::= id `:' ParamType [`=' Expr]
*/
def paramClauses(owner: Name, ofCaseClass: Boolean = false): List[List[ValDef]] = {
- var implicitMod: Mod = null
- var firstClauseOfCaseClass = ofCaseClass
+ var imods: Modifiers = EmptyModifiers
var implicitOffset = -1 // use once
+ var firstClauseOfCaseClass = ofCaseClass
def param(): ValDef = {
val start = in.offset
var mods = annotsAsMods()
@@ -1714,7 +1764,7 @@ object Parsers {
if (in.token == ARROW) {
if (owner.isTypeName && !(mods is Local))
syntaxError(s"${if (mods is Mutable) "`var'" else "`val'"} parameters may not be call-by-name")
- else if (implicitMod != null)
+ else if (imods.hasFlags)
syntaxError("implicit parameters may not be call-by-name")
}
paramType()
@@ -1726,7 +1776,7 @@ object Parsers {
mods = mods.withPos(mods.pos.union(Position(implicitOffset, implicitOffset)))
implicitOffset = -1
}
- if (implicitMod != null) mods = addMod(mods, implicitMod)
+ for (imod <- imods.mods) mods = addMod(mods, imod)
ValDef(name, tpt, default).withMods(mods)
}
}
@@ -1735,7 +1785,7 @@ object Parsers {
else {
if (in.token == IMPLICIT) {
implicitOffset = in.offset
- implicitMod = atPos(in.skipToken()) { Mod.Implicit(Implicit) }
+ imods = implicitMods()
}
commaSeparated(param)
}
@@ -1745,7 +1795,7 @@ object Parsers {
if (in.token == LPAREN)
paramClause() :: {
firstClauseOfCaseClass = false
- if (implicitMod == null) clauses() else Nil
+ if (imods.hasFlags) Nil else clauses()
}
else Nil
}
@@ -2210,9 +2260,9 @@ object Parsers {
stats.toList
}
- def localDef(start: Int, implicitFlag: FlagSet, implicitMod: Option[Mod] = None): Tree = {
- var mods = addFlag(defAnnotsMods(localModifierTokens), implicitFlag)
- if (implicitMod.nonEmpty) mods = mods.withAddedMod(implicitMod.get)
+ def localDef(start: Int, implicitMods: Modifiers = EmptyModifiers): Tree = {
+ var mods = defAnnotsMods(localModifierTokens)
+ for (imod <- implicitMods.mods) mods = addMod(mods, imod)
defOrDcl(start, mods)
}
@@ -2235,11 +2285,11 @@ object Parsers {
else if (isDefIntro(localModifierTokens))
if (in.token == IMPLICIT) {
val start = in.offset
- val mod = atPos(in.skipToken()) { Mod.Implicit(ImplicitCommon) }
- if (isIdent) stats += implicitClosure(start, Location.InBlock, Some(mod))
- else stats += localDef(start, ImplicitCommon, Some(mod))
+ val imods = implicitMods()
+ if (isBindingIntro) stats += implicitClosure(start, Location.InBlock, imods)
+ else stats += localDef(start, imods)
} else {
- stats += localDef(in.offset, EmptyFlags)
+ stats += localDef(in.offset)
}
else if (!isStatSep && (in.token != CASE)) {
exitOnError = mustStartStat