failwith 在计算表达式中使用时会导致错误 - FParsec

failwith causes an error when used in a calculation expression - FParsec

我使用了一个函数:

let identifier kind =
    (many1Satisfy2L isLetter
        (fun c -> isLetter c || isDigit c) "identifier"
     >>= fun s -> preturn s) >>= fun s -> identifierKind s kind

kind 参数属于这种类型:

type KindOfIdentifier =
    | Data
    | Type
    | Module

这是我分析 kind 参数的函数:

let private identifierKind (id: string) kind =
    match kind with
    | KindOfIdentifier.Data ->
        if id.ToUpper() = id && id.Length > 1 then preturn id
        elif System.Char.IsUpper id.[0] = false then preturn id
        else failwith "Error 1"
    | KindOfIdentifier.Module ->
        if System.Char.IsUpper id.[0] then preturn id
        else failwith "Error 2"
    | KindOfIdentifier.Type ->
        preturn id

因此我想分析一个标识符来验证它是否符合标识符类型的标准。如果识别不符合标准,我return错误failwith。 但是,当我在要分析的文本中故意使用此解析器(识别)来检查是否一切正常时,我收到一个很长的错误:

(抱歉,我是法国人,所以错误信息中有一点法语^^。)

如何防止这一切,并仅以 FParsec 的经典方式显示错误消息?

failwith 函数抛出 .NET 异常 - 灾难性故障,表明程序以意外方式中断。或者,换句话说,以 特殊的 方式 - 因此得名 "exception"。这不是你想要做的。

你在这里试图做的是向 FParsec 表明当前的解析尝试失败,并可能提供对究竟发生了什么的解释。

为此,您需要创建一个 Parser 的错误生成实例 - 与 preturn 返回的类型相同。

虽然 preturn 创建了一个成功的 Parser 实例,但还有另一个函数创建了一个产生错误的实例。这个函数叫做fail。只需使用它:

    | KindOfIdentifier.Data ->
        if id.ToUpper() = id && id.Length > 1 then preturn id
        elif System.Char.IsUpper id.[0] = false then preturn id
        else fail "Error 1"