Skip to content

Instantly share code, notes, and snippets.

@johansolve
Created November 6, 2013 07:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save johansolve/7332277 to your computer and use it in GitHub Desktop.
Save johansolve/7332277 to your computer and use it in GitHub Desktop.
CSV parser for Lasso
[ // Lasso 8
define_tag('parse_csv', -required='input'
, -optional='linebreak', -type='string', -copy
, -optional='fielddelimiter', -type='string', -copy
, -optional='fieldseparator', -type='string', -copy
, -optional='escapecharacter', -type='string', -copy
, -optional='optionaldelimiters', -copy
, -optional='firstrowfieldnames', -copy
, -optional='rowformat', -type='string', -copy
);
local( 'state'='out'
, 'output'=array
, 'row'=array
, 'field'=string
, 'char'=string
, 'escaped'=false
, 'unquoted'=false
, 'fieldnames'=array
);
!local_defined('linebreak') ? local('linebreak'='\n');
!local_defined('fielddelimiter') ? local('fielddelimiter'='"');
!local_defined('fieldseparator') ? local('fieldseparator'=',');
!local_defined('escapecharacter') ? local('escapecharacter'='\\');
!local_defined('rowformat') ? local('rowformat'='array');
local('optionaldelimiters'=(local_defined('optionaldelimiters') && #optionaldelimiters != false));
local('firstrowfieldnames'=(local_defined('firstrowfieldnames') && #firstrowfieldnames != false));
iterate(#input -> split(''), #char);
select(#state);
case('out');
if(#char==#fielddelimiter);
#state='in';
else(#char==#fieldseparator);
if(#firstrowfieldnames && #rowformat=='map' && #fieldnames -> size);
if(#fieldnames -> size >= #row -> size + 1);
#row -> insert(#fieldnames -> get(#row -> size + 1) = #field);
/if;
else;
#row -> insert(#field);
/if;
#field=string;
else(#char==#linebreak);
if(#firstrowfieldnames && #rowformat=='map' && #fieldnames -> size);
if(#fieldnames -> size >= #row -> size + 1);
#row -> insert(#fieldnames -> get(#row -> size + 1) = #field);
/if;
else;
#row -> insert(#field);
/if;
#output -> insert(#row);
#field=string;
#rowformat == 'map' ? #row = map | #row = array;
else(#optionaldelimiters);
#state='in';
#unquoted=true;
#field += #char;
/if;
case('in');
if(!#escaped && #char == #escapecharacter);
#escaped=true;
else(#char==#fielddelimiter && !#escaped && !#unquoted);
#state='out';
else(#char==#fieldseparator && #optionaldelimiters && #unquoted && !#escaped);
#state='out';
#unquoted=false;
if(#firstrowfieldnames && #rowformat=='map' && #fieldnames -> size);
if(#fieldnames -> size >= #row -> size + 1);
#row -> insert(#fieldnames -> get(#row -> size + 1) = #field);
/if;
else;
#row -> insert(#field);
/if;
#field=string;
else(#char==#linebreak && #optionaldelimiters && #unquoted && !#escaped);
#state='out';
#unquoted=false;
if(#firstrowfieldnames && #rowformat=='map' && #fieldnames -> size);
if(#fieldnames -> size >= #row -> size + 1);
#row -> insert(#fieldnames -> get(#row -> size + 1) = #field);
/if;
else;
#row -> insert(#field);
/if;
#output -> insert(#row);
#field=string;
#rowformat == 'map' ? #row = map | #row = array;
#field=string;
else;
#field += #char;
#escaped=false;
/if;
/select;
if(#firstrowfieldnames && #output -> size == 1 && #fieldnames -> size == 0);
#fieldnames = #output -> get(1);
#output -> remove(1);
else(!#firstrowfieldnames);
#rowformat='array';
/if;
/iterate;
if(#field -> size);
if(#firstrowfieldnames && #rowformat=='map' && #fieldnames -> size);
if(#fieldnames -> size >= #row -> size + 1);
#row -> insert(#fieldnames -> get(#row -> size + 1) = #field);
/if;
else;
#row -> insert(#field);
/if;
/if;
#row -> size ? #output -> insert(#row);
return(#output);
/define_tag;
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment