使用Scala/SBT解析器组合器重复依赖解析器
解析形式为使用Scala/SBT解析器组合器重复依赖解析器,scala,sbt,Scala,Sbt,解析形式为Value[,Value]+的字符串可以通过rep1sep(Value,,')轻松完成。当值解析器依赖于重复中先前解析的值时,是否有方法实现rep1sep功能?例如,强制要求每个值必须是唯一的 依赖解析器的标准技术是flatMap,但我很难让它正常工作。这里有一个这样的尝试: def Values(soFar: Set[Value]): Parser[Set[Value]] = Value(soFar) flatMap { v => (',' ~> Values(soF
Value[,Value]+
的字符串可以通过rep1sep(Value,,')
轻松完成。当值解析器依赖于重复中先前解析的值时,是否有方法实现rep1sep功能?例如,强制要求每个值必须是唯一的
依赖解析器的标准技术是flatMap,但我很难让它正常工作。这里有一个这样的尝试:
def Values(soFar: Set[Value]): Parser[Set[Value]] =
Value(soFar) flatMap { v => (',' ~> Values(soFar + v)).?.map { _ getOrElse soFar } }
def Value(soFar: Set[Value]): Parser[Value] =
Num+ flatMap { v => if (soFar.contains(v)) failure("%d already appears".format(v)) else success(v) }
一般来说,我需要一种rep1sep形式,其中parser参数是从Seq[a]
到parser[a]
的函数:
def rep1sepDependent(rep: Seq[A] => Parser[A], sep: Parser[Any]): Seq[A] = ???
注意:我意识到用例在这里是有问题的,验证唯一性在解析后处理得更好。我在使用SBT解析组合符来完成制表符时遇到了这个问题——具体地说,我只想为用户尚未输入的那些键提供键/值对的完成选项。请参阅和可构建的SBT项目。以下内容不像您的
rep1sependent
那样通用,但它可以工作:
def rep1sepUnique[T](p: => Parser[T], q: => Parser[Any]) = {
def checkIfSeen(seen: Set[T]): Parser[Set[T]] = q ~> p >> (v =>
if (seen(v)) failure("Duplicate: %s".format(v)) else checkIfSeen(seen + v)
) | success(seen)
p >> (v => checkIfSeen(Set(v)))
}
例如:
import scala.util.parsing.combinator._
object parseUniqueWords extends RegexParsers {
def rep1sepUnique[T](p: => Parser[T], q: => Parser[Any]) = {
def checkIfSeen(seen: Set[T]): Parser[Set[T]] = q ~> p >> (v =>
if (seen(v)) failure("Duplicate: %s".format(v)) else checkIfSeen(seen + v)
) | success(seen)
p >> (v => checkIfSeen(Set(v)))
}
def apply(s: String) = parseAll(rep1sepUnique("\\w+".r, ","), s)
}
这给了我们:
scala> parseUniqueWords("aaa,bb,c")
res0: parseUniqueWords.ParseResult[Set[String]] = [1.9] parsed: Set(aaa, bb, c)
scala> parseUniqueWords("aaa,bb,aaa")
res1: parseUniqueWords.ParseResult[Set[String]] =
[1.11] failure: Duplicate: aaa
aaa,bb,aaa
^
这就是我们想要的。这里有一个解决方案,用于选择一些辅助完成的项目,避免重复的项目:
def select1(items: Iterable[String], separator: Parser[_] = Space) =
token(separator ~> StringBasic.examples(FixedSetExamples(items)))
def selectSome(items: Seq[String], separator: Parser[_] = Space): Parser[Seq[String]] = {
select1(items, separator).flatMap { v ⇒
val remaining = items filter { _ != v }
if (remaining.size == 0)
success(v :: Nil)
else
selectSome(remaining).?.map(v +: _.getOrElse(Seq()))
}
}
使用示例:
val myTask = inputTask[Unit]("Print selected numbers")
myTask := {
val numbers = selectSome(Seq("One", "Two", "Three", "Four")).parsed
numbers.foreach{ println _ }
}
使用SBT 0.13.9测试。谢谢!我推广到rep1sepDep,但我仍然面临着与当前实现相同的选项卡完成问题。我现在想知道,在使用flatMap时,这是否是SBT完成支持中的一个怪癖。详细信息:scala.util.parsing和SBT解析器兼容吗?我回答自己:不,它们相似但不完全相同
scala.util.parsing
不支持自动完成。@david.perez它只是flatMap
(和)的别名。