15

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

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

parseFoo :: Parsec Text Foo
parseFoo = ...

这很容易产生一个函数getFoo :: Text -> Maybe Foo

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

changeFoo :: (Foo -> Foo) -> Text -> Text

与属性

changeFoo id ≡ id
getFoo . changeFoo f ≡ fmap f . getFoo

可以通过将解析器的结果更改为类似镜头的东西来做到这一点

parseFoo :: Parsec Text (Foo, Foo -> Text)
parseFoo = ...

但这使得定义变得更加麻烦——我不能再掩盖不相关的信息,而是需要存储每个子解析的匹配string并手动重新组合它。

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

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

4

2 回答 2

3

这是“双向转化”的案例吗?例如, http://ceur-ws.org/Vol-1571/

特别是 Rendel 和 Osterman 的“可逆语法描述:统一解析和漂亮打印” http://dblp.org/rec/conf/haskell/RendelO10,Haskell Symposium 2010(参见http://lambda-the-ultimate.组织/节点/4191

于 2016-05-30T16:50:29.707 回答
1

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

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

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

有关捕获内容/如何捕获以及如何重新生成的详细信息,请参阅我的 SO 答案:将 AST 编译回源代码

于 2016-05-30T16:06:36.093 回答