Здравствуйте, smeeld, Вы писали:
_>>... опять сравниваешь несравнимое ...
S>Вот для того и сравниваю, чтоб узнать мнение местной публики, какой из них предпочтительней для, см. выше.
Удачи в попытках сравнить несравнимое. Но это лучше делать в политике. Там аудитория больше и больше любит сравнивать несравнимое.
_>Удачи в попытках сравнить несравнимое. Но это лучше делать в политике. Там аудитория больше и больше любит сравнивать несравнимое.
Вы опять не поняли, речь идёт о "выборе", а не о "сравнении". Что представляет из себя каждый из дизайнов ясно прекрасно, их не думалось "сравнивать". Тут всё просто: у кого-то проект, стоит ли ему писать в олдскульном C-like стиле, как в первом варианте, или "описать мир" параметризованными типами, как в первом варианте?
Здравствуйте, smeeld, Вы писали:
_>>Выбор основывается на сравнении или пальцем в небо?
S>Выбор должен основываться на опыте и предпочтении.
Допустим есть у человека опыт в написании парсеров генератором парсеров на языке L. Ему дают портянку реализации конкретного пасрера на языке M. Что он должен выбрать для "неизвестно чего тобой задуманного"? Ответ: даданетда.
Здравствуйте, smeeld, Вы писали:
_>>Ну так это и логично. Если бы скажем реализовать с помощью Spirit парсер из твоего первого примера, то он гарантированно занял бы в разы меньше кода, причём максимально красивого (в котором чётко видно отдельное описание формата). S>Чёрта с два он будет производительней, если использовать стандартную схему с построением дерева в контейнерах на основе правил qi::grammar, и последующем его обходе. В первом же случае переходы парсинга определяется по ходу чтения байтов-символов с сырого текста, и по достижению спайса уже известно куда идти дальше. Если такую схему реализовать spirit-ом, то получится то же самое, только записанное в ином стиле: цикл будет не в стиле S>
1. И где ты увидел в моей фразе хоть одно слово на тему производительности? )
2. Похоже ты не очень хорошо знаком с внутренним устройством Spirit'a — там как раз работает тот же самый посимвольный последовательный парсинг. И кстати это в какой-то степени недостаток (или точнее ограничение применимости), т.к. не позволяет работать с некоторыми сложными грамматиками.
3. Похоже что ты не очень хорошо знаком и с внешним интерфейсом Spirit'a, если предлагаешь подобные варианты использования. Советую посмотреть на задание ветвлений там. Не говоря уже о том, что в современном C++ для таких целей есть лямбды.
S> Какой из методов более предпочтителен, в этом и есть суть вопроса в треде, олдскульный while(){}, или в стиле фантазий разрабов буста, в виде type type type.
Вот это уже вполне вменяемый вопрос, который можно и пообсуждать. Только вот твой изначальный пример к нему абсолютно неудачный. Могу пояснить где главный косяк. Ты привёл в качестве примера исходник самого Spirit'a, т.е. библиотеки для создания произвольных парсеров. Так вот написать его полноценный аналог "в стиле C" просто невозможно (как ты будешь задавать грамматику в коде?). Для решения этой задачи в мире C используют внешний грамматики и кодогенераторы, но это уже как бы совсем другое и менее удобное решение. Корректным вариантом твоего примера было предоставление вместо исходника Spirit'a, код на C++ задающий аналогичный парсер с помощью Spirit'a. Но это ты естественно не стал делать, т.к. сравнение было бы однозначно в пользу C++ варианта (хотя бы потому что в разы меньший объём кода).
Здравствуйте, smeeld, Вы писали:
S>Тут задавали вопросы про сферический коммерческий код, типа что это такое и как он выглядит. Далее две ссылки, реализующие разные принципы построения парсеров, какой из них, по мнению здешней публики, больше достоен приниматься за эталон понятия "коммерческого кода".
Никакой. ))
Во-первых, нельзя сравнивать конкретный парсер и библиотеку для построения оных.
Во-вторых, первый код наивно-нубский сам по себе (http_parser_cpp, который).
Второй код не нубский, но позиционируется для нубов, потому что служит для разработки т.н. "комбинаторных парсеров".
Для чего-то более-менее серьезного оба не годятся, ес-но.
Здравствуйте, alex_public, Вы писали:
_>Если есть желание продемонстрировать честный аналог Spirit'a в стиле C, то надо взять исходники Bison + Flex.
А давно у нас Бизоны и Флексы являются аналогами комбинаторных парсеров?
_>P.S. Если бы в моём проект стоял выбор между использованием Bison + Flex и Spirit, то скорее всего я бы предпочёл последнее, в силу более удобного API.
Это ты по таким критериям выбираешь технологии реализации парсеров?
Или не выбирал еще ни разу, а просто вот, фантазируешь на тему? ))
Здравствуйте, alex_public, Вы писали:
_>2. Похоже ты не очень хорошо знаком с внутренним устройством Spirit'a — там как раз работает тот же самый посимвольный последовательный парсинг.
Нет там никакого "последовательного парсинга".
Там обход дерева правил с откатами.
Что-то типа PEG.
_>Вот это уже вполне вменяемый вопрос, который можно и пообсуждать. Только вот твой изначальный пример к нему абсолютно неудачный. Могу пояснить где главный косяк. Ты привёл в качестве примера исходник самого Spirit'a, т.е. библиотеки для создания произвольных парсеров. Так вот написать его полноценный аналог "в стиле C" просто невозможно
Возможно аж бегом.
_>как ты будешь задавать грамматику в коде?
В форме БНФ, вестимо:
extern Rule A, B, C;
Rule A = B | A+C | A+B+C;
Rule B = B+'x' | 'y';
Rule C = C+'z' | 'z';
_>Для решения этой задачи в мире C используют внешний грамматики и кодогенераторы, но это уже как бы совсем другое и менее удобное решение.
Кодогенераторы используют и в мире С++, это более удобное решение, чем Spirit.
Комбинаторные парсеры, типа Spirit (а их для С++ дофига, помимо бустовского) спасают только в совсем простейших случаях, где сложно напороться на зацикливание грамматики или когда сам парсер принципиально не позволяет зацикливать грамматику. В последнем случае имеем совсем обрезанный класс грамматик.
Здравствуйте, vdimas, Вы писали:
_>>Если есть желание продемонстрировать честный аналог Spirit'a в стиле C, то надо взять исходники Bison + Flex. V>А давно у нас Бизоны и Флексы являются аналогами комбинаторных парсеров?
Можешь предложить более близкий аналог Spirit'a из мира C? )
Здравствуйте, vdimas, Вы писали:
_>>Ты привёл в качестве примера исходник самого Spirit'a, т.е. библиотеки для создания произвольных парсеров. Так вот написать его полноценный аналог "в стиле C" просто невозможно V>Возможно аж бегом. _>>как ты будешь задавать грамматику в коде? V>В форме БНФ, вестимо: V>
V>extern Rule A, B, C;
V>Rule A = B | A+C | A+B+C;
V>Rule B = B+'x' | 'y';
V>Rule C = C+'z' | 'z';
V>
Перегрузка операторов в C? А ты как всегда шедеврален... )))
_>>Для решения этой задачи в мире C используют внешний грамматики и кодогенераторы, но это уже как бы совсем другое и менее удобное решение. V>Кодогенераторы используют и в мире С++, это более удобное решение, чем Spirit.
В C++ есть возможность использовать и EDSL генераторы парсеров и внешние кодогенераторы. А в C у нас имеется только последний вариант, так что точного аналога Spirit'a просто не существует. Именно в этом был мой тезис, который очевиден каждому вменяемому читателю. )))
Оба плохие: Я шарпист и плюсы вижу редко, поэтому чтение плюсов мне даётся сложно. В этих кусках кода я не понял откуда начинать читать, и поэтому я считаю их плохими. И, кстати, почему в первом варианте константы не где-то в h'нике с константами, а свалены в куче с кодом?
Всё сказанное выше — личное мнение, если не указано обратное.
Здравствуйте, alex_public, Вы писали:
_>3. Похоже что ты не очень хорошо знаком и с внешним интерфейсом Spirit'a, если предлагаешь подобные варианты использования. Советую посмотреть на задание ветвлений там. Не говоря уже о том, что в современном C++ для таких целей есть лямбды.
Про лямбды в современном C++ напоминать не нужно, если запихну туда что-то из boost::phoenix, то производительности это не добавит, как бы красиво это не выглядело.
Здравствуйте, smeeld, Вы писали:
_>>3. Похоже что ты не очень хорошо знаком и с внешним интерфейсом Spirit'a, если предлагаешь подобные варианты использования. Советую посмотреть на задание ветвлений там. Не говоря уже о том, что в современном C++ для таких целей есть лямбды. S>Про лямбды в современном C++ напоминать не нужно, если запихну туда что-то из boost::phoenix, то производительности это не добавит, как бы красиво это не выглядело.
Вот как раз с появлением лямбд потребность в boost::phoenix (а так же в boost::bind и т.п.) сильно уменьшилась. Ну и кстати лично я не вижу какой-то особой красоты во всех этих "_1" и т.п. Лямбды гораздо яснее и корректнее решают все эти задачи. Особенно современные обобщённые лямбды.
Но это всё отвлечение от темы. А по теме я хочу ещё раз уточнить свою изначальную мысль. Да, исходники Spirit'a действительно страшноватенькие. Но это потому, что это реально сложный продукт, прямой аналог которого просто невозможно написать на C. Более того, если учесть факт статической компиляции и оптимизации создаваемого парсера и поставить это как необходимое условие, то точный аналог невозможен и в большинстве других языков (т.е. задать произвольный парсер на каком-нибудь там C# уже получится, но он будет дико тормозным, т.к. это будет рантайм структура без всякой оптимизации компилятором). Поэтому тебе тут многие и написали о некорректности твоего примера.
В тоже время сам твой вопрос о сравнение "C стиля" и "стиля современного C++" вполне имеет право на жизнь. Но для его вменяемого обсуждения надо в начале найти два соответствующих примера решения одной и той же задачи. Тогда с удовольствием пообсуждаем...
Здравствуйте, smeeld, Вы писали:
V>>Для чего-то более-менее серьезного оба не годятся, ес-но. S>Есть ли что-то в открытом доступе, которое было бы примером пригодного для чего-то более-менее серьёзного?
Дык, классика:
связка lex/flex + yacc/bison.
Реализуют лексер + простой парсер по LR(1)
(более строго LRAR(1))
Но ты можешь просто поискать "LR(k) parser generator" — их хватает под разные языки, например: http://hyacc.sourceforge.net/
Что-то более серьезное — это GLR-парсеры, но это коммерческая тема чаще всего.
А вообще рулят фреймворки генераторов парсеров.
Из самых продвинутых — https://ru.wikipedia.org/wiki/ANTLR
Рекомендую скачать полный набор инструментария и побаловаться.
Более того, если опыта в разработке парсеров нет, то я категорически настаиваю начинать именно с этого инструмента.
Или вот у меня есть свои наработки по GLR-парсингу, которые я периодически юзаю. Алгоритм GLR относится к классу алгоритмов, которые в состоянии разобрать ЛЮБУЮ контектсно-свободную грамматику. Даже если в ней специально напихать циклов и "ловушек" — пофик. Жуёт и причмокивает. ))
Никакими Boost.Spirit ты GLR-парсер не нарисуешь, ес-но.
Но у меня сам "движок", который работает по некоей грамматике. Но саму-то грамматику удобнее отлаживать в каком-нить визуальном инструменте, вот как раз юзаю периодически ANTLR.
Здравствуйте, alex_public, Вы писали:
_>>>Если есть желание продемонстрировать честный аналог Spirit'a в стиле C, то надо взять исходники Bison + Flex. V>>А давно у нас Бизоны и Флексы являются аналогами комбинаторных парсеров? _>Можешь предложить более близкий аналог Spirit'a из мира C? )
Слава богу, редко кому в голову приходила идея реализовывать комбинаторные парсеры на С. Комбинаторные парсеры — это изобретение далёких от программирования людей, которые пользовали в ежедневной практике функциональные языки. Они не знали теорию грамматик и писали парсеры "в лоб", получая естественные тормоза и жор памяти.
Если же брать язык С, то он получил свой расцвет в те времена, когда память была еще ресурсом, а программисты еще были обучены по целевой специальности. ))
Здравствуйте, alex_public, Вы писали:
_>>>Ты привёл в качестве примера исходник самого Spirit'a, т.е. библиотеки для создания произвольных парсеров. Так вот написать его полноценный аналог [b]"в стиле C" просто невозможно[/b]
V>>Возможно аж бегом. _>>>как ты будешь задавать грамматику в коде? V>>В форме БНФ, вестимо: _>Перегрузка операторов в C? А ты как всегда шедеврален... )))
Релэкс, я знал, что тебе нечего будет возразить, кроме этого.
Но я ж специально проверил, что "в стиле C" написано в кавычках.
Т.е. не требовалось на С, требовалось в духе, ОК.
Вот такая инициализация глобальных правил, по которым могут работать несколько экземпляров парсера — это очень даже в духе С.
С точностью до перегрузки операторов, ес-но.
Без этой перегрузки было бы что-то вроде:
Rule * A = ruleOr(B, ruleOr(ruleCat(A, C), ruleCat(ruleCat(A, B), C);
То бишь, задание AST этого БНФ-выражения... Тоже вполне работоспособно, но лучше не стоит так упарываться. ))
У нас GCC сегодня пашет для всех основных архитектур, т.е. нет ни одной причины юзать "голый С", хотя писать "в духе С" причин всё еще полно:
— без исключений будет более эффективный код;
— глобальные данные рулят, если хорошо уметь их готовить;
— виртуальные вызовы тяжелы;
— как тяжел и RTTI.
В общем, в С++ есть много встроенных тормозов, как раз в случае парсеров их лучше не задействовать.
_>В C++ есть возможность использовать и EDSL генераторы парсеров и внешние кодогенераторы.
Как и в любом другом языке.
Мои претензии были конкретно к Spirit, потому что это НЕ генератор парсеров. Хотя, мне на глаза попадались и EDSL-генераторы парсеров.
Еще раз, Spirit — это парсер и есть, считай, а не генератор. Это готовые блоки парсера (базис) + ср-ва их комбинирования. Получаемый парсер — комбинаторный. То бишь, реализующий самый плохой алгоритм из всех известных на сегодня.
_>А в C у нас имеется только последний вариант, так что точного аналога Spirit'a просто не существует. Именно в этом был мой тезис, который очевиден каждому вменяемому читателю. )))
Каждому вменяемому читателю видна насосанность из пальца вот этого требования аналога Spirit под С. Мало того, что о такой постановке вопроса речи даже не было (!!!), дык, по современным меркам пытаться гнуть в эту сторону — это заведомо сливать любой спор, бо ограничений на распространённость С++ давно уже нет.
Здравствуйте, smeeld, Вы писали:
V>>Для чего-то более-менее серьезного оба не годятся, ес-но. S>Есть ли что-то в открытом доступе, которое было бы примером пригодного для чего-то более-менее серьёзного?