繁体   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