Parsing 使用(读取a,显示a)解析二进制树

Parsing 使用(读取a,显示a)解析二进制树,parsing,haskell,Parsing,Haskell,我在如何开始这个问题上有点困难。我应该解析一个二叉树的字符串表示,并检查叶的内容是否有有效的字母,如果有,则创建树,否则返回“”用于解析失败,而不进行派生(Show,Read) 使用一个典型的解析器库,我可以使用 parseTree = do{item; symb "Leaf"; x <- string; return Leaf (read x)} +++ {item; symb "Branch"; item;x <- parseTree; item; item; y <- p

我在如何开始这个问题上有点困难。我应该解析一个二叉树的字符串表示,并检查叶的内容是否有有效的字母,如果有,则创建树,否则返回“”用于解析失败,而不进行派生(Show,Read)

使用一个典型的解析器库,我可以使用

parseTree = do{item; symb "Leaf"; x <- string; return Leaf (read x)} +++ {item; symb "Branch"; item;x <- parseTree; item; item; y <- parseTree; item; return (Branch x y)} 

parseTree=do{item;symb“Leaf”;x正如Willem所说,您可以派生
Read
免费获取此函数:

数据字母=A | B | C | D | E | F | G
派生(显示、相等、枚举、有界、读取)
数据二叉树a=叶a |分支(二叉树a)(二叉树a)
推导(等式、显示、读取)
二叉树字母
t=枝(叶A)(枝(枝(叶A)(叶C))(叶D))
试一试:

λ>t==读取(显示t)
真的
创建树else return“”,用于解析所有未进行
派生(显示、读取)
的失败

parseTree=do{item;符号“Leaf”;…+++…}
我不确定从字符串中读取二叉树的上下文中“”是什么意思:根据您对二叉树的定义,树不能为空,因为即使
Leaf
也至少包含一个字母。因此,您可能正在寻找一个函数
string->maybe(二叉树字母)

由于您不愿意使用派生的
Show
Read
实例,因此这必须是编写解析器的练习。您可以用以下方式构造递归下降解析器:

parseLetter::String->Maybe(字母,字符串)
解析字母s=。。。
parseTree::String->Maybe(二进制树字母,字符串)
解析树
|“叶”`isPrefixOf`s=。。。
|“Branch”`isPrefixOf`s=。。。
|否则=没有
这里,
(…,String)
是正在被解析的字符串的剩余部分,子解析器没有使用它。例如,在解析
分支(叶a)(叶B)
时,当
解析的字母
解析了
a
,它可能会为其调用者返回
(a),(叶B)

但是,请注意,要获得与
派生Read
质量相当的内容,需要在空格和括号方面非常灵活:

λ> read "Branch ( Leaf A)(  Branch (  Leaf B )   ((Leaf C) )   ) " :: BinaryTree Letter
Branch (Leaf A) (Branch (Leaf B) (Leaf C))
我不确定如何处理穿过树叶或树枝的情况

穿过一片叶子意味着解析一个字母

遍历分支意味着递归调用解析器


您可能希望使用更高效、更符合人体工程学的解析库,如(它甚至包含一个读取树类型的示例),或者您可能希望使用解析器组合器框架,如或。

您可以使用
派生(Show,Read)
在您的
数据二叉树中
,它将自己生成一个解析器。函数代码有一些不完全正确的地方,例如,它应该是
返回(分支xy)
λ> read "Branch ( Leaf A)(  Branch (  Leaf B )   ((Leaf C) )   ) " :: BinaryTree Letter
Branch (Leaf A) (Branch (Leaf B) (Leaf C))