Parsing 在scala中使用解析器组合器创建递归数据结构

Parsing 在scala中使用解析器组合器创建递归数据结构,parsing,scala,tree,parser-combinators,Parsing,Scala,Tree,Parser Combinators,我是scala的初学者,正在努力学习scala。其中一个问题涉及从字符串到树数据结构的转换。我可以“手动”完成,我还想看看如何使用Scala的parser combinator库完成 树的数据结构是 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.t

我是scala的初学者,正在努力学习scala。其中一个问题涉及从字符串到树数据结构的转换。我可以“手动”完成,我还想看看如何使用Scala的parser combinator库完成

树的数据结构是

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 
}
但是如何使用解析库来构建树呢?我知道我可以使用
^ ^
将一些字符串转换为整数。我之所以感到困惑,是因为在创建
节点的实例时需要“了解”左右子树。我该怎么做,或者这是我想做些不同事情的信号


我是不是最好拿走解析器返回的东西(
((((((((a~((((((b~)d~,)~e~))~,)((((c~)~,)((((f~)g~,)~(((f~)g~,)))~)上面的示例输入,然后在此基础上构建树,与其使用解析器操作符,如
^
^ ^ ^
直接构建树?

可以使用
^ ^
干净地完成此操作,而且您非常接近:

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
}

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

Hah,我认为
JavaTokenParsers
是某种Java库。你又想出了一个更好的答案!你没有
T(…)
是对的。我省略了
“”=>(\u=>End)
位。为了清楚起见,我删除了我的答案。谢谢你的答案和关于如何解决这类问题的元答案。现在,我需要重读“Scala编程”中关于解析器的章节,看看我还遗漏了什么。
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 . .) .)))