aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/src/dotty/tools/dotc/parsing/Parsers.scala117
-rw-r--r--compiler/src/dotty/tools/dotc/parsing/Tokens.scala2
-rw-r--r--docs/syntax-summary.txt12
3 files changed, 81 insertions, 50 deletions
diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala
index 5dd0df022..6fb10fd39 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
@@ -951,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]
@@ -985,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 {
@@ -1066,8 +1072,6 @@ object Parsers {
atPos(in.skipToken()) { Return(if (isExprIntro) expr() else EmptyTree, EmptyTree) }
case FOR =>
forExpr()
- case IMPLICIT =>
- implicitClosure(in.offset, location, atPos(in.skipToken()) { Mod.Implicit() })
case _ =>
expr1Rest(postfixExpr(), location)
}
@@ -1115,19 +1119,43 @@ 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) {
+ in.nextToken()
+ infixType()
+ }
+ 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: Mod): Tree = {
- val mods = Modifiers(Implicit).withAddedMod(implicitMod)
- 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) {
@@ -1581,6 +1609,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)
@@ -1686,9 +1717,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()
@@ -1723,7 +1754,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()
@@ -1735,7 +1766,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)
}
}
@@ -1744,7 +1775,7 @@ object Parsers {
else {
if (in.token == IMPLICIT) {
implicitOffset = in.offset
- implicitMod = atPos(in.skipToken()) { Mod.Implicit() }
+ imods = implicitMods()
}
commaSeparated(param)
}
@@ -1754,7 +1785,7 @@ object Parsers {
if (in.token == LPAREN)
paramClause() :: {
firstClauseOfCaseClass = false
- if (implicitMod == null) clauses() else Nil
+ if (imods.hasFlags) Nil else clauses()
}
else Nil
}
@@ -2217,9 +2248,9 @@ object Parsers {
stats.toList
}
- def localDef(start: Int, implicitMod: Option[Mod] = None): Tree = {
+ def localDef(start: Int, implicitMods: Modifiers = EmptyModifiers): Tree = {
var mods = defAnnotsMods(localModifierTokens)
- for (imod <- implicitMod) mods = (mods | ImplicitCommon).withAddedMod(imod)
+ for (imod <- implicitMods.mods) mods = addMod(mods, imod)
defOrDcl(start, mods)
}
@@ -2242,9 +2273,9 @@ object Parsers {
else if (isDefIntro(localModifierTokens))
if (in.token == IMPLICIT) {
val start = in.offset
- val mod = atPos(in.skipToken()) { Mod.Implicit() }
- if (isIdent) stats += implicitClosure(start, Location.InBlock, mod)
- else stats += localDef(start, Some(mod))
+ val imods = implicitMods()
+ if (isBindingIntro) stats += implicitClosure(start, Location.InBlock, imods)
+ else stats += localDef(start, imods)
} else {
stats += localDef(in.offset)
}
diff --git a/compiler/src/dotty/tools/dotc/parsing/Tokens.scala b/compiler/src/dotty/tools/dotc/parsing/Tokens.scala
index 5324207db..280832ef3 100644
--- a/compiler/src/dotty/tools/dotc/parsing/Tokens.scala
+++ b/compiler/src/dotty/tools/dotc/parsing/Tokens.scala
@@ -209,6 +209,8 @@ object Tokens extends TokensCommon {
final val canStartTypeTokens = literalTokens | identifierTokens | BitSet(
THIS, SUPER, USCORE, LPAREN, AT)
+ final val canStartBindingTokens = identifierTokens | BitSet(USCORE, LPAREN)
+
final val templateIntroTokens = BitSet(CLASS, TRAIT, OBJECT, CASECLASS, CASEOBJECT)
final val dclIntroTokens = BitSet(DEF, VAL, VAR, TYPE)
diff --git a/docs/syntax-summary.txt b/docs/syntax-summary.txt
index fe0ebc89c..d382507d3 100644
--- a/docs/syntax-summary.txt
+++ b/docs/syntax-summary.txt
@@ -125,13 +125,13 @@ grammar.
TypeBounds ::= [`>:' Type] [`<: Type] | INT TypeBoundsTree(lo, hi)
TypeParamBounds ::= TypeBounds {`<%' Type} {`:' Type} ContextBounds(typeBounds, tps)
- Expr ::= FunParams `=>' Expr Function(args, expr), Function(ValDef([implicit], id, TypeTree(), EmptyTree), expr)
+ Expr ::= [`implicit'] FunParams `=>' Expr Function(args, expr), Function(ValDef([implicit], id, TypeTree(), EmptyTree), expr)
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(Parens(cond), thenp, elsep?)
| `if' Expr `then' Expr [[semi] else Expr] If(cond, thenp, elsep?)
@@ -178,9 +178,7 @@ grammar.
| {Annotation} {LocalModifier} TmplDef
| Expr1
|
- ResultExpr ::= Expr1
- | (Bindings | ([`implicit'] id | `_') `:' ) `=>' Block
- Function(args, block) // block starts at =>
+
ForExpr ::= `for' (`(' Enumerators `)' | `{' Enumerators `}') ForYield(enums, expr)
{nl} [`yield'] Expr ForDo(enums, expr)
| `for' Enumerators (`do' Expr | `yield' Expr)
@@ -241,7 +239,7 @@ grammar.
DefParams ::= DefParam {`,' DefParam}
DefParam ::= {Annotation} [`inline'] Param ValDef(mods, id, tpe, expr) -- point of mods at id.
- Bindings ::= `(' Binding {`,' Binding `)' bindings
+ Bindings ::= `(' Binding {`,' Binding}] `)'
Binding ::= (id | `_') [`:' Type] ValDef(_, id, tpe, EmptyTree)
Modifier ::= LocalModifier