-
Notifications
You must be signed in to change notification settings - Fork 0
/
Library.fs
46 lines (35 loc) · 1.73 KB
/
Library.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
namespace Vertigo.CsvParse
module CSVParse =
open FParsec.Primitives
open FParsec.CharParsers
type CsvResult = { IsSuccess : bool; ErrorMsg : string; Result : seq<string list> }
let isWs = Seq.map (isAnyOf "\t ") >> Seq.reduce (&&)
let ws = spaces
let chr c = skipChar c
let st str = if isWs str then skipString str else skipString str .>> ws
let ch c = chr c .>> ws
let escapeChar = chr '\\' >>. anyOf "\"\\/bfnrt,"
|>> function
| 'b' -> '\b'
| 'f' -> '\u000C'
| 'n' -> '\n'
| 'r' -> '\r'
| 't' -> '\t'
| c -> c
let nonQuotedCellChar delim = escapeChar <|> (noneOf (delim + "\r\n"))
let cellChar = escapeChar <|> (noneOf "\"")
let cell delim = between (chr '\"') (chr '\"') (manyChars cellChar) <|> manyChars (nonQuotedCellChar delim)
let row delim = sepBy (cell delim) (st delim)
let csv delim = sepBy (row delim) newline .>> eof
let commaCsv = csv ","
let stripEmpty ls = Seq.filter (fun (row:'a list) -> row.Length <> 0) ls
let ParseCsv s delim =
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 = [[]] |> Seq.ofList}
let ParseCsvStream path delim =
let res = runParserOnFile (csv delim) () path (System.Text.Encoding.UTF8)
match res with
| Success (rows, _, _) -> { IsSuccess = true; ErrorMsg = "Ok"; Result = stripEmpty rows}
| Failure (s, _, _) -> { IsSuccess = false; ErrorMsg = s; Result = [[]] |> Seq.ofList}