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

如何将MegaParsec的ParseErrorBundle转换为SourcePos与错误信息列表

解决方案

你可以直接复用Megaparsec内置的reachOffset接口实现需求,不需要复刻整个errorBundlePretty的逻辑,最简实现代码如下:

import qualified Data.Text as T
import Text.Megaparsec
import Text.Megaparsec.Error

getParseErrors :: (VisualStream s, TraversableStream s, ShowErrorComponent e)
               => ParseErrorBundle s e -> [(SourcePos, T.Text)]
getParseErrors bundle = map wrapError $ bundleErrors bundle
  where
    basePosState = bundlePosState bundle
    wrapError err = (errPos, T.pack $ parseErrorTextPretty err)
      where
        -- 直接调用官方接口通过错误偏移计算对应SourcePos
        (errPos, _, _) = reachOffset (errorOffset err) basePosState

这个实现完全复用官方的位置计算逻辑,返回的行号、列号和errorBundlePretty的输出完全一致,代码量非常少,适合绝大多数场景。

如果你的解析结果经常出现大量错误,可以优化为单遍遍历推进位置状态的版本,避免重复计算偏移:

import Data.List (sortOn)
import qualified Data.Text as T
import Text.Megaparsec
import Text.Megaparsec.Error

getParseErrorsOptimized :: (VisualStream s, TraversableStream s, ShowErrorComponent e)
                        => ParseErrorBundle s e -> [(SourcePos, T.Text)]
getParseErrorsOptimized bundle = snd $ foldl process (basePosState, []) sortedErrs
  where
    -- 先按错误偏移从小到大排序,方便顺序推进位置状态
    sortedErrs = sortOn errorOffset $ bundleErrors bundle
    basePosState = bundlePosState bundle
    process (currState, res) err = (newState, res ++ [(errPos, errText)])
      where
        (errPos, newState, _) = reachOffset (errorOffset err) currState
        errText = T.pack $ parseErrorTextPretty err

内容的提问来源于stack exchange,提问作者Joe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 18:54:07