[英]Parse string to list in Haskell
我想解析要在Haskell中列出的字符串,但是我不知道如何正確編寫它。 字符串結構為:
A [B [], C [D [], E []]]
它代表結構
A-+-B
|
`-C-+-D
|
`-E
有想法嗎? 謝謝!
在Haskell中進行解析時,最好的選擇幾乎總是Parsec。 這是一個例子。
import Text.ParserCombinators.Parsec
data Tree a = Tree [Tree a] | Leaf a deriving Show
parseLeaf :: Parser (Tree Char)
parseLeaf = noneOf "[]" >>= return.Leaf
parseNode :: Parser (Tree Char)
parseNode = do
char '['
a <- parseTree
char ']'
return (Tree a)
parseTree = many1 (parseLeaf <|> parseNode)
測試一下:
> parseTest parseTree "a[aa]"
[Leaf 'a',Tree [Leaf 'a',Leaf 'a']]
> parseTest parseTree "a[aa]aaa"
[Leaf 'a',Tree [Leaf 'a',Leaf 'a'],Leaf 'a',Leaf 'a',Leaf 'a']
> parseTest parseTree "a[aa[aaaaaa]]aaa"
[Leaf 'a',Tree [Leaf 'a',Leaf 'a',Tree [Leaf 'a',Leaf 'a',Leaf 'a',Leaf 'a',Leaf 'a',Leaf 'a']],Leaf 'a',Leaf 'a',Leaf 'a']
運作方式如下。 Parsec中的解析器是一元語法,因此支持常用的do表示法。 (您也可以適當地編寫解析器,也可以在其他地方查找如何做。)
我們從一個簡單的數據結構開始
data Tree a = Tree [Tree a] | Leaf a deriving Show
這與您想要的並不完全相同,但是由於我不確定您的語義是什么,因此我使用了此示例。 您應該能夠針對您的目的對其進行調整。
然后,我們需要針對樹的每個可能部分的解析器。 葉子非常簡單,只是沒有括號的任何東西:
parseLeaf :: Parser (Tree Char)
parseLeaf = noneOf "[]" >>= return.Leaf
請注意,這可能是像
parseLeaf = do
a <- noneOf "[]"
return (Leaf a)
然后,要解析樹的分支部分,我們需要解析左括號和右括號。 在方括號之間,我們可以再有一棵完整的樹。
parseNode :: Parser (Tree Char)
parseNode = do
char '['
a <- parseTree
char ']'
return (Tree a)
那么parseTree
是parseTree
? 這只是我們編寫的任何一個解析器。 <|>
運算符允許解析器選擇任一解析器,無論哪種解析器首先正確解析。 所以我們有
parseTree = many1 (parseLeaf <|> parseNode)
您應該能夠適應您的目的。 看來您的結構可能更像這樣:
data Structure a = Node (Structure a) a a | Leaf a
通過遵循相同的原則,找出每種可能性需要解析器,然后將它們組合在一起,您應該立即進行解析。
更新
這是解析您詢問的數據結構的非常快速且骯臟的版本。 它不支持空格或逗號,但應有助於說明基本原理。
data Tree = Tree Char [Tree] deriving Show
parseTree :: Parser Tree
parseTree = do
character <- noneOf "[]"
subtree <- parseSubTree
return $ Tree character subtree
parseSubTree :: Parser [Tree]
parseSubTree = do
char '['
trees <- many parseTree
char ']'
return trees
這是一個以相當簡單的方式添加逗號和空格的版本。 parsec庫中有很多有用的組合器,它們可以簡化和改進此組合,您應該自己進行研究。 還要注意用於symbol
快捷方式解析器定義的應用樣式。 許多人喜歡解析器的應用程序樣式,它可能更加簡潔,因此也值得一去。
data Tree = Tree Char [Tree] deriving Show
symbol :: String -> Parser String
symbol s = string s <* spaces
parseTree :: Parser Tree
parseTree = do
character <- noneOf "[]"
spaces
subtree <- parseSubTree
return $ Tree character subtree
parseSubTree :: Parser [Tree]
parseSubTree = do
symbol "["
trees <- sepBy parseTree (symbol ",")
symbol "]"
return trees
它在這里工作:
> parseTest parseTree "A [ A [ B [ ] , C [ ], D [ ] ] ] "
Tree 'A' [Tree 'A' [Tree 'B' [],Tree 'C' [],Tree 'D' []]]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.