Фрагментированный синтаксический анализ с помощью 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, описанный в статье, которую вы связали во втором комментарии ниже.Если входные данные можно легко разделить на независимые фрагменты (например, строки для текстового формата на основе строк), было бы более эффективно разделить их самостоятельно, а затем проанализировать входной фрагмент с помощью кусок.