• ? Haskell XML lexing Есть одна ебанутая спецификация, которая требует отдельные 0x0D заменять на 0x0A, а пары 0x0D 0x0A заменять на 0x0A. И пусть меня закидают ссаными тряпками, я вообще не вкуриваю как это сделать.
    Не, ясен пень, нужно сварганить простейший конечный автомат (вернее, трансдюсер), который будет разбивать поступающие на вход байтстринги на более мелкие байтстринги (ленивые, без копирования). А вот как это сделать в реале?
    Перейти на стринги, перейти на текст? Важна даже не столько вычислительная сложность. Важно чтобы реализация как можно меньше сношала сборщик мусора.
    Обойти — не вариант. Во-первых, такое поведение — MUST. Во-вторых, без реализации такого поведения к чертям полетит вся кошер^W каноничность.

Replies (9)

  • @Macil, Попробуй кондуитами. Ими же и парсить можно (xml-conduit)
  • @segfault, Про xml-conduit я в курсе и пользуюсь. Только у Сноймана код какбэ мнэ-э-э ... глубоко специфичный. Ему похуй на спецификацию XML, его парсер без проблем принимает \r и \r\n.
    И, как я уже сказал, нормализация EOL до парсинга — MUST в спецификации.
    Можно сварганить фильтр на Event'ы, но во-первых, опять встаёт вопрос «Как?»; во-вторых, всё нужно делать по-нормальному, не через жопу.
  • @Macil, Это же кондуиты, создай кондуит `Conduit ByteString m ByteString` или как там, потом склей его с кондуитом — парсером
  • @segfault, Да понятно! Весь вопрос как такое сделать!!! Работа идёт с чанками байтстрингов (для простоты будем считать что кодировка однобайтовая). По спеке "\r\n" нужно заменить на "\n". Теперь представь что у тебя \r в конце одного чанка, а \n — в начале другого. Т.е. нужно как-то таскать состояние. А еще нужно чтобы это было красиво, элегантно и без насилия над сборщиком мусора.
    Можно вклиниться в преобразование ByteString -> Text на уровне Conduit.Text, но опять хрен его знает как это сделать потому что получившийся нормализованный текст будет, сцуко, КОРОЧЕ. И опять нужно как-то тащить состояние.
  • @Macil, Не нужно ничего тащить leftover же есть (засовывает схаванное обратно). А про сборщик я бы беспокоился в последнюю очередь, и уж конечно только после бенчмарков.
  • @segfault, leftover мне не поможет, тогда мне придётся заглядывать на шаг вперед, что в данном контексте нахрен не нужно. Можно поступить как Снойман — таскать состояние внутри цикла в кондуите, например как в Data.Conduit.Text.lines... Скорее всего так и придётся сделать.
  • @Macil, go = do (xs,ys) <- span (/= chr (0x0D))
    case ys of
    "" -> xs
    '\r' : '\n' :ys -> xs <> chr (0x0A): go ys
    _ -> xs <> go ys

    это тебе на строках, чтобы перевести на LBS вместо xs пиши [xs] и потом fromChunks натрави, чтобы перевести на кондуиты просто делай yield вместо возврата xs и не забудь в случае "" попросить ещё входящих данных, так же случай с '\r' разобьётся на 2 в случае пустого и не пустого ys.
  • @qnikst, о скорости будешь потом думать, не вижу принципиальной разницы в вариантах, если только не посивольно рассматривать или не умудриться левособирать все. Ну и как я уже сказал, этот вариант протсто втупую переносится на пайпы кондуиты и т.п.
  • @qnikst, github.com вот на машинках, чуть сложнее, чем на строках, в принципе ещё можно сделать аккуратнее, когда на \n не делается отдельный чанк если он является частью следующего чанка, но мне лень, будут бенчмарки, можно поговорить будет