F# 让FParsec拒绝不匹配的开始-结束标记?

F# 让FParsec拒绝不匹配的开始-结束标记?,f#,fparsec,F#,Fparsec,编写自己的XML解析器来学习FParsec,我需要测试XML开始和结束标记是否匹配,或者让解析器失败 在下面的代码片段中 解析器xStartTag和xKey返回我想要匹配的strings 解析器xContent\u untlclosetag只返回标记之间的内容 ws跳过空格和str(“>”)跳过一个'>' PipeN.pipe10函数是标准FParsec原语pipe5的扩展,用于将10个解析器的结果输入到函数中 所有这些解析器都编译并工作 当开始标记和结束标记不匹配时,如何使以下类型为par

编写自己的XML解析器来学习FParsec,我需要测试XML开始和结束标记是否匹配,或者让解析器失败

在下面的代码片段中

  • 解析器
    xStartTag
    xKey
    返回我想要匹配的
    string
    s
  • 解析器
    xContent\u untlclosetag
    只返回标记之间的内容
  • ws
    跳过空格和
    str(“>”)
    跳过一个'>'
  • PipeN.pipe10
    函数是标准FParsec原语
    pipe5
    的扩展,用于将10个解析器的结果输入到函数中
所有这些解析器都编译并工作

当开始标记和结束标记不匹配时,如何使以下类型为
parser
的解析器构建类型
XELEMENT\u CONTENT
失败

00 let xElement_Content : Parser<XELEMENT, USER_STATE> =
01    (PipeN.pipe10 ws xStartTag ws xContent_UntilCloseTag ws xKey ws (str ">") ws
02                  (fun stream -> getUserState stream)
03                  (fun x1 x2_startTag x3 x4_content x5 x6_closeTag x7 x8 x9 userState ->
04                    if x2_startTag.head = x6_closeTag
05                        then
06                            (userState.Deeper(x2_startTag.head), x2_startTag, x4_content)
07                        else Reply(FatalError, messageError ("in xElementContent: head tag (%s) does not match close tag (%s)", x2_startTag.head, x6_closeTag))
08                   ) |>> C_XELEMENT_CONTENT
09                  )

我已经详细查看了(特别是)但是可能遗漏了什么?

我认为您不需要维护用户状态来匹配XML标记。下面是一个非常简单的解析器,可以正确地检测不匹配(但不处理嵌套标记):

打开FParsec
让它打开=
pstring“”
让我关上=
pstring“”
让语法分析器输入=
parseTagOpen

.>>. (manySatisfy(fun c->c)你是对的,用户状态用于跟踪嵌套深度,这与此问题无关。请注意,“failfailly”内部发生了什么?我认为这是实际的答案-谢谢!这是一个内置解析器,只返回致命错误。请参见相同的错误:-(失败的
的返回时间是解析器,它不符合预期的返回类型
XELEMENT\u CONTENT
if
的两个分支都需要返回相同的类型。啊,好的。如果您试图理解代码为什么不编译,请注意,我代码中if语句的另一个分支调用
pre转动
,而不是返回原始元组。这是必要的,因为整个函数实际上是一个解析器,通过bind调用(
>=
),而不是
pipeN
。这允许解析器在标记不匹配时正常失败。另一方面,一旦
pipeN
调用10参数函数,就无法正常失败。您确实需要绑定(或使用
parse
计算表达式)。
type USER_STATE =
    {
        tag : string
    depth : int
    }

type XELEMENT_CONTENT = USER_STATE * XHEADandATTRIBUTES_RECORD * string
type XELEMENT_EMPTY = XHEADandATTRIBUTES_RECORD

type XELEMENT =
    | C_XELEMENT_CONTENT of XELEMENT_CONTENT
    | C_XELEMENT_NESTED of USER_STATE * XHEADandATTRIBUTES_RECORD * (XELEMENT list)
    | C_XELEMENT_EMPTY of XELEMENT_EMPTY

type XELEMENT_NESTED = XHEADandATTRIBUTES_RECORD * (XELEMENT list)