是否有一种既定的方法来编写可以重建其精确输入的解析器?

lef*_*out 14 parsing haskell parsec bijection

假设我想用语言X解析文件.真的,我只对其中的一小部分信息感兴趣.为此目的在Haskell的许多eDSL中编写解析器很容易(例如Megaparsec).

data Foo = Foo Int  -- the information I'm after.

parseFoo :: Parsec Text Foo
parseFoo = ...
Run Code Online (Sandbox Code Playgroud)

这很容易产生一种功能getFoo :: Text -> Maybe Foo.

但现在我还要修改信息的来源Foo,即基本上我想实现

changeFoo :: (Foo -> Foo) -> Text -> Text
Run Code Online (Sandbox Code Playgroud)

与属性

changeFoo id ? id
getFoo . changeFoo f ? fmap f . getFoo
Run Code Online (Sandbox Code Playgroud)

可以通过将解析器的结果更改为类似镜头的方式来实现

parseFoo :: Parsec Text (Foo, Foo -> Text)
parseFoo = ...
Run Code Online (Sandbox Code Playgroud)

但是这使定义变得更加麻烦 - 我不能仅仅string掩盖不相关的信息,而是需要存储每个subparse 的匹配并手动重新组装它.

这可以通过将字符串重组保持在StateT解析器monad周围的层中来实现自动化,但我不能只使用现有的原始解析器.

这个问题是否有现成的解决方案?

Ira*_*ter 1

在 Haskell 中实现的解决方案?我不知道有哪一个;它们可能存在。

不过,一般来说,通过使用收集的令牌存储“格式化”信息,可以存储足够的信息来重新生成与原始程序在任意程度上相似的合法版本。限制条件下,格式信息为token的原始字符串;任何近似值都会依次给出不太准确的答案。

如果您将空格保留为解析树中的显式标记,则在限制范围内您甚至可以重新生成它。这是否有用可能取决于应用程序。总的来说,我认为这太过分了。

有关捕获内容/如何捕获以及如何重新生成的详细信息可以在我的答案中找到:Compiling an AST back to source code