fparsec解析具有不同数据类型的键值对

时间:2015-08-27 02:56:10

标签: f# parser-combinators fparsec

我试图编写一个解析器,它可以解析可能因值数据类型而异的键值对。

  

KEY1:1,2,3

     

KEY2:ABC

     

KEY3:123

使用以下代码

open FParsec
type UserState = unit
type Parser<'t> = Parser<'t,UserState>

let str s = pstring s 
let str_ws s = str s .>> spaces
let stringLiteral : Parser<_> = manyChars (noneOf "\">")

let numList : Parser<_> = sepBy1 (pint32) (str ",")  

let parseHeader inner header = str header >>. str ":" >>. inner
let parseKvps = 
    let strHeader header =  parseHeader stringLiteral header .>> newline  
    let numListHeader header = parseHeader numList header .>> newline 
    let numHeader header = parseHeader pint32 header .>> newline 

    let rest = parse {
        let! key1 = numListHeader "KEY1"
        let! key2 = strHeader "KEY2"
        let! key3 = numHeader "KEY3"
        return key1,key2,key3
    }
    rest

let kvps = "KEY1:1,2,3\nKEY2:abc\nKEY3:123"
run parseKvps kvps

上面给出了以下错误:

val it : ParserResult<(int32 list * string * int32),unit> =
  Failure:
Error in Ln: 3 Col: 9
KEY3:123
        ^
Note: The error occurred at the end of the input stream.
Expecting: any char not in ‘">’ or newline

我认为这与numList解析器有关,因为取出第一个键可以按预期工作。

感谢任何帮助!提前谢谢!

1 个答案:

答案 0 :(得分:0)

第三个解析器失败,因为FParsec最后没有找到必需的\n

有几种方法可以解决问题:

  1. 通过向流添加\n来使您的数据有效:

    let kvps = "KEY1:1,2,3\nKEY2:abc\nKEY3:123\n"
    

    下行:修改源流仅适用于测试,而不适用于真实应用。

  2. .>> newline可选:

    .>> (optional newline)
    

    下行:当尝试解析同一源代码行中的两个密钥时,可能会导致错误。

  3. 尝试使用eof替代newline

  4. 另外,附注。您的代码似乎很难支持。想想如果密钥在源字符串中出现错误的顺序,或者需要在应用程序开发过程中添加新密钥会发生什么。

    查看thisthis个答案以了解更多详情。