attoparsec-enumerator, забавное
Три парсера :
и их использование:
Второй и третий работают. Первый глючит - пропускает куски потока. Потому как после разбора не сохраняет остаток буфера, прочитанного енумератором и не отдает его при продолжении, а начинает разбор уже со свежепрочитанного буфера.
А нужен именно первый, для того, чтобы посылать по одной команды на девайс и читать и парсить ответы. Т.е. один цикл работы связки enumerator $$ iteratee на каждый ответ от девайса.
Либо использовать не enumerator, а более сложную реализацию - пакет iteratee, который умеет из Iteratee посылать команды обратно в Enumerator, используя исключения и их перехват.
Либо забить и сделать в лоб, т.к. тут на самом деле Iteratees нужны только для сушения мозга и удобства комбинирования парсеров и прочих фильтров потоков.
--построчный парсер iterParseLine :: Monad m => E.Iteratee BS.ByteString m BS.ByteString iterParseLine = iterParser parseLine --парсер всех строк сразу iterParseLines :: Monad m => E.Iteratee BS.ByteString m [BS.ByteString] iterParseLines = iterParser $ many parseLine --парсер из Enumeratee enumParseLines :: Monad m => E.Enumeratee BS.ByteString BS.ByteString m b enumParseLines = E.sequence $ iterParser $ parseLine
и их использование:
parseHandleByLine :: IO.Handle -> IO () parseHandleByLine h = loop where loop = do s<-E.run_ $ enumHandle1 h E.$$ iterParseLine BS.putStrLn s loop testIterParseLines :: IO.Handle -> IO () testIterParseLines = do answers <- E.run_ $ enumHandle1 h E.$$ iterParseLines mapM BS.putStrLn answers testEnumParseLines :: IO.Handle -> IO () testEnumParseLines h = E.run_ $ enumHandle1 h E.$= enumParseLines E.$$ printLnI
Второй и третий работают. Первый глючит - пропускает куски потока. Потому как после разбора не сохраняет остаток буфера, прочитанного енумератором и не отдает его при продолжении, а начинает разбор уже со свежепрочитанного буфера.
А нужен именно первый, для того, чтобы посылать по одной команды на девайс и читать и парсить ответы. Т.е. один цикл работы связки enumerator $$ iteratee на каждый ответ от девайса.
Либо использовать не enumerator, а более сложную реализацию - пакет iteratee, который умеет из Iteratee посылать команды обратно в Enumerator, используя исключения и их перехват.
Либо забить и сделать в лоб, т.к. тут на самом деле Iteratees нужны только для сушения мозга и удобства комбинирования парсеров и прочих фильтров потоков.
no subject
no subject
no subject
no subject
кстати, примерно понятно, как за'loop'ить всё это мероприятие, или ещё надо думать?
no subject
Впрочем, наверно и iteratee может завершить работу, по идее.
no subject
no subject
То есть, в зависимости от условий, нужно будет выбирать либо loop в конце, либо что-то другое. return () какой-нибудь вполне ок.