簡體   English   中英

解析字符串以在Haskell中列出

[英]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)

那么parseTreeparseTree 這只是我們編寫的任何一個解析器。 <|>運算符允許解析器選擇任一解析器,無論哪種解析器首先正確解析。 所以我們有

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM