LINUX.ORG.RU

Парсинг с продолжениями

 


1

2

Вот есть ли такие библиотеки генераторов парсеров где возможно такое. Вот идёт парсер, которому скормили правило, по строке. Если он находит на строке подстроку которая отвечает правилу полностью то тут поведение ничем не отличается от уже реализованных генераторов парсеров типа всевозможных regexp-либ или esrap. Интересно если строка закончилась и тогда парсер должен вернуть состояние. Это состояние можно скормить парсеру вместо правила (состояние скорее всего будет содержать правило иначе как-то мало смысла кормить остальное состояние с каким-то другим правилом) и отправить парсить какую-то новую строку. Причём в таком случае если парсер не упрётся опять с подобным результатом в конец строки, то результат работы парсера был бы такой же как если бы парсера изначально бы отправили по одной строке, которая была бы соединением первой и новой строк.

★★★★★

Последнее исправление: ados (всего исправлений: 1)

Не совсем то, что ты ищешь, ибо это решение позволяет составить парсер в коде с помощью декларативной записи аля ebnf. Но вроде бы умел так boost::spirit. По крайней мере я видел mpi систему на нём которая кушала сообщения из tcp сокета, а вот был ли там splitter или нет - хоть убей не помню.

Другое дело, что, обычно для этого таки используют сущность splitter, что бы разбить поток на сообщения, а потом кормить сообщения парсеру.

pon4ik ★★★★★
()
Последнее исправление: pon4ik (всего исправлений: 1)

Строки скармливаешь хитрому потоку, поток - парсеру. Для потока реализуешь логику хитрой аппликации строк как тебе хочется.

anonymous
()
Ответ на: комментарий от anonymous

Хитрый поток проще всего сделать на корутинах и прочих yield. Но, это слегка некрасиво, да и не особо эффективно, плюс из пушки по воробьям.

pon4ik ★★★★★
()

man sed

man awk

anonymous
()

В Яре такой был. Стек такой:

1. Путём форка интерпретатора sb-eval из sbcl был сделан интерпретатор CL, способный прерваться и вернуть состояние.

2. Многоверсионные данные. Смысл тот же, что и в СУБД с многоверсионностью (Oracle/Postgres), но хранимые объекты имитируют консы, структуры и массивы.

3. В сумме (1) и (2) дают основу.

4. «Полностью кешированный поток» - это погружение потока (stream) в функциональную парадигму. Такой поток можно клонировать в любой точке и это будет как бы закладка, к которой можно вернуться и начать заново. И он нормально сочетается с интерпретатором из первой части.

5. На основе этого написана библиотека создания парсеров методом рекурсивного спуска с дополнительными операциями «установить закладку» и «вернуться к закладке». Точно уже не помню.

Всё это использовалось некоторое время для IDE и для собственно транспилятора. Но было оно очень медленным и оказалось в итоге непригодным для этой задачи.

den73 ★★★★★
()
Последнее исправление: den73 (всего исправлений: 1)

Все эти «синхрофазатроны» аля генераторы генераторов парсеров парсеров - одно разочарование :-) Рецепт: берёшь Си и пишешь парсер вручную :-)

anonymous
()

