【问题标题】:Creating a recursive data structure using parser combinators in scala在 scala 中使用解析器组合器创建递归数据结构
【发布时间】:2012-12-27 23:25:13
【问题描述】:

我是 scala 的初学者,正在使用 S99 尝试学习 scala。其中一个问题涉及从字符串转换为树数据结构。我可以“手动”完成它,我还想看看如何使用 Scala 的解析器组合器库来完成它。

树的数据结构是

sealed abstract class Tree[+T]
case class Node[+T](value: T, left: Tree[T], right: Tree[T]) extends Tree[T] {
  override def toString = "T(" + value.toString + " " + left.toString + " " + right.toString + ")"
}
case object End extends Tree[Nothing] {
  override def toString = "."
}
object Node {
  def apply[T](value: T): Node[T] = Node(value, End, End)
}    

输入应该是一个字符串,像这样:a(b(d,e),c(,f(g,)))

我可以使用类似的东西来解析字符串

trait Tree extends JavaTokenParsers{
  def leaf: Parser[Any] = ident
  def child: Parser[Any] = node | leaf | ""
  def node: Parser[Any] = ident~"("~child~","~child~")" | leaf 
}

但是如何使用解析库来构建树呢?我知道我可以使用^^ 将例如一些字符串转换为整数。我的困惑来自在创建Node 的实例时需要“知道”左右子树。我该怎么做,或者这是否表明我想做一些不同的事情?

我最好采用解析器返回的东西((((((a~()~(((((b~()~d)~,)~e)~)))~,)~(((((c~()~)~,)~(((((f~()~g)~,)~)~)))~)))~)) 用于上面的示例输入),并基于它构建树,而不是使用像 ^^^^^ 这样的解析器运算符直接构建树?

【问题讨论】:

    标签: parsing scala tree parser-combinators


    【解决方案1】:

    使用^^ 可以干净利落地执行此操作,而且您已经非常接近:

    object TreeParser extends JavaTokenParsers{
      def leaf: Parser[Node[String]] = ident ^^ (Node(_))
      def child: Parser[Tree[String]] = node | leaf | "" ^^ (_ => End)
      def node: Parser[Tree[String]] =
        ident ~ ("(" ~> child) ~ ("," ~> child <~ ")") ^^ {
          case v ~ l ~ r => Node(v, l, r)
        } | leaf
    }
    

    现在:

    scala> TreeParser.parseAll(TreeParser.node, "a(b(d,e),c(,f(g,)))").get
    res0: Tree[String] = T(a T(b T(d . .) T(e . .)) T(c . T(f T(g . .) .)))
    

    在我看来,解决此类问题的最简单方法是在解析器方法中键入您想要的结果,然后使用^^ 添加适当的映射操作,直到编译器满意为止。

    【讨论】:

    • 哈,我以为JavaTokenParsers 是一些Java 库。你又想出了一个更好的答案!
    • 你是对的,从来没有T(. .)。我省略了"" =&gt; (_ =&gt; End) 位。为了清楚起见,我删除了我的答案。
    • 感谢您提供有关如何解决此类问题的答案和元答案。现在,我需要重新阅读“Scala 编程”中关于解析器的章节,看看我还遗漏了什么。
    猜你喜欢
    • 2012-10-04
    • 1970-01-01
    • 1970-01-01
    • 2022-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-05
    • 1970-01-01
    相关资源
    最近更新 更多