gpt4 book ai didi

f# - FParsec:如何从错误消息中省略 `many` 解析器失败

转载 作者:行者123 更新时间:2023-12-04 20:27:20 24 4
gpt4 key购买 nike

考虑这个将数字字符串转换为 int 的解析器s:

let toInt (s:string) = 
match Int32.TryParse(s) with
| (true, n) -> preturn n
| _ -> fail "Number must be below 2147483648"

let naturalNum = many1Chars digit >>= toInt <?> "natural number"

当我在非数字字符串上运行它时,比如 "abc"它显示了正确的错误信息:

Error in Ln: 1 Col: 1
abc
^
Expecting: natural number

但是当我给它一个超过 int 的数字字符串时range 它给出了以下适得其反的信息:

Error in Ln: 1 Col: 17
9999999999999999
^
Note: The error occurred at the end of the input stream.
Expecting: decimal digit
Other error messages:
Number must be below 2147483648

主要留言 "Expecting: decimal digit"没有意义,因为我们已经有很多数字了。

有没有办法摆脱它,只显示 "Number must be below 2147483648" ?

完整示例:
open System
open FParsec

[<EntryPoint>]
let main argv =
let toInt (s:string) =
match Int32.TryParse(s) with
| (true, n) -> preturn n
| _ -> fail "Number must be below 2147483648"

let naturalNum = many1Chars digit >>= toInt <?> "natural number"

match run naturalNum "9999999999999999" with
| Failure (msg, _, _) -> printfn "%s" msg
| Success (a, _, _) -> printfn "%A" a

0

最佳答案

我认为这里问题的根源在于这是一个非语法问题,它不适合前瞻解析器的模型。如果您可以以句法方式表达“太多数字”,那么解析器也很有意义,但实际上它会返回并尝试消耗更多输入。因此,我认为最干净的解决方案是在解析后在单独的 channel 中进行 int 转换。

也就是说,FParsec 似乎足够灵活,您仍然应该能够一起破解它。这符合你的要求,我认为:

let naturalNum: Parser<int, _> =
fun stream ->
let reply = many1Chars digit stream
match reply.Status with
| Ok ->
match Int32.TryParse(reply.Result) with
| (true, n) -> Reply(n)
| _ -> Reply(Error, messageError "Number must be below 2147483648")
| _ ->
Reply(Error, reply.Error)

或者,如果您想要“自然数”错误消息而不是“十进制数字”,请将最后一行替换为:
Reply(Error, messageError "Expecting: natural number")

关于f# - FParsec:如何从错误消息中省略 `many` 解析器失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56300298/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com