为了好玩,这里提供使用FParsec解析字符串的概要,它是一个组合器库。
首先,你需要导入一些模块:
open FParsec.Primitives
open FParsec.CharParsers
然后,您可以定义一个解析器,该解析器将匹配括号内的所有字符串:
let betweenParentheses p s = between (pstring "(") (pstring ")") p s
这将匹配任何括号中的字符串,例如
"(42)"
,
"(foo)"
,
"(1,2,3,4,5)"
等,具体取决于作为第一个参数传递的特定解析器
p
。
为了解析像
"(1,2,3,4,5)"
或
"(1,2)"
这样的数字,您可以将
betweenParentheses
与FParsec的内置
sepBy
和
pint32
组合使用。
let pnumbers s = betweenParentheses (sepBy pint32 (pstring ",")) s
pint32
是一个整数解析器,sepBy
是一个解析器,读取由字符串-在这种情况下为","
分隔的值列表。
为了解析整个“组”中的值,例如"(states,(1,2,3,4,5))"
或"(alpha,(1,2))"
,您可以再次使用betweenParentheses
和pnumbers
:
let pgroup s =
betweenParentheses
(manyTill anyChar (pstring ",") >>. spaces >>. pnumbers) s
< p >
manyTill
组合解析任何
char
值,直到遇到
,
。接下来,
pgroup
解析器期望任意数量的空格,然后是由
pnumbers
定义的格式。
最后,您可以定义一个函数,在字符串上运行 pgroup
解析器:
// string -> int32 list option
let parseGroup s =
match run pgroup s with
| Success (result, _, _) -> Some result
| Failure _ -> None
由于该函数返回一个选项,您可以使用List.choose
来映射可解析的字符串:
> ["(states, (1,2,3,4,5))"; "(alpha, (1,2))"; "(final, (1))"]
|> List.choose parseGroup;;
val it : int32 list list = [[1; 2; 3; 4; 5]; [1; 2]; [1]]
使用FParsec很可能过于复杂,除非你有比.NET标准的
string
API更灵活的格式化规则。