我想知道是否可以从下面的语法中获得匹配正则表达式生成的MatchData。
object DateParser extends JavaTokenParsers {
....
val dateLiteral = """(\d{4}[-/])?(\d\d[-/])?(\d\d)""".r ^^ {
... get MatchData
}
}
当然,一个选项是在块内再次执行匹配,但由于RegexParser已经执行了匹配,我希望它将MatchData传递给块,或者存储它?
答案 0 :(得分:20)
以下是将Regex
转换为Parser
的隐式定义:
/** A parser that matches a regex string */
implicit def regex(r: Regex): Parser[String] = new Parser[String] {
def apply(in: Input) = {
val source = in.source
val offset = in.offset
val start = handleWhiteSpace(source, offset)
(r findPrefixMatchOf (source.subSequence(start, source.length))) match {
case Some(matched) =>
Success(source.subSequence(start, start + matched.end).toString,
in.drop(start + matched.end - offset))
case None =>
Failure("string matching regex `"+r+"' expected but `"+in.first+"' found", in.drop(start - offset))
}
}
}
只是改编它:
object X extends RegexParsers {
/** A parser that matches a regex string and returns the Match */
def regexMatch(r: Regex): Parser[Regex.Match] = new Parser[Regex.Match] {
def apply(in: Input) = {
val source = in.source
val offset = in.offset
val start = handleWhiteSpace(source, offset)
(r findPrefixMatchOf (source.subSequence(start, source.length))) match {
case Some(matched) =>
Success(matched,
in.drop(start + matched.end - offset))
case None =>
Failure("string matching regex `"+r+"' expected but `"+in.first+"' found", in.drop(start - offset))
}
}
}
val t = regexMatch("""(\d\d)/(\d\d)/(\d\d\d\d)""".r) ^^ { case m => (m.group(1), m.group(2), m.group(3)) }
}
示例:
scala> X.parseAll(X.t, "23/03/1971")
res8: X.ParseResult[(String, String, String)] = [1.11] parsed: (23,03,1971)
答案 1 :(得分:3)
不,你不能这样做。如果你看一下将正则表达式转换为Parser时使用的Parser的定义,它会丢弃所有上下文并返回完整匹配的字符串:
你还有其他几个选择:
第一个看起来像
val separator = "-" | "/"
val year = ("""\d{4}"""r) <~ separator
val month = ("""\d\d"""r) <~ separator
val day = """\d\d"""r
val date = ((year?) ~ (month?) ~ day) map {
case year ~ month ~ day =>
(year.getOrElse("2009"), month.getOrElse("11"), day)
}
<~
表示“将这两个令牌放在一起,但只给出第一个令牌的结果。
~
表示“将这两个令牌放在一起并将它们绑定在一个模式匹配的对象中。
?
表示解析器是可选的,将返回一个选项。
.getOrElse
位为解析器未定义值时提供默认值。
答案 2 :(得分:1)
在RegexParsers实例中使用正则表达式时,RegexParsers中的隐式def正则表达式(正则表达式):解析器[String] 用于将Regex应用于输入。在当前输入成功应用RE时产生的Match实例用于在regex()方法中构造Success,但仅使用其“end”值,因此任何捕获的子匹配在方法时被丢弃回报。
就目前而言(在我看过的2.7源文件中),我相信你运气不好。
答案 3 :(得分:0)
我使用scala 2.8.1遇到了类似的问题,并尝试使用RegexParsers
类解析“name:value”形式的输入:
package scalucene.query
import scala.util.matching.Regex
import scala.util.parsing.combinator._
object QueryParser extends RegexParsers {
override def skipWhitespace = false
private def quoted = regex(new Regex("\"[^\"]+"))
private def colon = regex(new Regex(":"))
private def word = regex(new Regex("\\w+"))
private def fielded = (regex(new Regex("[^:]+")) <~ colon) ~ word
private def term = (fielded | word | quoted)
def parseItem(str: String) = parse(term, str)
}
在解析之后,您似乎可以抓住匹配的组:
QueryParser.parseItem("nameExample:valueExample") match {
case QueryParser.Success(result:scala.util.parsing.combinator.Parsers$$tilde, _) => {
println("Name: " + result.productElement(0) + " value: " + result.productElement(1))
}
}