我有一个使用 permute
的文件解析器来自 parsec
结合各种Parser
秒。看起来像 permute
只允许 Identity
monad,我确信它会降低算法的复杂性。
现在我正在尝试将我所有的解析代码转换为使用 MyErrorClass m => ParsecT String () m
, 其中Monad m => MyErrorClass m
是 class
具有特殊的错误处理。具体来说,使用 permute
的代码现在需要组合需要 MyErrorClass m
的解析器这样他们就可以提供结构化错误,而不仅仅是使用 fail
. (permute
仅在解析编程语言的模块配置文件时使用。文件格式允许嵌入某些语言结构,重用编译器的解析器。)
我只用permute
在 3 个地方,这个数字不太可能增加,所以为这 3 个中的每一个组合一些一次性函数并不是不可能的。或者,我可以删除字段排序的灵 active ,但我宁愿不。
在我做任何重要的事情之前,我是否缺少一个简单的解决方案 parsec
?也许我能以某种方式填充ParsecT String () m
进入permute
来自 parsers
而不是 parsec
? (这会增加依赖性,但可能是值得的。)
编辑:
以下是关于为什么结构化错误对解析有用的一些背景知识。
在大多数情况下,我分别进行解析和验证。例如,在解析成功后检查重复的符号定义。
我经常遇到类似于 expected //, /* or argument type
的解析错误,并且可能需要一段时间(对我来说,语言创建者)才能理解正在调用的解析器。
MyErrorClass
允许构造错误消息,例如
("In parsing of function declaration for " ++ show f) ??> do
-- parse the components of function f
-- any error messages here will be nested under the message above
能够像这样添加上下文至少会告诉用户解析器在失败时试图做什么。
最后,使用 MyErrorClass
还将允许 try
无法抑制的快速失败错误或 <|>
. (在一些地方,我有使用过时语法的明确错误消息。)
最佳答案
正如@danidiaz 所建议的那样, parser-combinators
轻松解决了置换 ParsecT
的文字问题.
需要注意的是,使用 ParsecT
用Monad m
转换 错误(甚至它自己的错误)并不是特别有用,除了能够使用不能被 <|>
忽略的快速失败错误之外和 try
.
您不能“降级”
ParsecT
的错误状态至m
自己的错误类型,因为(AFAIK)无法访问ParsecT
的当前错误状态.ParsecT
缺少与StateT
相当的东西的mapStateT
.这意味着无法转换存储在m
中的错误。没有使用runPT
实际执行解析器(等),这是不可能进行中间解析的。
总而言之,ParsecT
不漏m
与 StateT
相同做一些m
无法从内部访问的功能 ParsecT
.
关于haskell - 用 `ParsecT` 进行排列解析?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65160666/