|
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 |
|
15 local value = (escape + (1-delim))^0; |
|
16 |
|
17 local escape_map = setmetatable({ |
|
18 t = "\t", b = "\b", f = "\f"; |
|
19 n = "\n", r = "\r", v = "\v"; }, |
|
20 { __index = function (_, n) |
|
21 if tonumber(n) then |
|
22 print"n" |
|
23 return s_char(tonumber(n)); |
|
24 else |
|
25 return n; |
|
26 end |
|
27 end |
|
28 }); |
|
29 |
|
30 function read_record(line, value_callback) |
|
31 local fieldpos = 0; |
|
32 local callback = function (v) |
|
33 return value_callback(v:gsub("\\(.)", escape_map)); |
|
34 end; |
|
35 repeat |
|
36 fieldpos = lpeg.match(value / callback, line, fieldpos+1); |
|
37 until fieldpos >= #line; |
|
38 end |
|
39 |
|
40 return _M; |