我目前正在學習FParsec庫,但遇到了一個問題。當我想要解析一個可選字符串並繼續正常解析時,FParsec將在可選解析器上返回一個致命錯誤,而不是像我期望的那樣返回None
。下面的工作代碼示例說明了我的觀點:FParsec在可選解析器上失敗
open System
open FParsec
type AccountEntity =
| Default
| Entity of string
let pEntity =
let isEntityFirstChar c = isLetter c
let isEntityChar c = isLetter c || isDigit c
(many1Satisfy2L isEntityFirstChar isEntityChar "entity") .>> skipString "/"
let pOptEntity =
opt pEntity
|>> (fun optEntity ->
match optEntity with
| Some entity -> Entity entity
| None -> Default)
[<EntryPoint>]
let main argv =
printfn "%A" (run pOptEntity "test/account:subaccount") //works
printfn "%A" (run pOptEntity "account:subaccount") //crashes
Console.ReadLine() |> ignore
0 // return an integer exit code
我期望的行爲是在不設置實體pOptEntity
返回一個Default
實體。但是,相反,我得到以下錯誤:
Failure:
Error in Ln: 1 Col: 8
account:subaccount
^
Expecting: '/'
不應該opt
提供我所描述的,繼續解析帳戶字符串爲正常還是我不正確的方式處理這個問題?我看了一下attempt
,但是,我不能像我想要的那樣提供默認的實體行爲。
非常感謝您的幫助,謝謝。
所以它只會嘗試下位,如果解析器沒有任何消耗輸入其已經被指示要走回頭路? –
我不清楚你在那個問題中說「它」時的意思。如果你的意思是'<|>'combinator,那麼刪除短語「它已被指示回溯」,答案將是「是」。 '<|>'combinator只會嘗試下一位,如果第一個解析器失敗*沒有消費輸入*。無論是第一個解析器立即失敗,還是嘗試了某種東西然後回溯,與組合器的觀點無關。所有'<|>'知道的是「我嘗試了第一個解析器,並且流仍然處於相同的狀態」。我會在下一條評論中提到'。>>?'。 – rmunn
如果您的問題中的「it」一詞表示'。>>?'combinator,那麼答案是「否」。 '。>>?'組合器將首先嚐試下一位,如果下一位失敗,它將在第一位嘗試*之前回溯到解析器狀態*。以'?'結尾的其他組合變體都遵循類似的規則:它們都嘗試第二位,如果失敗,則返回到第一位嘗試之前的狀態。 – rmunn