如何 map/bind FParsec 用户状态?
How to map/bind FParsec userstate?
我想通过解析器将一些状态线程化,但我不想为解析器的所有部分使用单一类型的状态,因为某些类型在解析器的某些部分没有意义,但在其他人中需要。我可以使用可选值或可区分的联合来创建更大更复杂的状态类型,但我认为这很丑陋。
所以我希望能够将函数映射到解析器的状态。
具体来说,我想要一个具有以下签名的函数
stateMap: (f:'a->'b) (p:Parser<'x,'a>) -> Parser<'x,'b>
FParsec 中是否存在这样的函数或运算符?如果不是,创建它的惯用方法是什么?
查了源码我的印象是现在没有这样的方法,实现起来也不是那么容易。 Parser<_>
被定义为喜欢 this:
type Parser<'Result, 'UserState> = CharStream<'UserState> -> Reply<'Result>
如果有办法将 CharStream<'a>
映射到 CharStream<'b>
那么我们就可以达到目标。
但是调查 CharStream<_>
的 source 揭示了一些问题:
CharStream<_>
没有map
。
CharStream<_>
是 IDisposable
,这意味着 FParsec
在解析开始时创建了 CharStream<_>
的一个实例,并且假设这会跟踪整个解析过程。在现有的基础上创建新的 CharStream<_>
并改用它似乎与设计不符。
CharStream<_>
继承了 CharStream
- 所以 CharStream
似乎在分页时必须做繁重的工作,而 CharStream<_>
只是为了将流与用户配对状态。如果 CharStream<_>
使用组合而不是继承,我们可以创建一个新的 CharStream<_>
,它仍然使用已经存在的 CharStream
,但继承是不可能的。我的猜测是这里选择继承是为了避免额外的取消引用,从而节省几个时钟周期(性能对解析器很重要)。
所以我认为复合用户状态的想法听起来很有趣,但据我所知,目前 FParsec 不支持它。
我想通过解析器将一些状态线程化,但我不想为解析器的所有部分使用单一类型的状态,因为某些类型在解析器的某些部分没有意义,但在其他人中需要。我可以使用可选值或可区分的联合来创建更大更复杂的状态类型,但我认为这很丑陋。
所以我希望能够将函数映射到解析器的状态。
具体来说,我想要一个具有以下签名的函数
stateMap: (f:'a->'b) (p:Parser<'x,'a>) -> Parser<'x,'b>
FParsec 中是否存在这样的函数或运算符?如果不是,创建它的惯用方法是什么?
查了源码我的印象是现在没有这样的方法,实现起来也不是那么容易。 Parser<_>
被定义为喜欢 this:
type Parser<'Result, 'UserState> = CharStream<'UserState> -> Reply<'Result>
如果有办法将 CharStream<'a>
映射到 CharStream<'b>
那么我们就可以达到目标。
但是调查 CharStream<_>
的 source 揭示了一些问题:
CharStream<_>
没有map
。CharStream<_>
是IDisposable
,这意味着FParsec
在解析开始时创建了CharStream<_>
的一个实例,并且假设这会跟踪整个解析过程。在现有的基础上创建新的CharStream<_>
并改用它似乎与设计不符。CharStream<_>
继承了CharStream
- 所以CharStream
似乎在分页时必须做繁重的工作,而CharStream<_>
只是为了将流与用户配对状态。如果CharStream<_>
使用组合而不是继承,我们可以创建一个新的CharStream<_>
,它仍然使用已经存在的CharStream
,但继承是不可能的。我的猜测是这里选择继承是为了避免额外的取消引用,从而节省几个时钟周期(性能对解析器很重要)。
所以我认为复合用户状态的想法听起来很有趣,但据我所知,目前 FParsec 不支持它。