FParsec匹配字符串有两个模式之一



我正在努力学习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")

我认为还有其他好的解决方案,但我已经尝试给你一个需要对当前代码进行最小更改的解决方案。

最新更新