,例如秒差距使用之間。如果我想多帶括號的組串解析成控股各組字符串列表來解析括號
"((a b c) a b c)"
到
["((a b c) a b c)","(a b c)"]
我會怎麼做使用parsec?使用between
看起來不錯,但似乎不可能用開始和結束值分開。
,例如秒差距使用之間。如果我想多帶括號的組串解析成控股各組字符串列表來解析括號
"((a b c) a b c)"
到
["((a b c) a b c)","(a b c)"]
我會怎麼做使用parsec?使用between
看起來不錯,但似乎不可能用開始和結束值分開。
聚集在jozefg的解決方案几乎是相同的什麼,我想出了(我完全同意他的建議),也有讓我覺得,我應該發佈第二一些小的區別回答:
所以這裏是我的版本。正如jozefg所建議的那樣,將任務分成幾個子任務。它們是:
關於1,我們首先需要的是一棵數據類型
import Text.Parsec
import Text.Parsec.String
import Control.Applicative ((<$>))
data Tree = Leaf String | Node [Tree]
,然後一個功能,可以解析字符串到這種類型的值。
parseTree :: Parser Tree
parseTree = node <|> leaf
where
node = Node <$> between (char '(') (char ')') (many parseTree)
leaf = Leaf <$> many1 (noneOf "()")
在我的版本我認爲括號之間的孔字符串作爲Leaf
節點(即我沒有在白空間分割)。
現在,我們需要收集樹我們感興趣的子樹:
nodes :: Tree -> [Tree]
nodes (Leaf _) = []
nodes [email protected](Node ts) = t : concatMap nodes ts
最後,Show
-instance爲Tree
允許的數量我們將它們變成字符串。
instance Show Tree where
showsPrec d (Leaf x) = showString x
showsPrec d (Node xs) = showString "(" . showList xs . showString ")"
where
showList [] = id
showList (x:xs) = shows x . showList xs
那麼原來的任務是可以解決的,例如,通過:
parseGroups :: Parser [String]
parseGroups = map show . nodes <$> parseTree
> parseTest parseGroups "((a b c) a b c)"
["((a b c) a b c)","(a b c)"]
我會使用一個遞歸解析:
data Expr = List [Expr] | Term String
expr :: Parsec String() Expr
expr = recurse <|> terminal
其中terminal
是你的原語,在這種情況下,這些似乎是個字符的字符串,這樣
where terminal = Term <$> many1 letter
和recurse
是
recurse = List <$>
(between `on` char) '(' ')' (expr `sepBy1` char ' ')
現在我們有一棵漂亮的樹Expr
sw HICH我們可以
collect [email protected](List ts) = r : concatMap collect ts
collect _ = []
Awsome回答非常感謝。我更喜歡這種方法 – user2150839 2013-04-24 06:52:31
@chris我試過這個,我看到它的一個問題..節點功能複製所有嵌套括號的內容。當我將最後一行節點函數替換爲此節點時,它的工作方式應該如此:'節點t @(節點_)= t' – 2016-02-15 23:06:59
P.S.啊,我明白這是OP的要點。不要那麼:-)我需要一些不同的東西 - 只是爲了解析圓括號的內容,其中包括圓括號。像'func(){hello {...}}',但內容變平。有了這個簡單的改變,它就做到了我所需要的,所以非常感謝! – 2016-02-15 23:14:50