微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

FParsec中的递归语法

如何解决FParsec中的递归语法

| 我决定签出FParsec,并尝试为λ表达式编写一个解析器。事实证明,渴望使递归解析变得困难。我该如何解决? 码:
open FParsec

type λExpr =
    | Variable of char
    | Application of λExpr * λExpr
    | Lambda of char * λExpr

let rec FV = function
    | Variable v -> Set.singleton v
    | Application (f,x) -> FV f + FV x
    | Lambda (x,m) -> FV m - Set.singleton x

let Λ0 = FV >> (=) Set.empty

let apply f p =
    parse
        { let! v = p
          return f v }

let λ e =

    let expr,exprR = createParserForwardedToRef()

    let var = lower |> apply Variable

    let app = tuple2 expr expr
                 |> apply Application

    let lam = pipe2 (pchar \'λ\' >>. many lower)
                        (pchar \'.\' >>. expr) (fun vs e ->
                                                List.foldBack (fun c e -> Lambda (c,e)) vs e)

    exprR := choice [
                    lam
                    app
                    var
                    (pchar \'(\' >>. expr .>> pchar \')\')
                    ]

    run expr e
谢谢!     

解决方法

        正如您所指出的那样,问题在于应用程序的解析器以递归方式调用expr,因此存在无限循环。解析器需要编写成始终消耗一些输入,然后决定要做什么。 对于lambda演算,棘手的事情是识别应用程序和变量,因为如果输入的内容类似like1ѭ,则第一个字符表明它可能是它们中的任何一个。 您可以像这样合并应用程序和变量的规则:
let rec varApp = parse {
  let! first = lower |> apply Variable
  let! res = 
    choice [ expr |> apply (fun e -> Application(first,e))
             parse { return first } ]
  return res }
这首先解析一个变量,然后解析另一个表达式(在这种情况下,它是一个应用程序),或者它仅返回该变量(如果该变量之后没有表达式)。其余规则相似:
and lam = 
  pipe2 (pchar \'λ\' >>. many lower)
        (pchar \'.\' >>. expr) (fun vs e ->
    List.foldBack (fun c e -> Lambda (c,e)) vs e)
and brac = pchar \'(\' >>. expr .>> pchar \')\'
and expr = parse.Delay(fun () ->
  choice 
    [ lam; varApp; brac ])
我只是通过使用
parse.Delay()
避免了显式突变的需要(这使得创建递归值引用成为可能)。原则上,它可以写成:
and expr = parse {
  return! choice [ lam; varApp; brac ] }
...但是由于某种原因,如果要在计算表达式中使用
return!
,FParsec不会实现所需的
ReturnFrom
成员。     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。