gpt4 book ai didi

parsing - FParsec - 解析器序列

转载 作者:行者123 更新时间:2023-12-02 17:43:28 27 4
gpt4 key购买 nike

假设我有一些文字:

a = "foobarbaz"
b = "foobar"
c = "foo"
d = "rubbish"
e = "foobazbar"

以及分别用于字符串 'foo'、'bar' 和 'baz' 的三个解析器 foo、bar 和 baz。

我将如何创建一个能给我结果的解析器:

a = ["foo", "bar", "baz"]
b = ["foo", "bar"]
c = ["foo"]
d = []
e = ["foo"]

什么时候针对上面的输入运行?基本上尝试每种可能性,直到在构建列表时失败。我可以使用用户状态,但我想尽可能避免。 (我想让各个解析器自己对用户状态一无所知)

我得到的最接近的是下面的 fooseq:

let foo = pstring "foo"
let bar = pstring "bar"
let baz = pstring "baz"

let foobar = pipe2 foo bar Seq.of2
let foobarbaz = pipe3 foo bar baz Seq.of3

let fooseq = choice (Seq.map attempt [foobarbaz; foobar; foo |>> Seq.of1 ;])

//(the Seq.ofx functions just take arguments and create a sequence of them)

在我看来一定有更好的方法来做到这一点?

最佳答案

FParsec 没有内置的序列组合器可以完全满足您的需求,但您可以自己实现一个,如下例所示:

let mySeq (parsers: seq<Parser<'t,'u>>) : Parser<'t[],'u> =
let ps = Array.ofSeq parsers
if ps.Length = 0 then preturn [||]
else
fun stream ->
let mutable stateTag = stream.StateTag
let mutable reply = ps.[0] stream
let mutable error = reply.Error
let mutable myReply = Reply()
if reply.Status <> Ok then myReply.Result <- [||]
else
// create array to hold results
let mutable xs = Array.zeroCreate ps.Length
xs.[0] <- reply.Result
let mutable i = 1
while i < ps.Length do
stateTag <- stream.StateTag
reply <- ps.[i] stream
error <- if stateTag <> stream.StateTag then reply.Error
else mergeErrors error reply.Error
if reply.Status = Ok then
xs.[i] <- reply.Result
i <- i + 1
else // truncate array and break loop
xs <- Array.sub xs 0 i
i <- ps.Length
myReply.Result <- xs
myReply.Status <- if reply.Status = Error && stateTag = stream.StateTag
then Ok
else reply.Status
myReply.Error <- error
myReply

使用 mySeq 组合器,您可以将您的 fooSeq 解析器表示为

let fooSeq = mySeq [foo; bar; baz]

关于parsing - FParsec - 解析器序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17768349/

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