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

Haskell Megaparsec如何显示错误对应的解析器回溯信息?

在Megaparsec中实现带回溯标签的错误提示

Megaparsec默认的错误报告不会自动展示通过<?>添加的解析器标签回溯层级,但可以通过自定义错误格式化函数实现需求——利用ParseError结构中保存的errorStack字段(解析器标签栈),将其整合到错误输出里。

实现步骤

  1. 理解错误结构:当用<?>给解析器添加标签时,Megaparsec会把这些标签存入ParseError的errorStack字段,默认的parseErrorPretty函数不会输出这个栈,需要手动提取并格式化。

  2. 自定义错误格式化函数:编写函数提取错误栈并生成带回溯的错误信息:

import Text.Megaparsec
import Text.Megaparsec.Char
import Data.Void (Void)

type Parser = Parsec Void String

-- 格式化带回溯栈的错误信息
formatWithStack :: ParseErrorBundle String Void -> String
formatWithStack bundle =
  let -- 获取错误位置信息
      posInfo = errorBundlePos bundle
      -- 获取最精确的错误记录
      coreErr = head $ bundleErrors bundle
      -- 生成回溯栈文本:从外层到内层缩进区分层级
      stackContent = case errorStack coreErr of
        [] -> ""
        stack -> unlines $ zipWith (\depth label -> replicate (depth*2) ' ' ++ "error while parsing " ++ label ++ ":") [0..] (reverse stack)
      -- 格式化原始错误提示并缩进
      rawMsg = parseErrorTextPretty coreErr
      indentedMsg = unlines $ map ("  " ++) (lines rawMsg)
  in posInfo ++ "\n" ++ stackContent ++ indentedMsg
  1. 自定义测试函数:替换默认的parseTest,用自定义函数输出错误:
-- 自定义解析测试工具
testParser :: Parser a -> String -> IO ()
testParser p input =
  case parse p "" input of
    Left err -> putStrLn $ formatWithStack err
    Right res -> print res

示例测试

定义带嵌套标签的解析器:

-- 内层解析器
letterParser :: Parser Char
letterParser = letterChar <?> "single letter"

-- 中层解析器
fooParser :: Parser String
fooParser = do
  d <- digitChar <?> "count digit"
  c <- letterParser
  return $ replicate (read [d]) c
  <?> "foo pattern" -- 给整个foo解析器打标签

-- 外层解析器
parentParser :: Parser String
parentParser = fooParser <?> "parent block"

测试错误输入"33a":

testParser parentParser "33a"

输出结果:

1:2:
  |
1 | 33a
  |  ^
error while parsing parent block:
  error while parsing foo pattern:
    error while parsing single letter:
      unexpected '3'
      expecting single letter

说明

  • 错误栈从最外层解析器到最内层失败节点,通过缩进区分层级,清晰展示回溯路径。
  • 该方案适用于Megaparsec 8.x及以上版本(errorStack字段在这些版本中稳定存在)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 03:26:00