【问题标题】:Parser combinator optional parts解析器组合器可选部分
【发布时间】:2013-12-13 15:31:43
【问题描述】:

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

【问题讨论】:

    标签: scala parser-combinators


    【解决方案1】:

    这里发生了几件事。

    首先是 ~ 和 ?意味着不是将 Parser[List[String]] 的 (name+) 与 ("-" ~> parent_type ) 结合起来吗?哪个是 Parser[Option[String]] 您实际上将整个内容包装在其中?如果有意义的话,就得到一个 Parser[Option[~[List[String],String]] 。

    最简单的解决方案是使用一组额外的括号。

    所以你要开始:

    def type_list = ((name+) ~ (("-" ~> parent_type)?))
    

    然后在映射函数中,您将收到一个 ~[List[String],Option[String]],其中包含名称列表和可选的 parent_type。 在模式匹配方面,您总是得到名称 ~ parent_type,其中后者是一个选项 [字符串]。 所以基本上你的第二种模式是无效的。

    所以你可以这样做:

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

    【讨论】:

    • 谢谢...这些单子仍然设法让我偏离轨道。也感谢更简单的版本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-13
    • 2015-09-15
    • 2020-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-06
    相关资源
    最近更新 更多