0

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

KEY1:1,2,3

KEY2:abc

键3: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解析器有关,因为取出第一个密钥按预期工作。

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

4

1 回答 1

0

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

有几个选项可以解决这个问题:

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

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

    缺点:修改源流只对测试有用,对真正的应用程序无效。

  2. 设为.>> newline可选:

    .>> (optional newline)
    

    缺点:尝试解析同一源代码行的两个键时可能会导致错误。

  3. 尝试使用eof作为可能的替代方案newline


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

检查答案以获取更多详细信息。

于 2015-08-27T03:33:34.517 回答