我必須寫一個解析器解析鍵值對的,看起來像這樣的文件:fparsec鍵值解析器無法解析
as235 242kj25klj Pairs:A=a1|B=b1|C=c1
kjlkjlkjlkj Pairs:A=a2|B=b2|C=c2
注意,行包含一些垃圾,標籤,然後鍵值對。
,我寫的F#代碼如下:
#r"FParsec.dll"
open FParsec
let parse keys label =
let pkey = keys |> Seq.map pstring |> choice
let pvalue = manyCharsTill anyChar (anyOf "|\n")
let ppair = pkey .>> (skipChar '=') .>>. pvalue
let ppairSeq = many ppair
let pline = skipManyTill anyChar (pstring label)
>>. ppairSeq .>> newline
let pfile = many (opt pline) |>> Seq.choose id
run pfile
>> function
| Success (result, _, _) -> result
| Failure (errorMsg, _, _) -> failwith errorMsg
"""
as235 242kj25klj Pairs:A=a1|B=b1|C=c1
lkjlkjlkjlkj Pairs:A=a2|B=b2|C=c2
"""
|> parse ["A";"B";"C"] "Pairs:"
|> List.ofSeq
|> printfn "%A"
預期的結果是:
[[("A","a1"); "B","b1"; "C","c1"]
[("A","a2"); "B","b2"; "C","c2"]]
...而是我得到以下錯誤:
System.Exception: Error: Error in Ln: 8 Col: 1
Note: The error occurred at the end of the input stream.
Expecting: any char or 'Pairs:'
關於如何修復此解析器的任何想法?
謝謝!
更新:史蒂芬的評論後,我試圖修復它,但沒有成功。這是我期望能夠工作的最後一次嘗試,但事實並非如此。
let pkey = keys |> Seq.map pstring |> choice
let pvalue = manyCharsTill anyChar (anyOf "|\n")
let ppair = pkey .>> (skipChar '=') .>>. pvalue
let ppairSeq = manyTill ppair newline
let pnonEmptyLine =
skipManyTill anyChar (pstring label)
>>. ppairSeq
|>> Some
let pemptyLine = spaces >>. newline >>% None
let pline = pemptyLine <|> pnonEmptyLine
let pfile = manyTill pline eof |>> Seq.choose id
現在的錯誤信息是:
Error in Ln: 2 Col: 5
as235 242kj25klj Pairs:A=a1|B=b1|C=c1
^
Expecting: newline
的'pline'解析器似乎消耗輸入後失敗,因爲'anyChar'也消耗換行,這可能不是你通緝。請注意,「許多(opt pline)'最終會導致異常,因爲'opt x'可以在不消耗輸入的情況下成功。要解決這個問題,你可以跳過空行作爲(尾隨)空白,或者你的空行解析器需要實際消耗一個換行符。 –
我想我理解你的意思,但我不知道如何修復解析器。我發佈了我的嘗試作爲更新 – vidi