我正在使用解析库Parsec来解析一些文本.我只需要解析行,这些行是任意字符的字符串,当它位于字符串的末尾时以'\n'或eof结尾.打电话的时候,parseHS'
我得到了投诉Exception: Text.ParserCombinators.Parsec.Prim.many: combinator 'many' is applied to a parser that accepts an empty string.
.
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
Run Code Online (Sandbox Code Playgroud)
怎么能正确实现?
如果将many
(或many1
)应用于接受(以及其他)空字符串的解析器,则会出现含糊不清的语法.可以经常任意识别空字符串,从而产生不同的解析树.
在这种情况下,line
接受空字符串,并many1
按照实现many
,因此这会触发异常.在您的情况下解决方案可能是确保line
始终消耗至少一个字符.
当然,如果您只需要按行拆分输入,则可以使用lines
.
sepEndBy
在Parsec做你想要的 - 将输入分成由给定分隔符分隔的解析实体列表,可选地以它或eof结尾.
您的语法line
允许解析器为任何输入生成永无止境的行流.这可以通过在线外做出关于换行的决定来解决:
hsFile' = do
x <- line
xs <- many $ do
newline
line
eof
return (x:xs)
line = many $ noneOf "\n"
Run Code Online (Sandbox Code Playgroud)
如果文件以换行符结尾,则此行将在末尾生成一个空行.