Фрагментированный синтаксический анализ с помощью FParsec
Можно ли передавать входные данные парсеру FParsec кусками, как из сокета? Если нет, то можно ли получить текущий результат и непереработанную часть входного потока, чтобы я мог выполнить это? Я пытаюсь запустить куски входных данных, поступающих из SocketAsyncEventArgs
, без буферизации целых сообщений.
Обновить
Причиной для упоминания использования SocketAsyncEventArgs
было указание на то, что отправка данных в CharStream
может привести к асинхронному доступу к базовому Stream
. В частности, я рассматриваю использование кругового буфера для выталкивания данных, поступающих из сокета. Я помню, что в документации FParsec отмечалось, что к базовому Stream
не следует обращаться асинхронно, поэтому я планировал вручную управлять фрагментированным синтаксическим анализом.
Окончательные вопросы:
- могу ли я использовать круговой буфер под моим
Stream
, переданным вCharStream
? - не нужно ли мне побеспокоиться о ручном управлении фрагментами в этом сценарии?
1 ответ:
Обычная версия FParsec (хотя и не версия с низким уровнем доверия) считывает входные данные по частям или "по блокам", как я называю ее в
CharStream
документация . Таким образом, если вы создаетеCharStream
изSystem.IO.Stream
и содержимое достаточно велико, чтобы охватить несколько блоковCharStream
, вы можете начать синтаксический анализ до того, как полностью восстановите входные данные.Обратите внимание, однако, что
CharStream
будет потреблять входной поток в кусках фиксированного (но настраиваемого) размера, т. е.Read
МетодSystem.IO.Stream
так часто, как это необходимо для заполнения полного блока. Следовательно, если вы анализируете входные данные быстрее, чем вы можете получить новые входные данные,CharStream
может блокировать, даже если уже есть какой-то непереработанный вход, потому что еще недостаточно входных данных, чтобы заполнить полный блок.Обновить
Ответ(ы) на ваши конечные вопросы:
42.
Как вы реализуете
Stream
, из которого вы строитеCharStream
, полностью зависит от вас. То ограничение, которое вы помните, исключает параллельный доступ, применяется только к классуCharStream
, который не является потокобезопасным.Реализация
Stream
в виде кругового буфера, скорее всего, ограничит максимальное расстояние, на которое вы можете вернуться.Размер блока
CharStream
влияет на то, как далеко вы можете вернуться, когдаStream
не поддерживает поиск.Самый простой способ проанализировать входные данные асинхронно - это выполнить синтаксический анализ в асинхронная задача (т. е. в фоновом потоке). В задаче вы можете просто читать сокет синхронно, или, если вы не доверяете буферизации ОС, вы можете использовать класс stream, как
BlockingStream
, описанный в статье, которую вы связали во втором комментарии ниже.Если входные данные можно легко разделить на независимые фрагменты (например, строки для текстового формата на основе строк), было бы более эффективно разделить их самостоятельно, а затем проанализировать входной фрагмент с помощью кусок.