Parser组合器可选部件

时间:2013-12-13 15:31:43

标签: scala parser-combinators

这是我第一次使用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丢失,它应默认为“对象”。 如何最好地解决这个问题?

1 个答案:

答案 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)
}