Tg.*_*Tg. 11 parsing scala combinators
我从组合库中编写了一些解析器.我想要一个泛型函数,将任何大小的nest变换成一个列表.这该怎么做 ?
这是我使用的解析器的例子(我的真正的解析器有一个很长的链〜所以我想避免我现在的解决方案,这在下面的评论).
object CombinatorParser extends RegexParsers {
lazy val a = "a"
lazy val b = "b"
lazy val c = "c"
lazy val content = a ~ b ~ c // ^^ {case a~b => a::b::c::Nil work but I want something more general that work for any ~ length.
}
object CombinatorTesting {
def main(args:Array[String]) {
val testChar = "abc"
val output = CombinatorParser.parseAll(CombinatorParser.content, testChar)
println(output) // ((a~b)~c) but I want List(a,b,c)
}
}
Run Code Online (Sandbox Code Playgroud)
Mil*_*bin 20
这是一种很好的(并且相当简单)应用程序,适用于无形中示例的通用编程技术.
根据你的定义,
object CombinatorParser extends RegexParsers {
lazy val a = "a"
lazy val b = "b"
lazy val c = "c"
lazy val content = a ~ b ~ c
}
Run Code Online (Sandbox Code Playgroud)
我们可以递归地定义一个类型类,它会将它的结果展平如下,
import CombinatorParser._
Run Code Online (Sandbox Code Playgroud)
首先,我们定义一个特征(抽象地)将任意匹配展平M为a List[String],
trait Flatten[M] extends (M => List[String]) {
def apply(m : M) : List[String]
}
Run Code Online (Sandbox Code Playgroud)
然后,我们提供的所有形状类型的类实例M,我们有兴趣:在这种情况下,String,A ~ B和ParseResult[T](其中A,B并且T是其中有各种类型的Flatten实例),
// Flatten instance for String
implicit def flattenString = new Flatten[String] {
def apply(m : String) = List(m)
}
// Flatten instance for `A ~ B`. Requires Flatten instances for `A` and `B`.
implicit def flattenPattern[A, B]
(implicit flattenA : Flatten[A], flattenB : Flatten[B]) =
new Flatten[A ~ B] {
def apply(m : A ~ B) = m match {
case a ~ b => flattenA(a) ::: flattenB(b)
}
}
// Flatten instance for ParseResult[T]. Requires a Flatten instance for T.
implicit def flattenParseResult[T]
(implicit flattenT : Flatten[T]) = new Flatten[ParseResult[T]] {
def apply(p : ParseResult[T]) = (p map flattenT) getOrElse Nil
}
Run Code Online (Sandbox Code Playgroud)
最后,我们可以定义一个便捷函数来简化应用Flatten实例来解析结果,
def flatten[P](p : P)(implicit flatten : Flatten[P]) = flatten(p)
Run Code Online (Sandbox Code Playgroud)
现在我们准备好了,
val testChar = "abc"
val output = parseAll(content, testChar)
println(output) // ((a~b)~c) but I want List(a, b, c)
val flattenedOutput = flatten(output)
println(flattenedOutput) // List(a, b, c)
Run Code Online (Sandbox Code Playgroud)
小智 6
如果您更喜欢没有通用编程的解决方案......
def flatten(res: Any): List[String] = res match {
case x ~ y => flatten(x) ::: flatten(y)
case None => Nil
case Some(x) => flatten(x)
case x:String => List(x)
}
val testChar = "abc"
val output = CombinatorParser.parseAll(CombinatorParser.content, testChar).getOrElse(None)
println(flatten(output))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1286 次 |
| 最近记录: |