【问题标题】:Why are these two FParsec snippets different?为什么这两个 FParsec 片段不同?
【发布时间】:2021-02-16 18:20:13
【问题描述】:

我想解析给定的char 两次,但只返回该字符的string 一次。

例如:

aa    ->    a

我有一些代码可以工作,但也有一些代码不能工作,我不明白为什么。

为什么这些 sn-ps 不同?

// Works
let parseEscapedQuote (c : char)  =
  let q = string c
  pstring (q + q) >>% q
// Does not work
let parseEscapedQuote (c : char)  =
  let q = string c
  pchar c >>. pchar c >>% q

【问题讨论】:

    标签: f# fparsec


    【解决方案1】:

    第二个将成功地以您想要的方式解析重复的字符,但它可能不会以您期望的方式失败。如果只有第一个 pchar c 成功,它将使您的解析器处于无效状态。要解决此问题,您可以使用attempt,如果失败则恢复之前的状态:

    attempt (pchar c >>. pchar c) >>% q
    

    这里有一个完整的例子来说明差异:

    open FParsec
    
    let parseTwiceBad (c : char) =
        pchar c >>. pchar c >>% string c
    
    let parseTwiceGood (c : char) =
        attempt (pchar c >>. pchar c) >>% string c
    
    let mkParser parseTwice =
        choice [
            parseTwice 'x'
            anyString 3
        ]
    
    let run parser str =
        let result = runParserOnString parser () "" str
        match result with
            | Success (value, _, _) -> printfn "Success: %A" value
            | Failure (msg, _, _) -> printfn "Failure: %s" msg
    
    let test str =
    
        printfn ""
        printfn "Parsing \"%s\" with bad parser:" str
        let parser = mkParser parseTwiceBad
        run parser str
    
        printfn "Parsing \"%s\" with good parser:" str
        let parser = mkParser parseTwiceGood
        run parser str
    
    [<EntryPoint>]
    let main argv =
        test "xx"
        test "xAx"
        0
    

    输出:

    Parsing "xx" with bad parser:
    Success: "x"
    Parsing "xx" with good parser:
    Success: "x"
    
    Parsing "xAx" with bad parser:
    Failure: Error in Ln: 1 Col: 2
    xAx
     ^
    Expecting: 'x'
    
    Parsing "xAx" with good parser:
    Success: "xAx"
    

    【讨论】:

    • 谢谢,有道理。我发现回溯 /attempt 是使用 FParsec 时最容易出错的部分。
    • 是的,这可能会造成混淆。 attempt 有点慢,但它可以更容易地推断解析器的行为。
    猜你喜欢
    • 1970-01-01
    • 2018-09-11
    • 1970-01-01
    • 2012-08-26
    • 1970-01-01
    • 1970-01-01
    • 2011-04-30
    • 2015-12-21
    • 2022-07-04
    相关资源
    最近更新 更多