匹配多个ParserResult并提取值 [英] Matching More than One ParserResult and Extracting Values

查看:43
本文介绍了匹配多个ParserResult并提取值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是有关使用FParsec的ParserResult的问题.

This is a question about working with FParsec's ParserResult.

是否有一个更干净的 match_result 实现,可以提取 ParserResult 中包含的 XKEYVALUE XATTRIBUTES 两个嵌套的匹配项?

Is there a cleaner implementation of match_result to pull out the XKEYVALUE or XATTRIBUTES contained inside the ParserResult without two nested matches?

以下代码可用作F#控制台应用程序...

The following code works as a F# console app...

// Learn more about F# at http://fsharp.org

open System
open FParsec

// Types
type XKEYVALUE = string * string
type XATTRIBUTES = Map< string, string>

type PARSER_RESULT_XML = 
    | PR_XKEYVALUE of ParserResult<XKEYVALUE, unit>
    | PR_XATTRIBUTES of ParserResult<XATTRIBUTES, unit>

// Parser Trace
let (<!>) (p: Parser<_,_>) label : Parser<_,_> =
    fun stream ->
        printfn "%A: Entering %s" stream.Position label
        let reply = p stream
        do
            match (reply.Status) with
                | Ok  -> printfn "%A: Leaving %s (%A) - %A" stream.Position label reply.Status reply.Result
                | Error -> printfn "%A: Leaving %s (%A) - %A" stream.Position label reply.Status reply.Error
                | FatalError -> printfn "%A: Leaving %s with FatalError (%A)" stream.Position label reply.Status
                | _ -> printfn "%A: Leaving %s with unknown status" stream.Position label
        reply

// Parsers
let ws = spaces
let str = pstring
let xKey : Parser<string,unit> = (ws >>. regex "[a-zA-Z][a-zA-Z0-9:]*") <!> "xKey"
let xStringLiteral = regex "[^\"]+" <!> "xStringLiteral"
let xKeyValue : Parser<XKEYVALUE, unit> = 
    ws >>. xKey .>>. (ws >>. str "=" >>. ws >>. str "\"" >>. xStringLiteral .>> str "\"" .>> ws) |>> XKEYVALUE <!> "xKeyValue"
let xAttributes : Parser<XATTRIBUTES, unit> = sepEndBy xKeyValue ws |>> XATTRIBUTES <!> "xAttributes"

// Test Data
let xKeyValue_text = """    key =  "value"    aa"""
let xAttributes_text = "key1=\"value1\" key2=\"value2\""

let match_result ( result : PARSER_RESULT_XML) : string =
    match result with 
        | PR_XKEYVALUE(a) ->    match a with  
                                    | Success( ((key : string), (value : string)), x2, x3) -> sprintf "%s=\"%s\"" key value
                                    | Failure( _, _, _) -> sprintf "FAILURE"
        | PR_XATTRIBUTES( a) -> match a with
                                    | Success( (x1 : Map<string, string>), x2, x3) -> sprintf "x1=%A, x2=%A, x3=%A" x1 x2 x3
                                    | Failure( _, _, _) -> sprintf "FAILURE"

[<EntryPoint>]
let main argv =
    run xKeyValue xKeyValue_text |> PR_XKEYVALUE |> match_result |> printfn "%A"
    run xAttributes xAttributes_text |> PR_XATTRIBUTES |> match_result |> printfn "%A"
    0 // return an integer exit code

但是 match_result 嵌套匹配看起来很笨拙.

But match_result just seems clumsy with its nested matches.

失败的实验是使用 AND模式比对,以匹配 PARSER_RESULT_XML&在相同的匹配表达式中成功(…),但我无法使两个匹配表达式的类型一致.

A failed experiment was to use an AND pattern match to put the match of PARSER_RESULT_XML & Success( …) in the same match expression but I couldn't get the types of the two match expressions to agree.

您将如何修改 match_result 以便做得更好或更清洁?

How would you modify match_result to do this better or cleaner?

推荐答案

您可以根据需要对结构中的深度进行模式匹配:

You can pattern match how deep as you need into a structure:

let match_result result =
    match result with
    | PR_XKEYVALUE (Success ((key, value), _, _)) -> sprintf "%s=\"%s\"" key value 
    | PR_XATTRIBUTES (Success (x1, x2, x3)) -> sprintf "x1=%A, x2=%A, x3=%A" x1 x2 x3
    | _ -> "FAILURE"

这篇关于匹配多个ParserResult并提取值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