You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:38:02