这是我第一次使用scala的解析器组合器。 我有这种情况,我有一个'类型'列表,他们可以扩展其他类型,或不。 如果他们这样做,我只是在类型及其父类型之间创建一个映射。 如果不是,我只是将类型映射到'对象'。 (类型只是字符串名称)
它们是这样写的:
type1 type2 type3 - parentType
或
type0a type0b
在这种情况下,它们将隐式为- object
我尝试以下列方式实现它,但它没有编译。它说它需要一个Option [~List [String,String]并找到〜[a,b]。它还说它无法在第一个中找到值名称进行理解,实际上它在案例模式中指定匹配。现在有点困惑实际发生了什么。
def type_list = ((name+) ~ ("-" ~> parent_type)?) ^^ {
case names ~ parent_type => for (name <- names) yield name -> parent_type
case names => for (name <- names) yield name -> "object"
}
def name = """[a-zA-Z\d]+""".r
实际上我只想让它返回Map[String, String]
,如果parent_type
丢失,它应默认为“对象”。
如何最好地解决这个问题?
答案 0 :(得分:3)
这里有几件事情。
首先是〜和?的优先级意味着不是将(名称+)组合为Parser [List [String]]而不是(“ - ”〜&gt; parent_type)?这是一个Parser [Option [String]]你实际上是把整个东西包裹起来的?所以如果有意义的话,得到一个Parser [Option [〜[List [String],String]]。
最简单的解决方案是使用一组额外的括号。
所以你想从:
开始def type_list = ((name+) ~ (("-" ~> parent_type)?))
然后在映射函数中,您将收到的是一个〜[List [String],Option [String]],其中包含名称列表和可选的parent_type。 在模式匹配方面,你总是得到name~parent_type,后者是一个Option [String]。 所以基本上你的第二种模式是无效的。
所以你可以这样做:
def type_list = ((name+) ~ (("-" ~> parent_type)?)) ^^ {
case names ~ Some(parent_type) => for (name <- names) yield name -> parent_type
case names ~ None => for (name <- names) yield name -> "object"
}
或者您可以将其简化为:
def type_list = ((name+) ~ (("-" ~> parent_type)?)) ^^ {
case names ~ parent_type => for (name <- names) yield name -> parent_type.getOrElse("object)
}