使用 FParsec 解析 float 或 int*float

Use FParsec to parse float or int*float

我刚刚开始使用 FParsec,现在我正在尝试解析以下格式的字符串

10*0.5 0.25 0.75 3*0.1 0.9

我要3*0.1,例如,展开成0.1 0.1 0.1

目前我有以下内容

type UserState = unit
type Parser<'t> = Parser<'t, UserState>

let str s : Parser<_> = pstring s

let float_ws : Parser<_> = pfloat .>> spaces

let product = pipe2 pint32 (str "*" >>. float_ws) (fun x y -> List.init x (fun i -> y)) 

产品解析器正确解析了 int*float 格式的条目并将其扩展为浮点数列表。但是,我无法想出一个允许我解析 int*float 或只是一个浮点数的解决方案。我想做类似

的事情
many (product <|> float_ws)

这当然行不通,因为 return 类型的解析器不同。关于如何使这项工作有任何想法吗?是否可以包装修改 float_ws 使其 return 是一个只有一个浮点数的列表?

您只需添加 |>> List.singleton

即可使 float_ws return 成为 float list
let float_ws : Parser<_> = pfloat .>> spaces |>> List.singleton

|>> 只是 map 函数,您可以在其中将某些函数应用于一个解析器的结果并接收某种新类型的新解析器:

val (|>>): Parser<'a,'u> -> ('a -> 'b) -> Parser<'b,'u>

参见:http://www.quanttec.com/fparsec/reference/primitives.html#members.:124::62::62:


此外,由于product解析器包含一个int解析器,它会成功地从错误的大小写中解析出一个字符,这意味着解析器状态将被改变。这意味着您不能直接在第一个解析器上使用 <|> 运算符,您还必须添加 attempt 以便 FParsec 可以 return 到原始解析器状态。

let combined = many (attempt product <|> float_ws)