summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
diff options
context:
space:
mode:
authorSom Snytt <som.snytt@gmail.com>2013-07-27 14:49:57 -0700
committerSom Snytt <som.snytt@gmail.com>2013-08-12 11:59:20 -0700
commit67d94f681fe17b18bb9ba1a3cec0a15a48bc3251 (patch)
tree7a2bdc5afbb48a6b5de130467337e56ddae7250d /src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
parente7876d5c41bbea0ee4679815edb5dc1ecef4c6a9 (diff)
downloadscala-67d94f681fe17b18bb9ba1a3cec0a15a48bc3251.tar.gz
scala-67d94f681fe17b18bb9ba1a3cec0a15a48bc3251.tar.bz2
scala-67d94f681fe17b18bb9ba1a3cec0a15a48bc3251.zip
SI-7715 String inpatternation s"$_" for s"${_}"
In a pattern, ``` scala> implicit class RX(val sc: StringContext) { | def rx = sc.parts.mkString("(.+)").r } defined class RX scala> "2 by 4" match { case rx"$a by $_" => a } res0: String = 2 scala> val rx"$_ by $b" = "2 by 4" b: String = 4 ```
Diffstat (limited to 'src/compiler/scala/tools/nsc/ast/parser/Parsers.scala')
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala105
1 files changed, 63 insertions, 42 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index eb924a811b..b8dc5b92e6 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -1137,32 +1137,70 @@ self =>
})
}
- private def interpolatedString(inPattern: Boolean): Tree = atPos(in.offset) {
- val start = in.offset
- val interpolator = in.name
+ /** Handle placeholder syntax.
+ * If evaluating the tree produces placeholders, then make it a function.
+ */
+ private def withPlaceholders(tree: =>Tree, isAny: Boolean): Tree = {
+ val savedPlaceholderParams = placeholderParams
+ placeholderParams = List()
+ var res = tree
+ if (placeholderParams.nonEmpty && !isWildcard(res)) {
+ res = atPos(res.pos)(Function(placeholderParams.reverse, res))
+ if (isAny) placeholderParams foreach (_.tpt match {
+ case tpt @ TypeTree() => tpt setType definitions.AnyTpe
+ case _ => // some ascription
+ })
+ placeholderParams = List()
+ }
+ placeholderParams = placeholderParams ::: savedPlaceholderParams
+ res
+ }
- val partsBuf = new ListBuffer[Tree]
- val exprBuf = new ListBuffer[Tree]
+ /** Consume a USCORE and create a fresh synthetic placeholder param. */
+ private def freshPlaceholder(): Tree = {
+ val start = in.offset
+ val pname = freshName("x$")
in.nextToken()
- while (in.token == STRINGPART) {
- partsBuf += literal()
- exprBuf += (
- if (inPattern) dropAnyBraces(pattern())
- else in.token match {
- case IDENTIFIER => atPos(in.offset)(Ident(ident()))
- case LBRACE => expr()
- case THIS => in.nextToken(); atPos(in.offset)(This(tpnme.EMPTY))
- case _ => syntaxErrorOrIncompleteAnd("error in interpolated string: identifier or block expected", skipIt = true)(EmptyTree)
- }
- )
- }
- if (in.token == STRINGLIT) partsBuf += literal()
+ val id = atPos(start)(Ident(pname))
+ val param = atPos(id.pos.focus)(gen.mkSyntheticParam(pname.toTermName))
+ placeholderParams = param :: placeholderParams
+ id
+ }
+
+ private def interpolatedString(inPattern: Boolean): Tree = {
+ def errpolation() = syntaxErrorOrIncompleteAnd("error in interpolated string: identifier or block expected",
+ skipIt = true)(EmptyTree)
+ // Like Swiss cheese, with holes
+ def stringCheese: Tree = atPos(in.offset) {
+ val start = in.offset
+ val interpolator = in.name
+
+ val partsBuf = new ListBuffer[Tree]
+ val exprBuf = new ListBuffer[Tree]
+ in.nextToken()
+ while (in.token == STRINGPART) {
+ partsBuf += literal()
+ exprBuf += (
+ if (inPattern) dropAnyBraces(pattern())
+ else in.token match {
+ case IDENTIFIER => atPos(in.offset)(Ident(ident()))
+ //case USCORE => freshPlaceholder() // ifonly etapolation
+ case LBRACE => expr() // dropAnyBraces(expr0(Local))
+ case THIS => in.nextToken(); atPos(in.offset)(This(tpnme.EMPTY))
+ case _ => errpolation()
+ }
+ )
+ }
+ if (in.token == STRINGLIT) partsBuf += literal()
- val t1 = atPos(o2p(start)) { Ident(nme.StringContext) }
- val t2 = atPos(start) { Apply(t1, partsBuf.toList) }
- t2 setPos t2.pos.makeTransparent
- val t3 = Select(t2, interpolator) setPos t2.pos
- atPos(start) { Apply(t3, exprBuf.toList) }
+ val t1 = atPos(o2p(start)) { Ident(nme.StringContext) }
+ val t2 = atPos(start) { Apply(t1, partsBuf.toList) }
+ t2 setPos t2.pos.makeTransparent
+ val t3 = Select(t2, interpolator) setPos t2.pos
+ atPos(start) { Apply(t3, exprBuf.toList) }
+ }
+ if (inPattern) stringCheese
+ else withPlaceholders(stringCheese, isAny = true) // strinterpolator params are Any* by definition
}
/* ------------- NEW LINES ------------------------------------------------- */
@@ -1260,18 +1298,7 @@ self =>
*/
def expr(): Tree = expr(Local)
- def expr(location: Int): Tree = {
- val savedPlaceholderParams = placeholderParams
- placeholderParams = List()
- var res = expr0(location)
- if (!placeholderParams.isEmpty && !isWildcard(res)) {
- res = atPos(res.pos){ Function(placeholderParams.reverse, res) }
- placeholderParams = List()
- }
- placeholderParams = placeholderParams ::: savedPlaceholderParams
- res
- }
-
+ def expr(location: Int): Tree = withPlaceholders(expr0(location), isAny = false)
def expr0(location: Int): Tree = (in.token: @scala.annotation.switch) match {
case IF =>
@@ -1520,13 +1547,7 @@ self =>
case IDENTIFIER | BACKQUOTED_IDENT | THIS | SUPER =>
path(thisOK = true, typeOK = false)
case USCORE =>
- val start = in.offset
- val pname = freshName("x$")
- in.nextToken()
- val id = atPos(start) (Ident(pname))
- val param = atPos(id.pos.focus){ gen.mkSyntheticParam(pname.toTermName) }
- placeholderParams = param :: placeholderParams
- id
+ freshPlaceholder()
case LPAREN =>
atPos(in.offset)(makeParens(commaSeparated(expr())))
case LBRACE =>