Functional programming F“如何定义”;递归的;变量

Functional programming F“如何定义”;递归的;变量,functional-programming,f#,fparsec,Functional Programming,F#,Fparsec,我正在使用FParsec库为伪语言编写解析器, 我有一个语句解析器,可以在所有可能的语句之间进行选择 一种块解析器,它解析一系列语句,直到出现一个“end”关键字 现在我想写一个“循环”结构,问题是,循环本身是一个语句,包含一个块 这导致了F#不喜欢的递归定义形式 不久前,我用C#编写了一个解析器,完成这一过程很容易,因为每个解析器都是一个函数,它们可以相互调用,而不依赖于它们是在之前还是之后定义的 所以我想知道如何用F来解决这个问题# 下面是提到的解析器: //解析由1个或多个换行符分隔的语句

我正在使用FParsec库为伪语言编写解析器, 我有一个语句解析器,可以在所有可能的语句之间进行选择 一种块解析器,它解析一系列语句,直到出现一个“end”关键字 现在我想写一个“循环”结构,问题是,循环本身是一个语句,包含一个块 这导致了F#不喜欢的递归定义形式 不久前,我用C#编写了一个解析器,完成这一过程很容易,因为每个解析器都是一个函数,它们可以相互调用,而不依赖于它们是在之前还是之后定义的

所以我想知道如何用F来解决这个问题#

下面是提到的解析器:

//解析由1个或多个换行符分隔的语句列表,(pre | post)由任意数量的空格固定,并在到达“end”关键字时完成解析
让block endtag=many1Till(statement.>>nl)(skipString endtag)//此时,语句未定义
//解析循环结构;关键字loop,后跟迭代变量的标识符,后跟计算应执行的迭代次数的表达式,后跟用“endloop”闭合的块
让循环=跳过“循环”>>。ws1>>。id.>>ws1.>>。expr.>>nl.>>。块“endloop”|>>fun((i,n),s)->Loop(i,n,s)
//解析任何语句,前或后由任意数量的空格固定
let语句=空格>>。选择[writeline;write;comment;定义;循环;休眠;赋值]。>>空格

FParsec通过
createParserForwardedToRef
支持递归解析器。这本书展示了如何使用它。以下是相关信息的摘录:

JSON列表和对象的语法规则是递归的,因为任何列表或对象本身都可以包含任何类型的JSON值。因此,为了编写列表和对象语法规则的解析器,我们需要一种方法来引用解析器以获取任何类型的JSON值,即使我们还没有构建这个解析器。就像计算中经常出现的情况一样,我们可以通过引入额外的间接方式来解决这个问题:

让jvalue,jvalueRef=createParserForwardedToRef()

正如您可能从名称猜到的,
createParserForwardedToRef
创建一个解析器(
jvalue
),该解析器将所有调用转发到引用单元格中的解析器(
jvalueRef
)。最初,引用单元持有一个虚拟解析器,但由于引用单元是可变的,我们可以在完成构建后用实际值解析器替换虚拟解析器