F# 为什么FParsec不使用解析列表分隔符的字符?

F# 为什么FParsec不使用解析列表分隔符的字符?,f#,fparsec,F#,Fparsec,下面的实际场景由以下部分组成。这个问题的目的是为了更多地了解FParsec在这里做什么 我正在分析由一个或多个空格字符分隔的字符串列表(w)和(x) my list的解析器xs与分隔符解析器isSeparator一起使用 isSeparator基于并似乎正确使用了空格。我相信这可以在下面的测试输出中看到,当它解析以位置3结尾的两个前导空格字符时 但是,当我在xs中使用它时,它失败了,如下所示 为什么这会失败?对于处理可能是一个或多个空格的分隔符,什么是好方法 open FParsec let

下面的实际场景由以下部分组成。这个问题的目的是为了更多地了解FParsec在这里做什么

我正在分析由一个或多个空格字符分隔的字符串列表
(w)
(x)

my list的解析器
xs
与分隔符解析器
isSeparator
一起使用

isSeparator
基于并似乎正确使用了空格。我相信这可以在下面的测试输出中看到,当它解析以位置3结尾的两个前导空格字符时

但是,当我在
xs
中使用它时,它失败了,如下所示

为什么这会失败?对于处理可能是一个或多个空格的分隔符,什么是好方法

open FParsec

let test p str =
    match run p str with
    | Success(result, _, p)   -> printfn "Success: %A position = %A" result p
    | Failure(errorMsg, _, _) -> printfn "Failure: %s" errorMsg

let str s = pstringCI s

let w = str "(w)"
let z = str "(z)"

let woz = w <|> z

let isSeparator = manySatisfy (fun c -> c = ' ')
let xs = sepBy woz isSeparator

test isSeparator "  (w)" // Success: "  " position = (Ln: 1, Col: 3)
test xs "(z) (w)"        // Failure: Error in Ln: 1 Col: 8
                         // (z) (w)
                         //        ^
                         // Note: The error occurred at the end of the input stream.                         
                         // Expecting: '(w)' (case-insensitive) or '(z)' (case-insensitive)
打开FParsec
let测试p str=
将runp str与
|成功(结果,p)->printfn“成功:%A位置=%A”结果p
|失败(errorMsg,,->打印fn“失败:%s”errorMsg
设str s=pstringCI s
设w=str“(w)”
设z=str“(z)”
设woz=wz
让isSeparator=many满足(乐趣c->c='')
设xs=sebby-woz为分离器
测试isSeparator“(w)”//成功:“位置=(项次:1,列:3)
测试xs“(z)(w)“//失败:Ln:1列中的错误:8
//(z)(w)
//        ^
//注意:错误发生在输入流的末尾。
//应为:“(w)”(不区分大小写)或“(z)”(不区分大小写)

之所以会发生这种情况,是因为
manySatisfy
匹配满足给定谓词的零个或多个字符,关键字是“零”。这意味着,在输入的最后,
isSeparator
实际上成功了,即使它不使用任何字符。由于
isSeparator
成功,因此
sebby
希望在分隔符之后找到另一个
woz
实例。但是没有更多的实例,因此
sebby
返回一个错误

要验证这一点,请尝试解析输入,在
w
z
之间不带空格:
testxs“(z)(w)”
。这应该打印“Success”,因为空分隔符是可以的

若要使isSeparator始终使用至少一个字符,并且在找不到空格时失败,请使用
many满足
而不是
many满足

let isSeparator = many1Satisfy (fun c -> c = ' ')
let xs = sepBy woz isSeparator

我不太清楚问题是什么。解析器
xs
正确地解析由单个空格分隔的
w
z
,因为这是您指定的分隔符。解析器
x2
应该像您期望的那样工作:解析
w
z
由多个空格分隔。哦,天哪,我的错……代码格式不正确。将进行编辑和更新。谢谢Fyodor Soikin。我现在编辑并更新了代码。今天花了几个小时在这上面,“关键词是‘零’”,这句话会一直留在我的脑海中!谢谢。很乐意帮忙。:-)