Skip to content

Instantly share code, notes, and snippets.

@ghik
Created April 24, 2015 10:26
Show Gist options
  • Select an option

  • Save ghik/2b02927737483d4faf84 to your computer and use it in GitHub Desktop.

Select an option

Save ghik/2b02927737483d4faf84 to your computer and use it in GitHub Desktop.
String interpolation + pattern matching = PROFIT
import RegexInterpolations._
val str = "My hovercraft is full of eels"
str match {
case r"""My (\w+)$vehicle is full of (\w+)$stuff""" =>
println(s"It is $stuff that my $vehicle is full of.")
}
import java.util.regex.Pattern
object RegexInterpolations {
implicit class Interpolations(sc: StringContext) {
def r = new PartsRegex(sc.parts)
}
class PartsRegex(parts: Seq[String]) {
private val regex = parts.mkString
private val matchedGroups = {
// indices of pattern's string interpolation arguments
val matchedGroupIndexes =
parts.iterator.map(_.length).scanLeft(0)(_ + _).map(_ - 1).drop(1).take(parts.size - 1).toSet
val matchedGroupsBuilder = Seq.newBuilder[Int]
var group = 0
var level = 0
var escaping = false
regex.zipWithIndex.foreach {
case ('(', _) if !escaping =>
group += 1
level += 1
case (')', index) if !escaping =>
level -= 1
if (matchedGroupIndexes contains index) {
matchedGroupsBuilder += (group - level)
}
case ('\\', _) if !escaping =>
escaping = true
case _ =>
escaping = false
}
matchedGroupsBuilder.result()
}
def unapplySeq(str: String) = {
val matcher = Pattern.compile(regex).matcher(str)
if (matcher.matches) Some(matchedGroups.map(matcher.group)) else None
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment