【问题标题】:F# how to define "recursive" variablesF#如何定义“递归”变量
【发布时间】:2021-07-11 12:07:28
【问题描述】:

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

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

这里是提到的解析器:

// parses a list of statements, separated by 1 or more newlines, (pre|post)fixed by any amount of whitespace, and finishes parsing upon reaching an "end" keyword
let block endtag = many1Till (statement .>> nl) (skipString endtag) // at this moment, statement is undefined

// parses a loop structure; the keyword loop, followed by an identifier for the iteration variable, followed by an expression which evaluates to the amount iterations which should be executed, followed by a block closed with "endloop"
let loop = skipString "loop" >>. ws1 >>. id .>> ws1 .>>. expr .>> nl .>>. block "endloop" |>> fun ((i, n), s) -> Loop (i, n, s)

// parses any statement, pre or post fixed by any amount of whitespace
let statement = spaces >>. choice [writeline; write; comment; definition; loop; sleep; assignment] .>> spaces

【问题讨论】:

    标签: functional-programming f# fparsec


    【解决方案1】:

    FParsec 通过createParserForwardedToRef 支持递归解析器。 JSON parser described in the tutorial 展示了如何使用它。以下是相关信息的摘录:

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

    let jvalue, jvalueRef = createParserForwardedToRef<Json, unit>()

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-04
      • 1970-01-01
      • 2014-11-02
      • 2020-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-13
      相关资源
      最近更新 更多