我努力想出能够转换正则表达式的算法(在常规语言环境中,只有3个操作'。'用于concat,' +' for& #34;或"和' *'用于迭代)对正则表达式树进行反向抛光表示法。
例如我有一个正则表达式
aa.bb.+
我需要构建以下表达式树
+
/ \
. .
/ \ / \
b b a a
非常感谢任何帮助。谢谢!
答案 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'))]
你没有写过关于你的数据结构的任何所以我采取了一些自由 - 一旦你理解了step
和foldl
,就应该很容易适应你的情况在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看起来更健全
当然你可能不喜欢[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