具有 2 种模式之一的 FParsec 匹配字符串
FParsec match string which have one of 2 patterns
我正在尝试学习 FParsec 并尝试匹配遵循两种模式的字符串。
该字符串可以是普通字符串,如 "string"
,也可以是带一个点的字符串,如 "st.ring"
.
解析器应如下所示:Parser<(string Option * string),unit>
。第一个字符串是可选的,具体取决于字符串是否被点分隔。可选字符串表示 "."
.
之前的字符串部分
我尝试了一些不同的东西,但我觉得这次尝试是结束:
let charstilldot = manyCharsTill anyChar (pstring ".")
let parser = opt(charstilldot) .>>. (many1Chars anyChar)
这适用于这样的输入 "st.ring"
但不适用于 "string"
因为后者不存在点。
非常感谢您的帮助,谢谢!
编辑:
我有一个解决方案,它基本上按顺序解析参数并根据它们是否在字符串
中是一个点来交换参数
let colTargetWithoutDot : Parser<string Option,unit> = spaces |>> fun _ -> None
let colTargetWithDot = (pstring "." >>. alphastring) |>> Some
let specificColumn = alphastring .>>. (colTargetWithDot <|> colTargetWithoutDot) |>> (fun (h,t) ->
match h,t with
| h,None -> (None,h)
| h,Some(t) -> (Some(h),t))
但是这不是很好,所以我仍然会推荐另一个解决方案!
我认为这里的主要问题是 charstilldot
即使失败也会消耗字符。在这种情况下,many1chars
会失败,因为整个输入已被消耗。解决此问题的最简单方法是在没有点时使用 attempt
回滚:
let charstilldot = attempt (manyCharsTill anyChar (pstring "."))
let parser = opt(charstilldot) .>>. (many1Chars anyChar)
结果:
"str.ing"
-> (Some "str", "ing")
"string"
-> (None, "string")
我认为还有其他好的解决方案,但我已尝试为您提供一个需要对当前代码进行最少更改的解决方案。
我正在尝试学习 FParsec 并尝试匹配遵循两种模式的字符串。
该字符串可以是普通字符串,如 "string"
,也可以是带一个点的字符串,如 "st.ring"
.
解析器应如下所示:Parser<(string Option * string),unit>
。第一个字符串是可选的,具体取决于字符串是否被点分隔。可选字符串表示 "."
.
我尝试了一些不同的东西,但我觉得这次尝试是结束:
let charstilldot = manyCharsTill anyChar (pstring ".")
let parser = opt(charstilldot) .>>. (many1Chars anyChar)
这适用于这样的输入 "st.ring"
但不适用于 "string"
因为后者不存在点。
非常感谢您的帮助,谢谢!
编辑: 我有一个解决方案,它基本上按顺序解析参数并根据它们是否在字符串
中是一个点来交换参数let colTargetWithoutDot : Parser<string Option,unit> = spaces |>> fun _ -> None
let colTargetWithDot = (pstring "." >>. alphastring) |>> Some
let specificColumn = alphastring .>>. (colTargetWithDot <|> colTargetWithoutDot) |>> (fun (h,t) ->
match h,t with
| h,None -> (None,h)
| h,Some(t) -> (Some(h),t))
但是这不是很好,所以我仍然会推荐另一个解决方案!
我认为这里的主要问题是 charstilldot
即使失败也会消耗字符。在这种情况下,many1chars
会失败,因为整个输入已被消耗。解决此问题的最简单方法是在没有点时使用 attempt
回滚:
let charstilldot = attempt (manyCharsTill anyChar (pstring "."))
let parser = opt(charstilldot) .>>. (many1Chars anyChar)
结果:
"str.ing"
->(Some "str", "ing")
"string"
->(None, "string")
我认为还有其他好的解决方案,但我已尝试为您提供一个需要对当前代码进行最少更改的解决方案。