aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-05-24 16:39:53 +0200
committerMartin Odersky <odersky@gmail.com>2013-05-24 16:39:59 +0200
commit991860936cbbedf6087a2e13ef69a61b69b3fa86 (patch)
treecd849b0090d876ded77d00c49beeea0db3249ce6
parentacc2b198692687394c9f8f84b16a0bec9ae12ee3 (diff)
downloaddotty-991860936cbbedf6087a2e13ef69a61b69b3fa86.tar.gz
dotty-991860936cbbedf6087a2e13ef69a61b69b3fa86.tar.bz2
dotty-991860936cbbedf6087a2e13ef69a61b69b3fa86.zip
Parser tweaks to handling new and templates.
-rw-r--r--src/dotty/tools/dotc/parsing/Parsers.scala49
-rw-r--r--src/dotty/tools/dotc/util/Positions.scala5
2 files changed, 39 insertions, 15 deletions
diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala
index 0599c4490..645929a6b 100644
--- a/src/dotty/tools/dotc/parsing/Parsers.scala
+++ b/src/dotty/tools/dotc/parsing/Parsers.scala
@@ -941,8 +941,7 @@ object Parsers {
atPos(id.pos.start, in.skipToken()) { Typed(id, infixType()) }
else
id
- val param = convertToParam(paramExpr, mods)
- closureRest(start, location, param :: Nil)
+ closureRest(start, location, convertToParam(paramExpr, mods) :: Nil)
}
def closureRest(start: Int, location: Location.Value, params: List[Tree]): Tree =
@@ -998,7 +997,11 @@ object Parsers {
blockExpr()
case NEW =>
canApply = false
- atPos(in.skipToken()) { New(template(emptyConstructor())) }
+ val start = in.skipToken()
+ templateOrNew(emptyConstructor()) match {
+ case impl: Template => atPos(start) { New(impl) }
+ case nu => adjustStart(start) { nu }
+ }
case _ =>
if (isLiteral) literal()
else {
@@ -1348,12 +1351,24 @@ object Parsers {
normalize(loop(start))
}
+ /** Wrap annotation or constructor in New(...).<init> */
+ def wrapNew(tpt: Tree) = Select(New(tpt), nme.CONSTRUCTOR)
+
+ /** Adjust start of annotation or constructor to position of preceding @ or new */
+ def adjustStart(start: Offset)(tree: Tree): Tree = {
+ val tree1 = tree match {
+ case Apply(fn, args) => tree.derivedApply(adjustStart(start)(fn), args)
+ case Select(qual, name) => tree.derivedSelect(adjustStart(start)(qual), name)
+ case _ => tree
+ }
+ if (start < tree1.pos.start) tree1.withPos(tree1.pos.withStart(start))
+ else tree1
+ }
+
/** Annotation ::= `@' SimpleType {ArgumentExprs}
*/
- def annot() = {
- accept(AT)
- argumentExprss(simpleType())
- }
+ def annot() =
+ adjustStart(accept(AT)) { argumentExprss(wrapNew(simpleType())) }
def annotations(skipNewLines: Boolean = false): List[Tree] = {
if (skipNewLines) newLineOptWhenFollowedBy(AT)
@@ -1763,19 +1778,27 @@ object Parsers {
/** ConstrApp ::= SimpleType {ParArgumentExprs}
*/
val constrApp = () =>
- parArgumentExprss(simpleType())
+ parArgumentExprss(wrapNew(simpleType()))
/** Template ::= ConstrApps [TemplateBody] | TemplateBody
* ConstrApps ::= ConstrApp {`with' ConstrApp}
*/
- def template(constr: DefDef): Template = {
+ def template(constr: DefDef): Template = templateOrNew(constr) match {
+ case impl: Template => impl
+ case parent => Template(constr, parent :: Nil, EmptyValDef(), Nil)
+ }
+
+ /** Same as template, but if {...} is missing and there's only one
+ * parent return the parent instead of a template. Called from New.
+ */
+ def templateOrNew(constr: DefDef): Tree = {
newLineOptWhenFollowedBy(LBRACE)
- if (in.token == LBRACE) {
- templateBodyOpt(constr, Nil)
- } else {
+ if (in.token == LBRACE) templateBodyOpt(constr, Nil)
+ else {
val parents = tokenSeparated(WITH, constrApp)
newLineOptWhenFollowedBy(LBRACE)
- templateBodyOpt(constr, parents)
+ if (in.token != LBRACE && parents.length == 1) parents.head
+ else templateBodyOpt(constr, parents)
}
}
diff --git a/src/dotty/tools/dotc/util/Positions.scala b/src/dotty/tools/dotc/util/Positions.scala
index 00d4e30ab..0a0a52e51 100644
--- a/src/dotty/tools/dotc/util/Positions.scala
+++ b/src/dotty/tools/dotc/util/Positions.scala
@@ -84,10 +84,11 @@ object Positions {
def endPos = Position(end)
/** A copy of this position with a different start */
- def withStart(start: Int) = fromOffsets(start, this.end, this.point - start)
+ def withStart(start: Int) =
+ fromOffsets(start, this.end, if (isSynthetic) SyntheticPointDelta else this.point - start)
/** A copy of this position with a different end */
- def withEnd(end: Int) = fromOffsets(this.start, end, this.point - this.start)
+ def withEnd(end: Int) = fromOffsets(this.start, end, pointDelta)
/** A copy of this position with a different point */
def withPoint(point: Int) = fromOffsets(this.start, this.end, point - this.start)