Не очень понятно описано, но выглядит так как будто вам нужен генератор pull-mode парсера. Если целевой язык С, то lemon ( https://www.hwaci.com/sw/lemon/lemon.html ) так умеет. Даете ему на вход по одному токены, он парсит и в семантических действиях изменяете состояние.

Или может быть вам нужно ввести в грамматику токен «перенос строки» и переписать логику с явным указанием окончания строки

Deleted
()

Для этого есть монады и стрелки - слова, которые так не любят некоторые камрады. Сами же конструкции создают вычисления в рамках некоторого контекста. То есть, контекстом здесь будет собственно сам процесс парсинга, а значением внутри вычисления - нужное нам состояние. Все откаты происходят автоматически. Кое-где можно и закешировать результаты работы парсера для ускорения процесса.

Про одну из библиотек на haskell был пост выше.

dave ★★★★★
()

Да, это возможно в Red, parse может выполнять произвольный код в процессе парсинга и этот код может менять сами правила парсинга.

Только это не как парсер генератор а просто парсер.

loz ★★★★★
()
Последнее исправление: loz (всего исправлений: 2)
Ответ на: комментарий от pon4ik

Давай пиши эффективный парсер с потоком (с семантикой). Только смотри, если грамматика не сложнее регулярок, твой парсер с потоком был конечным автоматом.

anonymous
()

Это неявно делает любой токенайзер (например, flex). Как правило, они поступают значительно проще: в качестве состояния тебя просят предоставить им часть строки, которая подавалась на вход.

Не могу не пропиарить замечательный ragel: http://www.colm.net/open-source/ragel/. В мануале тебя будет интересовать глава 6.3 Scanners.

kawaii_neko ★★★★
()
Ответ на: комментарий от pon4ik

У эффективного разработчика на эффективный диалог ресурсов не жалко, эффективное использование ресурсов.

anonymous
()

насколько помню «элементарная» связка bison+flex позволяет восстановить состояние при ошибке разбора и например начать скармливать ввод в другую грамматику. Про bison могу ошибаться, но flex точно можно откатывать при неверной лексеме.

всякие пых-пых подобные примерно так и делаются..вот тут одно, а вот тут оно не катит (повезёт если есть переключатель) и надо разбирать подругому.

да, надо делать буферизацию ввода на возможную глубину ошибки и прочие прелести, но всё возможно

MKuznetsov ★★★★★
()
Последнее исправление: MKuznetsov (всего исправлений: 1)
Ответ на: комментарий от pon4ik

можно простой пример,для арифметических,выражений в скобках,например?

как догадываешься, специально для ответа на ЛОР, довольно объёмный код писать не буду :-)

посмотри маны - обрати внимание что на каждом токене int YYSTATE - текущее состояние лексера, состояния можно менять yy_push_state yy_pop_state, затолкать обратно символ в поток yyunput, а сам поток FILE * и его тоже можно менять.

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

MKuznetsov ★★★★★
()
Ответ на: комментарий от MKuznetsov

Но, ты же говоришь про восстановление после ошибки нет? А ТС, как я понял, ищет возможность «докармливать» парсер, если сообщение пришло не целиком.

как догадываешься, специально для ответа на ЛОР, довольно объёмный код писать не буду

Я думал может в доке чего есть.

pon4ik ★★★★★
()
Последнее исправление: pon4ik (всего исправлений: 1)
Ответ на: комментарий от pon4ik

А ТС, как я понял, ищет возможность «докармливать» парсер, если сообщение пришло не целиком.

Вроде того. Главное это объект состояния. Вот если у нас правило парсинга в виде regexp'а «file» после парсинга строки «fil» должен вернуться объект состояния. После парсинга строки «e some text» с сообщением того объекта состояния парсер должен найти соответствие правилу.

ados ★★★★★
() автор топика

результат работы парсера был бы такой же как если бы парсера изначально бы отправили по одной строке, которая была бы соединением первой и новой строк

Вопрос: почему нельзя сразу скормить соединение этих двух (трёх, миллиона) строк? Соединить в ленивом стиле, конечно (сделать поток данных)

Crocodoom ★★★★★
()
Ответ на: комментарий от Crocodoom

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

pon4ik ★★★★★
()
Ответ на: комментарий от pon4ik

А ТС, как я понял, ищет возможность «докармливать» парсер, если сообщение пришло не целиком.

на каждом токене получая состояние и используя на входе FILE * можно «кормить» парсер чем угодно. Пайпы никто не отменял, да и набор опций для парсинга из различных кусков во flex полно. Читайте маны - они рулят :-) info ещё знатная вещь - там как правило всё разжёвано детальнее и с примерами.

насколько понял ТС хочет нечто готовое, чтобы ничего не думать самому, но такого не бывает

MKuznetsov ★★★★★
()
Ответ на: комментарий от anonymous

Как я понял из топика, ТС не имел в виду продолжения в смысле схемовских continuations.

theNamelessOne ★★★★★
()
Ответ на: комментарий от ados

А, так понятнее. Такая проблема решается конечным автоматом (man алгоритм ахо корасик).

Deleted
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.