gpt4 book ai didi

f# - 使用 FParsec 解析分隔列表

转载 作者:行者123 更新时间:2023-12-05 00:48:02 25 4
gpt4 key购买 nike

我正在尝试解析可能是项目列表或可能只是一个项目的内容。我想将结果放入 DU(下面的 Thing)。

我处理这个问题的方式如下,但即使列表中只有一件事,它也会给我一个列表。

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

type Thing =
| OneThing of int
| LotsOfThings of Thing list

let str s = pstringCI s .>> spaces

let one = str "one" |>> fun x -> OneThing 1
let two = str "two" |>> fun x -> OneThing 2
let three = str "three" |>> fun x -> OneThing 3

let oneThing = (one <|> two <|> three)
let lotsOfThings = sepBy1 oneThing (str "or") |>> LotsOfThings

let lotsFirst = (lotsOfThings <|> oneThing)
test lotsFirst "one or two" // Success: LotsOfThings [OneThing 1; OneThing 2]
test lotsFirst "one" // Success: LotsOfThings [OneThing 1]

正确的返回方式是什么 OneThing当列表中只有一项时?

如果我在返回之前测试列表,我可以做到这一点,如下所示。但这真的“感觉”不对。
let lotsOfThings = sepBy1 oneThing (str "or") |>> fun l -> if l.Length = 1 then l.[0] else l |> LotsOfThings

上面的LinqPad在这里: http://share.linqpad.net/sd8tpj.linq

最佳答案

如果你不喜欢在解析后测试列表长度,那么你可以尝试切换你的 <|>表达式先测试单项情况,然后使用 notFollowedBy确保单项案例不会与列表匹配:

let oneThing = (one <|> two <|> three)
let separator = str "or"
let lotsOfThings = sepBy1 oneThing separator |>> LotsOfThings

let oneThingOnly = oneThing .>> (notFollowedBy separator)
let lotsSecond = (attempt oneThingOnly) <|> lotsOfThings
test lotsSecond "one or two" // Success: LotsOfThings [OneThing 1; OneThing 2]
test lotsSecond "one" // Success: OneThing 1

注意 attempt的使用解析器 oneThingOnly .那是因为 documentation for the <|> parser声明(强调原文):

The parser p1 <|> p2 first applies the parser p1. If p1 succeeds, the result of p1 is returned. If p1 fails with a non‐fatal error and without changing the parser state, the parser p2 is applied.



没有 attempt在那里,“一两个”将首先尝试用 oneThingOnly 解析,这将消耗“一”,然后在“或”上失败,但解析器状态将已更改。 attempt组合器基本上在尝试解析器之前制作解析器状态的“书签”,如果该解析器失败,它会返回到“书签”。所以 <|>将在 attempt oneThingOnly 之后看到未更改的解析器状态,然后会尝试 lotsOfThings .

关于f# - 使用 FParsec 解析分隔列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50455569/

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