A simple CSV parser in Erlang. Usually splitting a line by comma would suffice unless a value itself is a string containing commas. This considers such cases as well.

-module(csv).

-export([parse_csv/1]).

parse_csv(String) ->
    parse_csv(String, [], [], [], false).

parse_csv([], S, Acc, [], _) ->
    lists:reverse(
        lists:map(fun(X) ->
                     lists:reverse(
                         lists:flatten(X))
                  end,
                  [Acc | S]));
parse_csv([], S, [], L, _) ->
    lists:reverse(
        lists:map(fun(X) ->
                     lists:reverse(
                         lists:flatten(X))
                  end,
                  [L | S]));
parse_csv(String, S, Acc, L, IsSubStr) ->
    case String of
        [$" | T] when IsSubStr =:= true ->
            % end of substring (ending quote).
            parse_csv(T, S, Acc, [$" | L], false);
        [$" | T] when IsSubStr =:= false ->
            % beginning of a substring (beginning quote).
            parse_csv(T, S, Acc, [$"], true);
        [$, | T] when IsSubStr =:= true andalso L =/= [] ->
            % comma within a substring
            parse_csv(T, S, Acc, [$, | L], true);
        [$, | T] when IsSubStr =:= false andalso L =/= [] ->
            % comma after a substring.
            parse_csv(T, [[L | Acc] | S], [], [], false);
        [$, | T] when IsSubStr =:= false andalso L =:= [] ->
            % comma after a normal string.
            parse_csv(T, [Acc | S], [], [], false);
        [H | T] when IsSubStr =:= true ->
            % within a substring
            parse_csv(T, S, Acc, [H | L], true);
        [H | T] when IsSubStr =:= false ->
            % a normal string
            parse_csv(T, S, [H | Acc], [], false)
    end.

Example usage

1> c(csv).
{ok,csv}
2> csv:parse_csv("1,\"Abc, cdf\",3.0").
["1","\"Abc, cdf\"","3.0"]
3> csv:parse_csv("1,xyz,3.0").         
["1","xyz","3.0"]