我想解析一些非常简单的文本,例如,将"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':"
使用兆赫秒-7.0.5(不是最新的9.x.x)。
有可能有一种更简单的方法来获得多行?
发布于 2021-12-20 19:00:57
仅将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://stackoverflow.com/questions/70426519
复制相似问题