用树木简化Haskell中的正则表达式

时间:2015-01-20 01:42:29

标签: regex haskell tree

我有正则表达式(RE)的数据结构,到目前为止我没有任何修改RE的函数:

data Regex a = Letter a | Emptyword | Concat (Regex a) (Regex a) | Emptyset | Or (Regex a) (Regex a) | Star (Regex a)
    deriving (Show, Eq)

我想为我的RE实现一个简化算法。为此,我认为我应该首先将RE表示为树,根据某些等价更新树,然后将其转换回RE。我的理由是,对于树,我将具有查找,提取和附加子树,更新值等功能。

但是,我很难找到一个提供这些功能的树模块,并且很容易让初学者学习。 我发现这个avl-tree package然而,它看起来非常大。

我希望对我的方法提供替代建议,并提供有关支持所提及功能的简单树模块的建议。 请注意,我是Haskell的初学者,我还不了解monad,并且我对简化RE的实现不感兴趣。

修改1:我们知道以下两个RE是等效的,其中L b代表Letter bC代表Concat:< / p>

    Or                          Or
   /  \                        / \
  L b  C            =        L b  L a
      /  \                        
    L a  Emptyword                  

因此,考虑到左RE,我希望用C标记的节点替换子树,其节点标记为L a。正如所指出的,我的数据结构是树结构。但是,目前我没有功能,例如用节点替换子树,或找到我可以替换的结构的子树。

1 个答案:

答案 0 :(得分:3)

如评论中所述,您已经有了一棵树。您可以立即简化:

simplify :: Regex a -> Regex a
simplify (Star Emptyset)   = Emptyword
simplify (Star (Star x))   = Star (simplify x)
simplify (Concat x Emptyword) = simplify x
simplify (Concat Emptyword y) = simplify y
simplify (Or x y) | x == y = x
-- or rather simplify (Or x y) | simplify x == simplify y = simplify x
-- more sophisticated rules here
-- ...
-- otherwise just push down
simplify (Or x y) = simplify (Or (simplify x) (simplify y)
-- ...
simplify x@(Letter _) = x

这只是肤浅的,例如第一条规则应为simplify (Star x) | simplify x == Emptyset = emptyword

AVL树

AVL树是为了平衡,这里并不适用。平衡有意义的唯一地方是关联操作

Or (x (Or y z) == Or (Or x y) y

我建议将列表用于这些操作

data Regex' a = Letter' a | Concat' [Regex a]  | Or [Regex a] | Star (Regex a)
deriving (Show, Eq)

(否Emptyword',因为它是Concat' [];与Emptyset'Or相同。) 在RegexRegex'之间进行转换是读者的惯常做法。

一般硬度

请注意,正则表达式等价并不容易:

(a|b)* = (a*b)*a*

优化Or "(a|b)*" "(a*b)*a*"很难......