haskell - 我的 parsec 解析器可以写弃用消息吗?
问题描述
我有一个 DSL,以及一个用 Haskell 和 Parsec 包编写的解析器。现在我想弃用 DSL 的特定语言功能。在下一个版本中,我希望解析器同时接受新语法和旧语法,但我希望解析器产生弃用消息。我找不到如何做到这一点。这可能吗?如果可以,怎么做?
解决方案
与其在解析期间发出消息,不如在解析结束时返回额外信息:是否遇到过时的语法。
该ParsecT
类型接受用户在解析期间设置的状态的类型参数:
ParsecT suma 是一个具有流类型 s、用户状态类型 u、底层 monad m 和返回类型 a 的解析器。Parsec 在用户状态下是严格的。
可以使用putState
和设置用户状态modifyState
。可以使用getState
.
大多数 parsec 组合器在用户状态上是多态的。您自己的 DSL 的大多数组合器也应该是。但是语法中不推荐使用的部分的解析器应该在你的用户状态中设置一个“标志”。
像这样的东西:
import Text.Parsec
import Text.Parsec.Char
import Data.Functor.Identity
type Parser = ParsecT [Char] Bool Identity -- using a Bool state
myParser :: Parser Char
myParser =
try (do char 'a'
putState True
char 'b')
<|>
try (do char 'a'
char 'c')
main :: IO ()
main = do
print $ runParser ((,) <$> myParser <*> getState) False "" "ab"
print $ runParser ((,) <$> myParser <*> getState) False "" "ac"
-- results:
-- Right ('b',True)
-- Right ('c',False)
当然,与其使用简单的布尔标志,不如将更多信息放入状态中。
请注意,如果子解析器回溯,则由子解析器设置的状态将被“遗忘”。对于我们的目的,这是正确的行为:否则,我们会得到由最终丢弃的分支触发的“误报”。
一个常见的 parsec 替代方案是megaparsec。后者不允许在解析器类型本身中使用用户定义的状态,但可以使用StateT
该类型的转换器来模拟它ParsecT
。
推荐阅读
- javascript - 从 col 到 row 将未排序的 cels 复制到另一个电子表格,现在卡在数组中
- scheme - 为什么我不能在这个函数中返回false,但我可以返回true?(球拍)
- ios - 在带有 iOS 的 ionic 框架 1.0.0 版中,iframe 无法正常工作并刷新
- php - Laravel 8 - 带有删除项目符号的自定义消息
- javascript - 使用 localfield 键从另一个文档连接对象
- angular - Ngrx StoreModule 声明 forRoot 错误 Angular 9
- java - 将优先级更改为 PRIORITY_MAX 是否会延迟通知 .setRepeating?
- kotlin - 使用协程在 kotlin 中的列表上实现 monad 理解
- ssh - 如何使用 Termius 应用程序将 SSH 远程连接到 MacOS 或 Linux 终端?
- typescript - TypeError:未定义不是对象(评估'details.geometry.location')