Fri, 27 Mar 2015 12:02:09 +0000
Add license (MIT)
0 | 1 | |
2 | local lpeg = require "lpeg" | |
3 | local setmetatable, tonumber = | |
4 | setmetatable, tonumber; | |
5 | local s_char = string.char; | |
6 | ||
7 | module("csv"); | |
8 | ||
9 | local delim = lpeg.P","; | |
10 | ||
11 | local char_escape = lpeg.R"az" + lpeg.S"\\\r\n" + delim; | |
12 | local numeric_escape = (lpeg.R"09"^1)^-3; | |
13 | local escape = (lpeg.P"\\" * (char_escape + numeric_escape)); | |
14 | ||
3
5b24d66365ec
Fix handling of quoted CSV fields, allowing this year's CSV to be properly parsed
Matthew Wild <mwild1@gmail.com>
parents:
0
diff
changeset
|
15 | local quoted_value = lpeg.P"\"" * ((1-lpeg.P"\"")^0) * lpeg.P"\""; |
5b24d66365ec
Fix handling of quoted CSV fields, allowing this year's CSV to be properly parsed
Matthew Wild <mwild1@gmail.com>
parents:
0
diff
changeset
|
16 | local value = quoted_value + (escape + (1-delim))^0; |
0 | 17 | |
18 | local escape_map = setmetatable({ | |
19 | t = "\t", b = "\b", f = "\f"; | |
20 | n = "\n", r = "\r", v = "\v"; }, | |
21 | { __index = function (_, n) | |
22 | if tonumber(n) then | |
23 | print"n" | |
24 | return s_char(tonumber(n)); | |
25 | else | |
26 | return n; | |
27 | end | |
28 | end | |
29 | }); | |
30 | ||
31 | function read_record(line, value_callback) | |
32 | local fieldpos = 0; | |
33 | local callback = function (v) | |
34 | return value_callback(v:gsub("\\(.)", escape_map)); | |
35 | end; | |
36 | repeat | |
37 | fieldpos = lpeg.match(value / callback, line, fieldpos+1); | |
38 | until fieldpos >= #line; | |
39 | end | |
40 | ||
41 | return _M; |