Адъ CSV

Nov. 9th, 2009 08:28 pm
metaclass: (Default)
[personal profile] metaclass
А напишите кто-нибудь табличку состояний CSV парсера? Т.е. последовательность символов, разделенных запятыми, в строках, разделенных \r или \r\n разбить на список списков строк. Если в строке должны быть служебные символы (т.е. запятая или \r \n) - строка обрамляется в кавычки, если внутри такой строки нужна кавычка - ставится две кавычки подряд.
На самом деле там немного сложнее, типа допустимо незначимые пробелы возле запятых, а значимыми их делают тоже через кавычки, управляющие символы <32 вроде тоже обязательно в кавычки, но это пофиг.
Вроде блин простая задачка, а каждый раз когда ее приходится делать - получаются на пару страниц конечные автоматы.

Date: 2009-11-09 09:58 pm (UTC)
From: [identity profile] lionet.livejournal.com
Как-то так (парсинг "строки" CSV в точном соответствии с RFC4180):

extract_line(Data) -> extract_line(Data, []).
extract_line(Data, Accum) ->
        case extract_value(Data) of
                {Value, Rest} -> extract_line(Rest, [r(Value)|Accum]);
                {Rest} -> {r(Accum), Rest};
                novalue when Accum =/= [] -> {r(Accum), []};
                novalue -> noline
        end.

extract_value([]) -> novalue;
extract_value([$\r,$\n|Rest]) -> {Rest};
extract_value([$\n|Rest]) -> {Rest};
extract_value([$"|Rest]) -> extract_quoted(Rest, []);
extract_value(Rest) -> extract_nonquoted(Rest, []).

extract_nonquoted([$\n|_]=Rest, V) -> {V, Rest};
extract_nonquoted([$\r,$\n|_]=Rest, V) -> {V, Rest};
extract_nonquoted([$,|Rest], V) -> {V, Rest};
extract_nonquoted([C|Rest], V) -> extract_nonquoted(Rest, [C|V]);
extract_nonquoted([], V) -> {V, []}.

extract_quoted([$",$,|Rest], V) -> {V, Rest};
extract_quoted([$",$\r,$\n|Rest], V) -> {V, [$\n|Rest]};
extract_quoted([$",$\n|Rest], V) -> {V, [$\n|Rest]};
extract_quoted([$",$"|Rest], V) -> extract_quoted(Rest, [$"|V]);
extract_quoted([$"], V) -> {V, []};
extract_quoted([$\r,$\n|Rest], V) -> extract_quoted(Rest, [$\n|V]);
extract_quoted([C|Rest], V) -> extract_quoted(Rest, [C|V]);
extract_quoted([], V) -> {V, []}.

Date: 2009-11-09 10:02 pm (UTC)
From: [identity profile] lionet.livejournal.com
incidentally, это табличка состояний. По вертикали идут состояния, по горизонтали — входные символы, меняющие состояния. После стрелки, соответственно, связанные действия.

Date: 2009-11-09 10:05 pm (UTC)
From: [identity profile] metaclass.livejournal.com
Да, паттерн-матчинг спасает очень сильно. У меня была мысль его имитировать, но я забил :)

Date: 2009-11-09 10:10 pm (UTC)
From: [identity profile] lionet.livejournal.com
Да ладно, на GNU C почти то же самое можно забубенить, если игнорировать \r\n/\n проблему :)

enum {
    ST_NOCHANGE,  /* Pseudo-state */
    ST_PLAIN,
    ST_QUOTED_VALUE,
    _ST_MAX
} stateTable[_ST_MAX][256] = {
    [ST_PLAIN] = {
        [ '"' ] = ST_QUOTED_VALUE,
        ...
    },
    [ST_QUOTED_VALUE] = { ... }
};

Profile

metaclass: (Default)
metaclass

April 2017

S M T W T F S
      1
2345678
9101112 131415
16171819202122
23242526272829
30      

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jul. 1st, 2025 11:44 am
Powered by Dreamwidth Studios