如何在使用Parsec解析多个条目时触发解析失败?
没问题,我来帮你搞定这个Parsec的解析失败触发需求~
首先明确核心需求:你希望当输入里存在多个FOO <value>条目时,解析直接失败,只允许单个条目存在对吧?我们可以用Parsec的notFollowedBy组合子来实现,它的作用就是检查后续输入不匹配指定规则,一旦匹配就触发解析失败。
先补全并优化你的基础解析代码(用Parser类型更简洁,等价于你原来的ParsecT String u Identity):
import Text.Parsec import Text.Parsec.String (Parser) parseFoo :: Parser (String, Int) parseFoo = do k <- string "FOO" _ <- space v <- many1 digit return (k, read v)
实现1:只允许恰好一个FOO条目(多个直接失败)
这个版本要求输入必须有且只有一个FOO <value>条目,多一个都不行:
parseSingleFoo :: Parser [(String, Int)] parseSingleFoo = do -- 解析单个FOO条目 foo <- parseFoo -- 兼容条目末尾的换行(比如你示例里的最后一个\n) _ <- optional newline -- 关键逻辑:检查后续不能再出现FOO开头的内容 notFollowedBy (do -- 允许中间有空白字符(空格、制表符等),不需要的话可以删掉这行 optional whitespace string "FOO") <?> "multiple FOO entries are not allowed" -- 返回包含单个条目的列表,保持和原parseFoos一致的返回类型 return [foo]
实现2:允许零个或一个FOO条目(多个失败)
如果你的场景允许输入为空,但只要有多个FOO就失败,可以用这个版本:
parseZeroOrOneFoo :: Parser [(String, Int)] parseZeroOrOneFoo = do -- 尝试解析一个FOO,失败就返回空列表 result <- option [] (do foo <- parseFoo _ <- optional newline notFollowedBy (do optional whitespace string "FOO") <?> "multiple FOO entries are not allowed" return [foo]) -- 可选:确保整个输入都被解析,没有无关内容 eof return result
测试效果
- 输入
"FOO 5\n":解析成功,返回[("FOO",5)] - 输入
"FOO 5\nFOO 9\n":解析失败,错误信息会显示unexpected "FOO", multiple FOO entries are not allowed - 输入空字符串:只有实现2会成功返回
[],实现1会失败
内容的提问来源于stack exchange,提问作者lsund
相关产品推荐
相关产品推荐

