csv.lua: move error handling up, again, trying to make the parser a bit shorter. Not really working, but giving it a go all the same

This commit is contained in:
Geoff Leyland 2014-05-27 09:48:01 +12:00
parent fd9d21cb9c
commit 70c5dd6f9b

View File

@ -38,7 +38,7 @@ column_map.__index = column_map
--- Parse a list of columns. --- Parse a list of columns.
-- The main job here is normalising column names and dealing with columns -- The main job here is normalising column names and dealing with columns
-- for which we have more than one possible name in the header. -- for which we have more than one possible name in the header.
function column_map:new(columns, filename) function column_map:new(columns)
local name_map = {} local name_map = {}
for n, v in pairs(columns) do for n, v in pairs(columns) do
local names local names
@ -69,7 +69,7 @@ function column_map:new(columns, filename)
end end
end end
return setmetatable({ name_map = name_map, filename = filename }, column_map) return setmetatable({ name_map = name_map }, column_map)
end end
@ -126,16 +126,14 @@ function column_map:read_header(header)
end end
function column_map:transform(value, index, line, column) function column_map:transform(value, index)
local field = self.index_map[index] local field = self.index_map[index]
if field then if field then
if field.transform then if field.transform then
local ok local ok
ok, value = pcall(field.transform, value) ok, value = pcall(field.transform, value)
if not ok then if not ok then
error(("%s:%d:%d: Couldn't read field '%s': %s"): error(("Error reading field '%s': %s"):format(field.name, value), 0)
format(self.filename or "<unknown>", line, column,
field.name, value))
end end
end end
return value or field.default, field.name return value or field.default, field.name
@ -277,12 +275,21 @@ local function separated_values_iterator(buffer, parameters)
local line = 1 local line = 1
local field_count, fields, starts = 0, {}, {} local field_count, fields, starts = 0, {}, {}
local header, header_read local header, header_read
local field_start_line, field_start_column
local function problem(message)
error(("%s:%d:%d: %s"):
format(parameters.filename, field_start_line, field_start_column,
message), 0)
end
while true do while true do
local field_start_line = line
local field_start_column = field_start - line_start + 1
local field_end, sep_end, this_sep local field_end, sep_end, this_sep
local tidy local tidy
field_start_line = line
field_start_column = field_start - line_start + 1
-- If the field is quoted, go find the other quote -- If the field is quoted, go find the other quote
if field_sub(1, 1) == '"' then if field_sub(1, 1) == '"' then
@ -292,16 +299,10 @@ local function separated_values_iterator(buffer, parameters)
local a, b, c = field_find('"("?)', current_pos + 1) local a, b, c = field_find('"("?)', current_pos + 1)
current_pos = b current_pos = b
until c ~= '"' until c ~= '"'
if not current_pos then if not current_pos then problem("unmatched quote") end
error(("%s:%d:%d: unmatched quote"):
format(parameters.filename, field_start_line, field_start_column))
end
tidy = fix_quotes tidy = fix_quotes
field_end, sep_end, this_sep = field_find(" *([^ ])", current_pos+1) field_end, sep_end, this_sep = field_find(" *([^ ])", current_pos+1)
if this_sep and not this_sep:match(sep) then if this_sep and not this_sep:match(sep) then problem("unmatched quote") end
error(("%s:%d:%d: unmatched quote"):
format(parameters.filename, field_start_line, field_start_column))
end
else else
field_end, sep_end, this_sep = field_find(sep, 1) field_end, sep_end, this_sep = field_find(sep, 1)
tidy = trim_space tidy = trim_space
@ -325,8 +326,11 @@ local function separated_values_iterator(buffer, parameters)
-- Insert the value into the table for this "line" -- Insert the value into the table for this "line"
local key local key
if parameters.column_map and header_read then if parameters.column_map and header_read then
value, key = parameters.column_map:transform(value, field_count, parameters.column_map:transform(value, field_count)
field_start_line, field_start_column) local ok
ok, value, key = pcall(parameters.column_map.transform,
parameters.column_map, value, field_count)
if not ok then problem(value) end
elseif header then elseif header then
key = header[field_count] key = header[field_count]
else else
@ -393,7 +397,7 @@ buffer_mt.__index = buffer_mt
local function use(buffer, parameters) local function use(buffer, parameters)
parameters.filename = parameters.filename or "<unknown>" parameters.filename = parameters.filename or "<unknown>"
parameters.column_map = parameters.columns and parameters.column_map = parameters.columns and
column_map:new(parameters.columns, parameters.filename) column_map:new(parameters.columns)
local f = { buffer = buffer, parameters = parameters } local f = { buffer = buffer, parameters = parameters }
return setmetatable(f, buffer_mt) return setmetatable(f, buffer_mt)
end end