FParsec在可选解析器上失败
问题描述:
我目前正在学习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
,但是,我不能像我想要的那样提供默认的实体行为。
非常感谢您的帮助,谢谢。
答
opt
combinator遵循与<|>
相同的规则;如果您查看<|>
documentation,它会提到如果第一个解析器在未更改解析器状态时失败,则尝试第二个解析器。 http://www.quanttec.com/fparsec/users-guide/parsing-alternatives.html进入更多细节。
在这里,.>>?
combinator是你想在你的pEntity
解析器中使用的。将.>>
替换为.>>?
,您将拥有一个pEntity
解析器,如果它后面没有跟随/
,将回溯到它尝试的内容的开头并且不会消耗输入。这将允许opt
组合器按设计运行。
P.S.我测试了这个,它工作。更换.>>
与.>>?
在pEntity
,然后运行代码产生了以下的输出:
Success: Entity "test"
Success: Default
所以它只会尝试下位,如果解析器没有任何消耗输入其已经被指示要走回头路? –
我不清楚你在那个问题中说“它”时的意思。如果你的意思是''combinator,那么删除短语“它已被指示回溯”,答案将是“是”。 ''combinator只会尝试下一位,如果第一个解析器失败*没有消费输入*。无论是第一个解析器立即失败,还是尝试了某种东西然后回溯,与组合器的观点无关。所有''知道的是“我尝试了第一个解析器,并且流仍然处于相同的状态”。我会在下一条评论中提到'。>>?'。 – rmunn
如果您的问题中的“it”一词表示'。>>?'combinator,那么答案是“否”。 '。>>?'组合器将首先尝试下一位,如果下一位失败,它将在第一位尝试*之前回溯到解析器状态*。以'?'结尾的其他组合变体都遵循类似的规则:它们都尝试第二位,如果失败,则返回到第一位尝试之前的状态。 – rmunn