Haskell 如何使用Parsec解析一行?
我正在使用解析库Parsec来解析一些文本。 我只需要分析行,这些行是由任意字符组成的字符串,当其位于字符串末尾时,以“\n”或eof结尾。 调用Haskell 如何使用Parsec解析一行?,haskell,parsec,Haskell,Parsec,我正在使用解析库Parsec来解析一些文本。 我只需要分析行,这些行是由任意字符组成的字符串,当其位于字符串末尾时,以“\n”或eof结尾。 调用parseHS'时,我收到投诉,称Exception:Text.ParserCombinators.Parsec.Prim.many:combinator“many”应用于接受空字符串的解析器。 parseHS' :: String -> Either ParseError [String] parseHS' input = parse hsFi
parseHS'
时,我收到投诉,称Exception:Text.ParserCombinators.Parsec.Prim.many:combinator“many”应用于接受空字符串的解析器。
parseHS' :: String -> Either ParseError [String]
parseHS' input = parse hsFile' "(unknown)" input
hsFile' :: GenParser Char st [String]
hsFile' = do
many1 line
line :: GenParser Char st String
line = do
result <- many (noneOf "\n")
optional newline
return result
parseHS'::String->ParseError[String]
parseHS'input=parse hsFile'(未知)输入
hsFile'::GenParser Char st[字符串]
hsFile'=do
多线
line::GenParser Char st String
line=do
结果如果将many
(或many1
)应用于接受空字符串的解析器,则语法不明确。空字符串经常可以被任意识别,导致不同的解析树
在这种情况下,line
接受空字符串,并且many1
按照many
实现,因此这会触发异常。在您的情况下,解决方案可能是确保行
始终使用至少一个字符。使用解析器来处理这一问题太过分了,因为您对行的内容没有限制。有一个库函数,行
,它以相当少的麻烦实现了您的要求
例如:
lines "Hello there\neveryone,\nhere are some lines,"
> ["Hello there", "everyone,", "here are some lines,"]
如果行具有某种结构,则应首先编码该行,而不是尝试将字符串向上切碎-自下而上是编写递归下降解析器的最佳方法。当然,如果只需要按行分割输入,则可以使用行
Parsec中的sepEndBy
做你想做的事-将输入拆分成一个由给定分隔符分隔的已解析实体列表,可以选择以它或eof结尾
line
的语法允许解析器为任何输入生成一个永无止境的行流。这可以通过在外部对行作出关于换行的决定来解决:
hsFile' = do
x <- line
xs <- many $ do
newline
line
eof
return (x:xs)
line = many $ noneOf "\n"
hsFile'=do
这似乎是正确的,而且异常没有多大意义,因为noneOf
不接受空字符串。你确定你的代码中没有很多行吗?谢谢你的回复@Tarmil。是的,我有一条比这高一层的1号线。仅此而已。答案更新为包含完整的代码示例