我有以下简单的解析器(实际上它有点复杂,但这个简单的例子说明问题是一样的)。
我有第一个匹配name
的解析器,String
由于某种原因而被转换为Any
类型。此外,第二个2列表是可选的,因此它们可能存在或者它们不存在。但是在我的域对象中,如果它们不是,它们各自的集合将是空的。
我似乎无法理解第一个问题。出于某种原因,当我删除第一个<~
时,名称再次成为String
,剩下的唯一错误是带有可选列表的错误,我认为我可以通过匹配Option
实例,虽然我将拥有相当多的这些可选列表,但我不想要它们的所有排列,包括Some和None。
最佳方法是什么?
import scala.util.parsing.combinator.RegexParsers
case class Test(name: String, extensions : Set[String] = Set[String](),
objects : Set[String] = Set[String]())
object TestParser extends RegexParsers {
def test = "((:name" ~> name <~ ")" ~ (extensions_def?) ~ (objects_def?) <~ ")" ^^ {
case name ~ extensions_def ~ objects_def =>
Test(name, extensions_def, objects_def)
}
def name : Parser[String] = """[a-zA-Z][a-zA-Z0-9_-]*""".r
def extensions_def = "(:extensions" ~> (extensions_key+) <~ ")"
def extensions_key = ":funcs" | ":literals" | ":numbers"
def objects_def = "(:objects" ~> (name+) <~ ")"
def main(args: Array[String]) {
val s = "(test hello (:extensions :funcs :numbers) (:objects obj1 obj2 obj3))"
val res = parseAll(test, s)
res match {
case Success(r, n) => println(r)
case Failure(msg, n) => println(msg)
case Error(msg, n) => println(msg)
}
}
}
答案 0 :(得分:1)
您必须在括号内对"(:name" ~> name <~ ")"
进行分组(或者您可以像name_def
和extensions_def
那样定义objects_def
。至于匹配None/Some
排列,可能更容易匹配选项并定义optionListToSet
方法,如下所示:
import scala.util.parsing.combinator.RegexParsers
case class Test(name: String, extensions : Set[String] = Set[String](),
objects : Set[String] = Set[String]())
object TestParser extends RegexParsers {
def test = "(" ~> ("(:name" ~> name <~ ")") ~ (extensions_def?) ~ (objects_def?) <~ ")" ^^ {
case name ~ extensions_def ~ objects_def =>
Test(name, optionListToSet(extensions_def), optionListToSet(objects_def))
}
def optionListToSet[A](o:Option[List[A]]) = o.map(_.toSet).getOrElse(Set[A]())
def name : Parser[String] = """[a-zA-Z][a-zA-Z0-9_-]*""".r
def extensions_def = "(:extensions" ~> (extensions_key+) <~ ")"
def extensions_key = ":funcs" | ":literals" | ":numbers"
def objects_def = "(:objects" ~> (name+) <~ ")"
def main(args: Array[String]) {
val s1 = "((:name test) (:extensions :funcs :numbers) (:objects obj1 obj2 obj3))"
val res1 = parseAll(test, s1)
res1 match {
case Success(r, n) => println(r)
case Failure(msg, n) => println(msg)
case Error(msg, n) => println(msg)
}
val s2 = "((:name test) (:objects obj1 obj2 obj3))"
val res2 = parseAll(test, s2)
res2 match {
case Success(r, n) => println(r)
case Failure(msg, n) => println(msg)
case Error(msg, n) => println(msg)
}
}
}
Output :
Test(test,Set(:funcs, :numbers),Set(obj1, obj2, obj3))
Test(test,Set(),Set(obj1, obj2, obj3))