简单的FParsec列表示例

时间:2019-07-08 19:00:14

标签: f# fparsec

我刚刚开始使用FParsec,不能把头放在一个简单的列表解析器上。 输入正确

"{ a;b;c d; }"

我想得到结果['a';'b';'c';'d']

如果我这样做

let baseChars = ['0'..'9'] @ ['A'..'Z'] @ ['a'..'z'] @ ['_'; '-']
let chars : Parser<_> = anyOf baseChars
let nameChars : Parser<_> = anyOf (baseChars @ ['.'])                

let semiColonList p : Parser<_> = sepBy p (pstring ";")
let pList p : Parser<_> = between (pstring "{") (pstring "}") (semiColonList p)

do  """{
    a;b;c;
    d;
}"""
    |> run (parse {
        let! data = pList (spaces >>. many1Chars nameChars)
        return data
    })
    |> printfn "%A"

我在最后一个}上失败,因为它在关闭之间的解析器之前试图与nameChars解析器上的匹配。 感觉好像缺少一个简单的解决方案,特别是因为如果我按预期的那样在d之后删除了最后一个分号,那么我会发现。 任何帮助表示赞赏。

[编辑] 感谢Fyodor Soikin的以下作品:

    let semiColonList p = many (p .>> (pstring ";" >>. spaces))
    let pList p : Parser<_> = between (pstring "{") (pstring "}") (semiColonList p)
    """{
    a;b;c;
    d;
}"""
    |> run (parse {
        let! data = pList (spaces >>. many1Chars nameChars)
        return data
    })
    |> printfn "%A" 

1 个答案:

答案 0 :(得分:3)

sepBy不允许尾随分隔符。像sepBy a b这样的解析器旨在像a b a b a那样解析输入,但是您的输入就像a b a b a b一样-末尾还有一个额外的分隔符b

您要做的是解析多个类似于a b的表达式-这样将为您提供所需的输入形状。

为了解析一个这样的表达式,请使用排序运算符.>>,为了解析多个这样的对,请使用many

semiColonList p = many (p .>> pstring ";")