例如,我想將一些非常簡單的文本決議
"abcxyzzzz\nhello\n"為["abcxyzzz", "hello"] :: String.
不尋找更簡單的函式來執行此操作(例如words),因為我需要決議更復雜的內容,而我只是在這里打下基礎。
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}
module RgParse where
import Data.Text (Text)
import Text.Megaparsec
import Text.Megaparsec.Char
data SimpleData = SimpleData String deriving (Eq, Show, Ord)
data SimpleData' = SimpleData' [String] deriving (Eq, Show, Ord)
instance ShowErrorComponent SimpleData where
showErrorComponent = show
instance ShowErrorComponent String where
showErrorComponent = show
simple :: Parsec String Text SimpleData
simple = do
x <- many (noneOf (Just '\n'))
pure $ SimpleData x
simple' :: Parsec String Text SimpleData'
simple' = do
x <- many (many (noneOf (Just '\n')))
pure $ SimpleData' x
example2 :: Text
example2 = "abcxyzzzz\nhello\n"
main :: IO ()
main = do
print "Simple:"
case parse simple "<stdin>" example2 of
Left bundle -> putStr (errorBundlePretty bundle)
Right result -> print result
print "Simple':"
case parse simple' "<stdin>" example2 of
Left bundle -> putStr (errorBundlePretty bundle)
Right result -> print result
print "done.."
不幸的是,上面的內容在輸入時遇到了無限回圈/空間泄漏,simple'因為它輸出以下內容:
Hello, Haskell!
[]
"Simple:"
SimpleData "abcxyzzzz"
"Simple':"
使用 megaparsec-7.0.5(不是最新的 9.xx)。
是否有更簡單的方法來獲取多行?
uj5u.com熱心網友回復:
many僅適用于至少消耗一個令牌(此處為一個Char)或失敗的決議器。那是因為它的many作業原理是運行它的引數直到它失敗。many x可能消耗零令牌,所以many (many x)打破了這個要求。
請注意,一行至少應包含終止換行符。這樣就可以滿足該要求。
oneline :: Parsec String Text String
oneline = many (noneOf (Just '\n')) <* single '\n'
manylines :: Parsec String Text [String]
manylines = many oneline
simple :: Parsec String Text SimpleData
simple = do
x <- oneline
pure $ SimpleData x
simple' :: Parsec String Text SimpleData'
simple' = do
x <- manylines
pure $ SimpleData' x
一個更寬松的要求many p是,p在有限次數的迭代之后,任何重復都必須失敗(這里p = many x永遠不會失敗),因此p在某些步驟中可能不消耗任何東西,但它必須是有狀態的,以便在某些重復之后最終消耗某些東西或失敗。但上述近似值在實踐中是一個很好的經驗法則。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/389034.html
上一篇:組合:圣彼得游戲演算法
