首页 > 解决方案 > 如何映射/绑定 FParsec 用户状态?

问题描述

我想通过解析器线程化一些状态,但我不想为解析器的所有部分使用单一类型的状态,因为某些类型在解析器的某些部分没有意义,但在其他部分需要. 我可以使用可选值或有区别的联合来制作更大更复杂的状态类型,但我认为这很难看。

所以我希望能够将函数映射到解析器的状态。

具体来说,我想要一个具有以下签名的函数

stateMap: (f:'a->'b) (p:Parser<'x,'a>) -> Parser<'x,'b>

FParsec 中是否存在这样的函数或运算符?如果没有,创建它的惯用方式是什么?

标签: f#fparsec

解决方案


通过查看源代码,我的印象是今天没有这样的方法,而且实现起来也不是那么容易。Parser<_>被定义喜欢这样

type Parser<'Result, 'UserState> = CharStream<'UserState> -> Reply<'Result>

如果有一种映射方式CharStream<'a>CharStream<'b>那么我们将达到目标。

然而,调查来源CharStream<_>揭示了一些问题:

  1. 没有mapCharStream<_>
  2. CharStream<_>IDisposable意味着在解析开始时FParsec创建一个实例,CharStream<_>并且假设这会跟踪整个解析过程。根据现有的创建一个新CharStream<_>的并使用它似乎与设计不匹配。
  3. CharStream<_>继承CharStream- 因此CharStream,在分页方面似乎必须进行繁重的工作,并且CharStream<_>只是将流与用户状态配对。如果CharStream<_>使用组合而不是继承,我们可以创建一个新的CharStream<_>,它仍然使用已经存在的CharStream但继承是不可能的。我的猜测是这里选择继承是为了避免额外的 deref 并因此节省一些时钟周期(性能对解析器很重要)。

所以我认为复合用户状态的想法听起来很有趣,但据我所知,目前 FParsec 不支持这一点。


推荐阅读