From 93e9623f5babee93c50eb1ce82e443d6771b693d Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Wed, 19 Jun 2013 06:23:02 -0700 Subject: SI-7737 Regex matches Char Enables Char extraction by regex. ``` val r = """(\p{Lower})""".r "cat"(0) match { case r(x) => true } val nc = """\p{Lower}""".r "cat"(0) match { case nc() => true } ``` --- src/library/scala/util/matching/Regex.scala | 38 ++++++++++++++ .../scala/util/matching/regextract-char.scala | 58 ++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 test/junit/scala/util/matching/regextract-char.scala diff --git a/src/library/scala/util/matching/Regex.scala b/src/library/scala/util/matching/Regex.scala index 8eac0a2520..439b30e714 100644 --- a/src/library/scala/util/matching/Regex.scala +++ b/src/library/scala/util/matching/Regex.scala @@ -194,6 +194,44 @@ class Regex private[matching](val pattern: Pattern, groupNames: String*) extends else None } + /** Tries to match the String representation of a [[scala.Char]]. + * If the match succeeds, the result is the first matching + * group if any groups are defined, or an empty Sequence otherwise. + * + * For example: + * + * {{{ + * val cat = "cat" + * // the case must consume the group to match + * val r = """(\p{Lower})""".r + * cat(0) match { case r(x) => true } + * cat(0) match { case r(_) => true } + * cat(0) match { case r(_*) => true } + * cat(0) match { case r() => true } // no match + * + * // there is no group to extract + * val r = """\p{Lower}""".r + * cat(0) match { case r(x) => true } // no match + * cat(0) match { case r(_) => true } // no match + * cat(0) match { case r(_*) => true } // matches + * cat(0) match { case r() => true } // matches + * + * // even if there are multiple groups, only one is returned + * val r = """((.))""".r + * cat(0) match { case r(_) => true } // matches + * cat(0) match { case r(_,_) => true } // no match + * }}} + * + * @param c The Char to match + * @return The match + */ + def unapplySeq(c: Char): Option[Seq[Char]] = { + val m = pattern matcher c.toString + if (runMatcher(m)) { + if (m.groupCount > 0) Some(m group 1) else Some(Nil) + } else None + } + /** Tries to match on a [[scala.util.matching.Regex.Match]]. * A previously failed match results in None. * If a successful match was made against the current pattern, then that result is used. diff --git a/test/junit/scala/util/matching/regextract-char.scala b/test/junit/scala/util/matching/regextract-char.scala new file mode 100644 index 0000000000..50fdcd9d46 --- /dev/null +++ b/test/junit/scala/util/matching/regextract-char.scala @@ -0,0 +1,58 @@ + +package scala.util.matching + +import org.junit.Assert._ +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +import PartialFunction._ + +/** Regex can match a Char. + * If the pattern includes a group, + * always return a single char. + */ +@RunWith(classOf[JUnit4]) +class CharRegexTest { + implicit class Averrable(val b: Boolean) /*extends AnyVal*/ { + def yes = assert(b) + def no = assert(!b) + } + val c: Char = 'c' // "cat"(0) + val d: Char = 'D' // "Dog"(0) + + @Test def comparesGroupCorrectly(): Unit = { + val r = """(\p{Lower})""".r + cond(c) { case r(x) => true } .yes + cond(c) { case r(_) => true } .yes + cond(c) { case r(_*) => true } .yes + cond(c) { case r() => true } .no + + cond(d) { case r(x) => true } .no + cond(d) { case r(_) => true } .no + cond(d) { case r(_*) => true } .no + cond(d) { case r() => true } .no + } + + @Test def comparesNoGroupCorrectly(): Unit = { + val rnc = """\p{Lower}""".r + cond(c) { case rnc(x) => true } .no + cond(c) { case rnc(_) => true } .no + cond(c) { case rnc(_*) => true } .yes + cond(c) { case rnc() => true } .yes + + cond(d) { case rnc(x) => true } .no + cond(d) { case rnc(_) => true } .no + cond(d) { case rnc(_*) => true } .no + cond(d) { case rnc() => true } .no + } + + @Test(expected = classOf[MatchError]) + def failCorrectly(): Unit = { + val headAndTail = """(\p{Lower})([a-z]+)""".r + val n = "cat"(0) match { + case headAndTail(ht @ _*) => ht.size + } + assert(false, s"Match size $n") + } +} -- cgit v1.2.3