0

値のデータ型によって異なるキーと値のペアを解析できるパーサーを作成しようとしています。

キー1: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 が最後に必要なものを見つけられなかったため、3 番目のパーサーは失敗します\n

問題を解決するには、いくつかのオプションがあります。

  1. \nストリームに追加して、データを有効にします。

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

    欠点: ソース ストリームの変更はテストにのみ有効であり、実際のアプリには有効ではありません。

  2. オプション.>> newlineにする:

    .>> (optional newline)
    

    欠点: 同じソース行にある 2 つのキーを解析しようとすると、エラーが発生する可能性があります。

  3. eof可能な代替手段として使用してみてくださいnewline


あと、余談。あなたのコードはサポートが非常に難しいようです。ソース文字列でキーが間違った順序で発生した場合、またはアプリ開発の過程で新しいキーを追加する必要がある場合はどうなるか考えてみてください。

詳細については、これこの回答を確認してください。

于 2015-08-27T03:33:34.517 に答える