FParsec: как разобрать дату в fparsec (новичок) - PullRequest
3 голосов
/ 12 апреля 2011

Я использую пост Билла Казарина о том, как анализировать файлы с разделителями с помощью fparsec, я просто теряю логику, чтобы понять, как работает код.Я анализирую многострочный документ в структуре списка ячеек (на данный момент), где ячейка является строкой или плавающей точкой.Я новичок в этом деле.

У меня возникают проблемы при разборе чисел с плавающей точкой - в типичном случае (ячейка, разделенная табуляцией и содержащая число), это работает.Однако, когда ячейка оказывается строкой, которая начинается с числа - она ​​разваливается.

Как мне изменить pFloatCell, чтобы он анализировал (хотя путь через вкладку) как число с плавающей точкой или ничего?

Спасибо

type Cell = 
    | String of string 
    | Float of float
.
.
.
let pStringCell delim = 
    manyChars (nonQuotedCellChar delim)
    |>> String

// this is my issue. pfloat parses the string one 
// char at a time, and once it starts off with a number 
// it is down that path, and errors out
let pFloatCell delim = 
    FParsec.CharParsers.pfloat
    |>> Float

let pCell delim = 
    (pFloatCell delim) <|> (pStringCell delim)
.
.
.
let ParseTab s  =
  let delim = "\t"
  let res = run (csv delim) s in
    match res with
     | Success (rows, _, _) -> { IsSuccess = true; ErrorMsg = "Ok"; Result = stripEmpty rows }
     | Failure (s, _, _) -> { IsSuccess = false; ErrorMsg = s; Result = [[]] }
.
.
.
let test() =

    let parsed = ParseTab data

К сожалению, поздно для меня в последний разночь.Я хотел опубликовать данные.Этот первый работает

let data = 
    "s10 Mar 2011 18:28:11 GMT\n"

, в то время как это возвращает ошибку:

let data = 
    "10 Mar 2011 18:28:11 GMT\n"

возвращает, как с рекомендацией ChaosP, так и без нее:

ErrorMsg = "Ошибкав Ln: 1 Col: 3 \ r \ n10 мар 2011 г. 18:28:11 GMT \ r \ n ^ \ r \ nВидно: конец файла, новая строка или '\ t' \ r \ n "

Похоже, что попытка работает нормально.во втором случае он захватывает только до 10 - и код для pfloat просматривает только до первого пробела .Мне нужно сообщить pfloat, что он должен смотреть до следующей вкладки или новой строки независимо от того, есть ли перед ним пробел;написать свою собственную версию pfloat, выполнив Double.Parse, но я бы предпочел использовать библиотеку.

1 Ответ

2 голосов
/ 12 апреля 2011

Поскольку кажется, что текст, который вы будете анализировать, немного неоднозначен, вам нужно изменить свой pCell синтаксический анализатор.

let sep delim =
     skipString delim <|> skipAnyOf "\r\n" <|> eof

let pCell delim = 
    attempt (pFloatCell delim .>> sep delim) <|> (pStringCell delim .>> sep delim)

Это также означает, что вам нужно изменить тот парсер, который использует pCell.

let pCells delim =
    many pCell delim 

Примечание

Оператор .>> на самом деле довольно прост. Думайте об этом как оператор скачкообразной лягушки. Значение левой части возвращается после применения правой части и игнорирования результата.

Parser<'a, 'b> -> Parser<'c, 'b> -> Parser<'a, 'b>
...