Разбор по частям с FParsec - PullRequest
5 голосов
/ 17 января 2012

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

Обновление

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

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

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

1 Ответ

8 голосов
/ 17 января 2012

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

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

Обновление

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

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

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

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

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

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

...