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

时间:2019-01-02 16:17:23

标签: exception f# 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

因此,我想分析一个标识符以验证其是否符合标识符类型的条件。如果确定它不符合条件,我将返回failwith的错误。 但是,当我使用此解析器(标识)并在要分析的文本中故意存在错误时,要检查一切是否正常,我会得到一个长错误:

enter image description here

(对不起,我是法语,所以错误消息^^中有一点法语。)

如何防止所有这些情况,并且仅使用FParsec以经典方式显示错误消息?

1 个答案:

答案 0 :(得分:2)

failwith函数会引发.NET异常-属巨灾失败,应表明程序以意外方式中断。或者,换句话说,以 exception 的方式命名-因此命名为“ 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"