Haskell - 反向抛光表示法正则表达式到表达式树

时间:2016-03-29 06:40:29

标签: regex haskell expression-trees postfix-notation

我努力想出能够转换正则表达式的算法(在常规语言环境中,只有3个操作'。'用于concat,' +' for& #34;或"和' *'用于迭代)对正则表达式树进行反向抛光表示法。

例如我有一个正则表达式

aa.bb.+

我需要构建以下表达式树

      +
    /   \
   .     .
  / \   / \
 b   b a   a  

非常感谢任何帮助。谢谢!

1 个答案:

答案 0 :(得分:4)

使用基于堆栈的算法(在Haskell中转换为foldl)并不难:

data Tree
  = Symbol Char
  | Op Char Tree Tree
  deriving Show

type Stack = [Tree]

step :: Stack -> Char -> Stack
step (r:l:s) '.' = (Op '.' l r):s
step (r:l:s) '+' = (Op '+' l r):s
step s c         = (Symbol c):s

parse :: String -> Stack
parse = foldl step []

会产生这样的结果:

λ> parse "aa.bb.+"
[Op '+' (Op '.' (Symbol 'a') (Symbol 'a')) (Op '.' (Symbol 'b') (Symbol 'b'))]

你没有写过关于你的数据结构的任何所以我采取了一些自由 - 一旦你理解了stepfoldl,就应该很容易适应你的情况在parse

如果您想在示例中更改 / 正确,您只需在step中执行此操作:

step :: Stack -> Char -> Stack
step (l:r:s) '.' = (Op '.' l r):s
step (l:r:s) '+' = (Op '+' l r):s
step s c         = (Symbol c):s

示例:

λ> parse "aa.bb.+"
[Op '+' (Op '.' (Symbol 'b') (Symbol 'b')) (Op '.' (Symbol 'a') (Symbol 'a'))]

但如果订单重要,我会期待第一个(在bb aa之前,这是奇怪的......

当然, star 操作也是二进制的,这很奇怪,所以我建议:

data Tree
  = Symbol Char
  | Concat Tree Tree
  | Star Tree
  deriving Show

type Stack = [Tree]

step :: Stack -> Char -> Stack
step (r:l:s) '.' = (Concat r l):s
step (t:s)   '+' = (Star t):s
step s c         = (Symbol c):s

parse :: String -> Stack
parse = foldl step []

会改变你的语法:

λ> parse "aa.bb..+"
[Star (Concat (Concat (Symbol 'b') (Symbol 'b')) (Concat (Symbol 'a') (Symbol 'a')))]

但是IMO看起来更健全

将列表转换为Maybe

当然你可能不喜欢[Stack]返回,所以你可以这样做:

parse :: String -> Maybe Tree
parse input =
  case result of
    [t] -> Just t
    []  -> Nothing
    _   -> error "syntax error"
  where result = foldl step [] input

的示例:

λ> parse "aa.bb..+"
Just (Star (Concat (Concat (Symbol 'b') (Symbol 'b')) (Concat (Symbol 'a') (Symbol 'a'))))
λ> parse ""
Nothing
λ> parse "aa.bb.+"
*** Exception: syntax error