я должен написать синтаксический анализатор, который анализирует пары ключ-значение в файл, который выглядит следующим образом:fparsec ключ-значение синтаксический анализатор не может разобрать
as235 242kj25klj Pairs:A=a1|B=b1|C=c1
kjlkjlkjlkj Pairs:A=a2|B=b2|C=c2
Обратите внимание, что строки содержат некоторое количество мусора, этикетку, а затем пары ключ-значение.
The 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:'
Любые идеи о том, как я могу исправить этот парсер?
Спасибо!
UPDATE: после комментария Stephan я попытался исправить это, но безуспешно. Это одна из моих последних попыток, которую я ожидал, но это не так.
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' также потребляет переводы строк, которые, вероятно, не то, что вы разыскивается. Обратите внимание, что 'many (opt pline)' в конечном итоге приведет к исключению, так как 'opt x' может преуспеть, не потребляя входные данные. Чтобы исправить это, вы можете пропустить пустые строки как (конечные) пробелы, или ваш пустой анализатор строк должен фактически использовать новую строку. –
Думаю, я понимаю, что вы имеете в виду, но я не знаю, как исправить парсер. Я отправил свою попытку как обновление – vidi