gpt4 book ai didi

f# - 在 FParsec 中解析简单类型

转载 作者:行者123 更新时间:2023-12-04 20:20:54 25 4
gpt4 key购买 nike

我正在尝试使用 FParsec 解析标准的简单类型(在 lambda 演算的意义上),但是我很难从 Lex/Yacc 样式转换为 FParsec 中使用的样式,特别是在递归定义方面。

我试图解析的类型的例子是:

  • o -> o
  • (o -> o -> o) -> o

  • 这是我的尝试:

    type SType =
    | Atom
    | Arrow of SType * SType

    let ws = spaces
    let stype, styperef = createParserForwardedToRef()

    let atom = pchar 'o' .>> ws |>> (fun _ -> Atom)

    let arrow = pipe2 (stype .>> (pstring "->" .>> ws))
    stype
    (fun t1 t2 -> Arrow (t1,t2))

    let arr = parse {
    let! t1 = stype
    do! ws
    let! _ = pstring "->"
    let! t2 = stype
    do! ws
    return Arrow (t1,t2)
    }

    styperef := choice [ pchar '(' >>. stype .>> pchar ')';
    arr;
    atom ]

    let _ = run stype "o -> o"`

    当我将其加载到交互中时,最后一行会导致堆栈溢出(具有讽刺意味的是,这些天很难搜索)。我可以想象为什么,鉴于存在递归引用,但我会认为一个标记前瞻会阻止遵循 stype 中的第一个(括号内的)选择.因此,我认为它必须选择 arr ,选择 stype , 等等。但是如何防止这种循环呢?

    我对有关图书馆惯用用法的评论以及对我尝试的解决方案的更正感兴趣。

    最佳答案

    当您使用 FParsec 时,您需要在 sequence combinators 的帮助下解析序列而不是左递归。例如,在您的情况下,您可以使用 sepBy1组合器:

    open FParsec

    type SType =
    | Atom
    | Arrow of SType * SType

    let ws = spaces : Parser<unit, unit>
    let str_ws s = pstring s >>. ws

    let stype, stypeRef = createParserForwardedToRef()

    let atom = str_ws "o" >>% Atom

    let elem = atom <|> between (str_ws "(") (str_ws ")") stype

    do stypeRef:= sepBy1 elem (str_ws "->")
    |>> List.reduceBack (fun t1 t2 -> Arrow(t1, t2))

    let _ = run stype "o -> o"

    关于f# - 在 FParsec 中解析简单类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6763982/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com