2017-08-27 91 views
0

我是新來解析的世界,有一個非常簡單的,看似問題:如何使用Parsec(Haskell)基於密鑰令牌將值內插到字符串中?

我有由Chunk正常的文字,並Key一個漫長的字符串編碼像<<key-label>>

data Merge a = Chunk a 
      | Key a 
    deriving (Show) 

key :: Parser (Merge String) 
key = Key <$> between (string "<<") (string ">>") (many1 letter) 

chunk :: Parser (Merge String) 
chunk = Chunk <$> many1 anyChar 

prose = many1 $ key <|> chunk 

ex = parseTest prose "hi <<x>> ! Do you like <<y>>?" 

-- Returns: 
-- [Chunk "hi <<x>> ! Do you like <<y>>?"] 

-- I'd like: 
-- [Chunk "hi ", Key "x", Chunk " !", ...] 

我想和值替換這些鍵,但我可以解決,如果我可以分析一個字符串到我的標記,IE String -> [Merge]

我已經潛入了無窮無盡的深度/解析,儘管我希望最終能夠學習所有知識,但現在解決此問題的任何指導意見?

這是我嘗試的最簡單的實例,雖然我已經嘗試過不同的數據傳遞,其中包括獨立的詞法/解析步驟,而且我喜歡使用parsec,而不是一個更具體的插值庫。

+2

解析器會查找'Chunk'的那一刻,因爲它的規則是'many1 anyChar',所以它會吸取所有剩餘的字符。您需要更改規則以禁止序列「<<」,這是「Key」的開始。但是,如果在解析'Key'的時候,在看到'>>'之前遇到了除字母之外的其他東西,那麼您必須確定這是否是錯誤,或者如果您想回溯並將其視爲另一個'Chunk' 。 – pat

+0

@pat我明白'many1 anyChar'太過貪心,但如果我錯了,請糾正我,'Chunk'需要編碼'Key'的語法概念(IE停在'<<')? –

+0

@ Josh.F這取決於你想要的語義。 '「<<」是一個有效的字符串嗎?那麼'「<< << >>」'或'「<< foo」'?無論如何,單獨的解析/搜索步驟是這裏的一種方式(實際上,這個簡單的例子只包含了對結果的清理和一點清理;如果這不是你想要的過於簡化的版本確實,放棄解析器)。 Lexing應該產生類似於'[Tok'hi',OpenBrace,Tok'x',CloseBrace,...]'之後的'解析'步驟完全是微不足道的。 – user2407038

回答

1

你可以使用notFollowedBy來表示你想要一個塊包含一個 字符,只要它不是一個關鍵字。 notFollowedBy不會消耗 輸入,因此prose仍然會繼續將密鑰解析爲其自己的項目。

chunk = Chunk <$> many1 (notFollowedBy key >> anyChar) 

這將允許甚至像aaa<<bbbbbb的事情由一路去到文件的末尾 被解析爲一個塊,沒有找到一個結束 >>,決定它不能是一個關鍵因此它可以是 成爲塊的一部分。

如果你寧願有<<始終是一個關鍵的開始,如果 它不是封閉的失敗,從塊禁止<<

chunk = Chunk <$> many1 (notFollowedBy (string "<<") >> anyChar) 
+0

作品!嘿,我知道更多的涉及解析,看向前或回溯的事情效率低下,並通過多次傳遞消除。我已經嘗試了多種傳遞方法,但是我一直無法弄清楚如何在令牌上使用Parsec,而不是字符/字符串。你能指出我正確的方向嗎? –

相關問題