gpt4 book ai didi

f# - FParsec 在很多方面都失败了

转载 作者:行者123 更新时间:2023-12-04 17:23:17 26 4
gpt4 key购买 nike

我有这个测试程序:

open FParsec

let test p str =
match run p str with
| Success(result, _, _) -> printfn "Success: %A" result
| Failure(errorMsg, _, _) -> printfn "Failure: %s" errorMsg

let str s = pstring s

let sepPart = skipNewline >>. pstring "-"

let part = manyChars (notFollowedBy sepPart >>. anyChar)

[<EntryPoint>]
let main argv =
let s = "AA 12345\nBB 6789\n-----\nCC 9876\nDD 54321\n-----"
test part s
test (many part) s

0 // return an integer exit code

{test part s} 行按预期工作,但下一行 {test (many part) s} 失败,我不明白我做错了什么。

编辑:

澄清一下,我想要做的是让 {test (many part) s} return ["AA 12345\nBB 6789"; “抄送 9876\nDD 54321”]。换句话说,我拥有的是一个由“pars”或“chunks”组成的输入字符串,这些字符串由带有所有破折号的行分隔。对于输出,我想要一个数组,其中每个元素都是部分之一,并且带破折号的线被简单地丢弃。

最佳答案

当您执行您的示例时,FParsec 会抛出一个带有以下消息的异常:

Additional information: (Ln: 2, Col: 8): The combinator 'many' was applied to a parser that succeeds without consuming input and without changing the parser state in any other way. (If no exception had been raised, the combinator likely would have entered an infinite loop.)



问题是你的 part parser 总是会成功,即使它只能解析一个空字符串。您可以通过替换 manyChars 来解决该问题。在 part的定义中与 many1Chars .

如果您搜索例如“应用于无需消耗输入即可成功的解析器”,您会在 Internet 上找到一些关于类似错误的讨论,其中包括 FParse 的用户指南: http://www.quanttec.com/fparsec/users-guide/parsing-sequences.html#the-many-parser

更新:
这是一个简单的解析器定义:
let sepPart = skipNewline 
>>? (skipMany1SatisfyL ((=) '-') "'-'"
>>. (skipNewline <|> eof))

let part = many1CharsTill anyChar sepPart
let parser = many part

请注意,我正在使用 >>?sepPart的定义中如果换行符后面没有破折号,则允许此解析器回溯到开头。或者,您也可以使用 attempt (skipNewline >>. ...) ,这也会在初始破折号后回溯错误。 many[Chars]Till p endp 的文档声明与 many (notFollowedBy endp >>. p) .>> endp 等价这并不严格,因为 many[Chars]Till不像 notFollowedBy 那样回溯.我将澄清文档。

如果使用 many[Chars]Till 避免回溯,则性能会更好或 notFollowedBy在可能的情况。例如,您还可以按如下方式解析您的行块:
let id = manyMinMaxSatisfyL 2 2 isUpper "id (two capital letters)"

let line = id .>>. (pchar ' ' >>. restOfLine true)

let separator = many1SatisfyL ((=) '-') "dash separator"
>>. (skipNewline <|> eof)

let chunk = many1 line
let parser = sepEndBy1 chunk separator

请注意,此实现不需要以分隔符结束最后一个块。如果你想要,你可以改用:
let chunk = many line .>> separator
let parser = many chunk

如果你想用 sepEndBy 允许空块定义,你可以使用:
let chunk = many1 line <|> (notFollowedByEof >>% [])
let parser = sepEndBy1 chunk separator

关于f# - FParsec 在很多方面都失败了,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16638867/

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