Фрагментированный синтаксический анализ с помощью FParsec


Можно ли передавать входные данные парсеру FParsec кусками, как из сокета? Если нет, то можно ли получить текущий результат и непереработанную часть входного потока, чтобы я мог выполнить это? Я пытаюсь запустить куски входных данных, поступающих из SocketAsyncEventArgs, без буферизации целых сообщений.

Обновить

Причиной для упоминания использования SocketAsyncEventArgs было указание на то, что отправка данных в CharStream может привести к асинхронному доступу к базовому Stream. В частности, я рассматриваю использование кругового буфера для выталкивания данных, поступающих из сокета. Я помню, что в документации FParsec отмечалось, что к базовому Stream не следует обращаться асинхронно, поэтому я планировал вручную управлять фрагментированным синтаксическим анализом.

Окончательные вопросы:

  1. могу ли я использовать круговой буфер под моим Stream, переданным в CharStream?
  2. не нужно ли мне побеспокоиться о ручном управлении фрагментами в этом сценарии?
1 5

1 ответ:

Обычная версия FParsec (хотя и не версия с низким уровнем доверия) считывает входные данные по частям или "по блокам", как я называю ее в CharStream документация . Таким образом, если вы создаете CharStream из System.IO.Stream и содержимое достаточно велико, чтобы охватить несколько блоков CharStream, вы можете начать синтаксический анализ до того, как полностью восстановите входные данные.

Обратите внимание, однако, что CharStream будет потреблять входной поток в кусках фиксированного (но настраиваемого) размера, т. е. Read Метод System.IO.Stream так часто, как это необходимо для заполнения полного блока. Следовательно, если вы анализируете входные данные быстрее, чем вы можете получить новые входные данные, CharStream может блокировать, даже если уже есть какой-то непереработанный вход, потому что еще недостаточно входных данных, чтобы заполнить полный блок.

Обновить

Ответ(ы) на ваши конечные вопросы: 42.

  • Как вы реализуете Stream, из которого вы строите CharStream, полностью зависит от вас. То ограничение, которое вы помните, исключает параллельный доступ, применяется только к классу CharStream, который не является потокобезопасным.

  • Реализация Stream в виде кругового буфера, скорее всего, ограничит максимальное расстояние, на которое вы можете вернуться.

  • Размер блока CharStream влияет на то, как далеко вы можете вернуться, когда Stream не поддерживает поиск.

  • Самый простой способ проанализировать входные данные асинхронно - это выполнить синтаксический анализ в асинхронная задача (т. е. в фоновом потоке). В задаче вы можете просто читать сокет синхронно, или, если вы не доверяете буферизации ОС, вы можете использовать класс stream, как BlockingStream, описанный в статье, которую вы связали во втором комментарии ниже.

  • Если входные данные можно легко разделить на независимые фрагменты (например, строки для текстового формата на основе строк), было бы более эффективно разделить их самостоятельно, а затем проанализировать входной фрагмент с помощью кусок.