metaclass: (Default)
metaclass ([personal profile] metaclass) wrote2011-06-06 01:13 am

Парсерный оверкилл?

Внезапно понадобилось сделать парсер строк с грамматикой подобного вида:
ИмяКласса | ИмяКласса(Параметр0,...)

Можно было бы не вдумываясь, склепать что-нибудь типа "найти скобки, до скобок - имя класса, внутри скобок разделить по запятым".
Но мне домашний паук из розетки приказал это сделать на генераторах парсеров, в частности fslex/fsyacc, что заняло немного больше времени, но как минимум, я теперь смогу при необходимости нормально менять грамматику или писать новые парсеры, разобравшись на простом примере.

Проблема в следующем: не является ли использование вуду-знаний из драгонбука правильных методик оверкиллом? А то уже не первый раз на работе возникают споры на тему "почему нужно делать правильно и долго, если можно сделать быстро и, с некоторыми ограничениями, будет работать".

[identity profile] smalgin.livejournal.com 2011-06-05 11:03 pm (UTC)(link)
Если введение новой зависимости от fslex/fsyacc не проблема и код хорошо документирован, то это никакой не оверкилл, а все правильно.

А то всякое бывает, от раздутия дистрибутива до maintenance nightmares...

[identity profile] justy-tylor.livejournal.com 2011-06-05 11:42 pm (UTC)(link)
Наоборот. Генераторы парсеров это низкоуровневая EBNF на входе и обычно неудобный bottom-up на выходе.

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

[identity profile] metaclass.livejournal.com 2011-06-06 04:47 am (UTC)(link)
Да, на комбинаторах это должно быть явно гуманнее.

[identity profile] lemantar.livejournal.com 2011-06-05 11:51 pm (UTC)(link)
а чем банальный регэксп не угодил?

[identity profile] metaclass.livejournal.com 2011-06-06 04:46 am (UTC)(link)
Может и подошел бы, но их я знаю еще хуже, чем генераторы парсеров :)
Я с ходу не вспомню, как описать такую грамматику регэкспом, да чтобы на выходе сразу получить результат.

[identity profile] lionet.livejournal.com 2011-06-06 05:11 am (UTC)(link)
ИмяКласса | ИмяКласса(Параметр0,...)

[A-Za-z0-9]+\s*(\([a-z0-9]+(,\s*[a-z0-9]+)*\))?

[identity profile] lemantar.livejournal.com 2011-06-06 12:08 pm (UTC)(link)
для латинских букв вполне

[identity profile] lionet.livejournal.com 2011-06-06 12:00 am (UTC)(link)
А чем банальный PEG не угодил?

[identity profile] metaclass.livejournal.com 2011-06-06 04:45 am (UTC)(link)
Вот мне только не хватало еще и это реализовывать, хотя как средство отмазаться от писания отчетов о проделанной работе хорошо. "С 1 по 7 июня: реализую PEG на F#" :)

[identity profile] thedeemon.livejournal.com 2011-06-06 05:51 am (UTC)(link)
Комбинаторы это дело реализуют, а сами они гораздо проще в реализации и использовании, чем это может показаться. Там кода-то строк 20.

[identity profile] permea-kra.livejournal.com 2011-06-08 08:53 am (UTC)(link)
Ну их нафиг, там надо очень тщательно за строением грамматики следить. Левой рекурсии низзя, легко напороться на экпонециальные затраты времени... Нафиг, нафиг.

[identity profile] gabaidulin.livejournal.com 2011-06-14 06:19 pm (UTC)(link)
Пакрат не решает эту проблему разве?

[identity profile] permea-kra.livejournal.com 2011-06-14 08:57 pm (UTC)(link)
Не-а. Пусть char 'x' - завершается успешно, если встретился x, а || порождает парсер, принимающий либо лево, либо право. Тогда парсер
a = ( a || char 'x' ++ something ) свалится в бесконечную рекурсию. В тоже время нормальный парсер-генератор такую грамматику вполне отработает. От мемоизации промежуточных результатов ничего не изменится.

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

[identity profile] gabaidulin.livejournal.com 2011-06-15 05:49 am (UTC)(link)
Ну значит manual по scala видимо говорит про какую-то другую левую рекурсию ?

http://www.scala-lang.org/api/current/scala/util/parsing/combinator/PackratParsers.html

[identity profile] permea-kra.livejournal.com 2011-06-15 08:42 am (UTC)(link)
Ваще-то да, поскольку там потроха изрядно другие, чем у простых парсер-комбинаторов.

[identity profile] gabaidulin.livejournal.com 2011-06-15 09:25 am (UTC)(link)
Хмм. Ну вообще с точки зрения кода эту будет тот же парсер комбинатор(то есть мы строим грамматику состоящую из простых правил с использованием простых парсеров, комбинируя их в более сложные с помощью специальных операторов), надо будет добавить with PackratParser и использовать lazy vals. Ну-да ладно.

[identity profile] raydac.livejournal.com 2011-06-06 05:19 am (UTC)(link)
у нас на работе предалагают вариант "долго и правильно", но тут контора богатая, за чужие бабки можно долго и правильно и даже безрезультатно если чо

[identity profile] blackyblack.livejournal.com 2011-06-06 05:21 am (UTC)(link)
Ответ на вопрос зависит от того, сколько в дальнейшем появится разных грамматик для парсения. Пока их одна и больше не предвидится, то лучше разбирать руками. Когда их становится больше 3-х, то лучше использовать парсер/генератор парсеров.

[identity profile] trueblacker.livejournal.com 2011-06-06 05:36 am (UTC)(link)
Вопрос можно префразировать. Какая пара из невозможной троицы (цена, время, качество) наиболее кошерна? При такой постановке отсутствие единственно верного подхода очевидна.
Скилл проджектляйтера, тимлида и прочих архитектуреров как раз и заключается в умении ппавильно расставить весовые коэффициенты в компонентах этой троицы применительно к конкретной задаче, набору доступных ресурсов и прогнозируемому спросу. В общем виде, разумеется, решения нет.
Что касается пауков, то все ок, пока их не начинаешь путать с тараканами.

[identity profile] jdevelop.livejournal.com 2011-06-06 06:16 am (UTC)(link)
я бы сказал, что ответ на вопрос зависит от того, что и как может делать команда

если они не знают про парсер-комбинаторы зато джедаи в регэкспах - то вас нужно изолировать от общества их и дать им работу работать

[identity profile] aamonster.livejournal.com 2011-06-06 06:26 am (UTC)(link)
Зависит от того, делать один раз или потом ещё 10 раз понадобится (и при этом правильные методы уже будут так же быстры, а в сложных случаях и быстрее)

[identity profile] gabaidulin.livejournal.com 2011-06-14 06:18 pm (UTC)(link)
PEG или парсер комбинаторы. На dot net вроде есть приличный PEG. Yacc/Lex после них настоящая боль.

[identity profile] os80.livejournal.com 2011-07-09 05:58 pm (UTC)(link)
>не является ли использование правильных методик оверкиллом?
Если моё мнение интересует, то - является. Более того, Ваш вопрос надо переформулировать по-другому - является ли разумным использование формата, для парсинга которого нужны правильные методики.