Здравствуйте, smeeld, Вы писали:
S>Тут задавали вопросы про сферический коммерческий код, типа что это такое и как он выглядит. Далее две ссылки, реализующие разные принципы построения парсеров, какой из них, по мнению здешней публики, больше достоен приниматься за эталон понятия "коммерческого кода".
Да никакой, ибо сам вопрос — глупый! Нет такого "коммерческого" кода. Есть задачи и целая куча параметров, влияющих на будущий код. Одна и та же "сортировка" может быть сделана 10 разными способами (не алгоритмом!), в зависимости от требований. Например:
а) программа нужна "ещё вчера", поэтому БЫСТРО делай любой прототип, лишь бы выход был корректный. Критерий — скорость разработки, шаблоны и космические архитектуры идут лесом.
б) программу будет поддерживать школьный учитель, поэтому код должен быть простой и даже без классов.
в) программа нужна для embedded, поэтому у тебя есть две переменных и 1КБ памяти — как хочешь, так и пиши.
г) программа нужна для выпендрёжа на RSDN, поэтому насуй туда побольше templates — люди это любят.
Ну и какой смысл при абсолютно неизвестных критериях сравнивать два шмота кода?? Вы, товарищ smeeld, сколько месяцев в программировании?
Здравствуйте, smeeld, Вы писали:
S>Далее две ссылки, реализующие разные принципы построения парсеров, какой из них, по мнению здешней публики, больше достоен приниматься за эталон понятия "коммерческого кода".
Здравствуйте, vsb, Вы писали:
vsb>1 более-менее понятно, хотя кода дофига. 2 вообще непонятно ничего. 1 лучше. А лучше написать кодогенератор, который сгенерирует код, похожий на 1 вариант из читабельного формата.
Хыхы, вот как раз данный вариант2 и является фрагментом "кодогенератора, который генерирует код из читабельного формата". )))
Здравствуйте, smeeld, Вы писали:
S>Он, этот монстр, в коммерческих проектах задействуется стохановскии темпами. Сейчас почти всё коммерческое, что пишется на C++, обязательно содержит код из буста, тенденция только нарастает.
Ну так это и логично. Если бы скажем реализовать с помощью Spirit парсер из твоего первого примера, то он гарантированно занял бы в разы меньше кода, причём максимально красивого (в котором чётко видно отдельное описание формата).
Здравствуйте, 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, Вы писали:
_>Ну т.е. если перевести с твоего языка на русский, то будет: "не могу". )))
В переводе на русский будет — "у alex_public в Киеве дядька".
Напомню твой залёт:
- Если есть желание продемонстрировать честный аналог Spirit'a в стиле C, то надо взять исходники Bison + Flex.
Spirit — это фреймворк для построения комбинаторного парсера. Напротив, семейство yacc (и его многочисленные клоны, включая бизона, бизона++ и прочих буфалло) — это полноценные LALR(1), LR(1), местами LR(k) и даже GLR-парсеры.
Похоже, эти перечисленные абревиатуры являются для тебя натуральной китайской грамотой, коль ты умудряешься давать советы, типа таких:
Если бы в моём проект стоял выбор между использованием Bison + Flex и Spirit, то скорее всего я бы предпочёл последнее, в силу более удобного API
Т.е., даже не глядя на вид грамматики, ты уже сделал выбор по некоему мифическому АПИ.
Откуда ты знаешь, какой АПИ у того же Bison++? Да у него чудесный С++ АПИ.
Мало того, АПИ Spirit просто ужасно, коряво, неюзабельно и сугубо write-only. Оно ужасно именно из-за тех вещей, что EDSL в С++ не всегда выходит гладко, особенно в деле ДЕКЛАРАТИВНОГО описания грамматик для парсинга с попыток связать эту декларацию с колбэками (semantic actions). Не они первые и не они последние, насчет EDSL парсеров в С++. Это болезнь роста как специалиста C++, многие через неё проходят.
Далее вообще смешно:
- Можешь предложить более близкий аналог Spirit'a из мира C? )
Тут сначала упал со стула, затем поднялся и внятно тебе ответил:
Слава богу, редко кому в голову приходила идея реализовывать комбинаторные парсеры на С. Комбинаторные парсеры — это изобретение далёких от программирования людей, которые пользовали в ежедневной практике функциональные языки. Они не знали теорию грамматик и писали парсеры "в лоб", получая естественные тормоза и жор памяти.
Похоже, ты не понял ответа моего и так не слишком завуалированного ответа, поэтому, перевожу на совсем прямую речь:
— комбинаторные парсеры предназначены для случайных в отрасли людей;
— случайные в отрасли люди редко пишут на С (как минимум редко пишут генераторы парсеров на С, ы-ы-ы).
Тем не менее, реализаций парсеров семейства PEG на С существует болееодной. Сие означает, что я-то как раз "могу" (могу привести примеры), но считаю их эээ... малость "неприличными" для приличного общества. Потому что упоминание PEG всуе, это как выйти на Красную площадь и ругаться матом. Судя по твоему ответу, ты не в курсе всех этих тонкостей, но опять и снова поторопился выступить в роли тролля. )) ИМХО, тролль должен хорошо разбираться в предмете, иначе это не тролль, а так, неудачная мимикрия из разряда "обалажался — притворись троллем".
Одно меня радует в приведенных ссылках на комбинаторные парсеры на С (который peg/leg), что после многолетней упорной смены версий и роста их аж до 0.1.18 (т.е. даже не альфы), авторы, судя по всему, одумались. Ну, мож, прочитали пару книг, наконец... Чего и всем советую.
Оба плохие: Я шарпист и плюсы вижу редко, поэтому чтение плюсов мне даётся сложно. В этих кусках кода я не понял откуда начинать читать, и поэтому я считаю их плохими. И, кстати, почему в первом варианте константы не где-то в h'нике с константами, а свалены в куче с кодом?
Всё сказанное выше — личное мнение, если не указано обратное.
Здравствуйте, 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 под С. Мало того, что о такой постановке вопроса речи даже не было (!!!), дык, по современным меркам пытаться гнуть в эту сторону — это заведомо сливать любой спор, бо ограничений на распространённость С++ давно уже нет.
Здравствуйте, vdimas, Вы писали:
_>>Перегрузка операторов в C? А ты как всегда шедеврален... ))) V>Релэкс, я знал, что тебе нечего будет возразить, кроме этого. V>Но я ж специально проверил, что "в стиле C" написано в кавычках. V>Т.е. не требовалось на С, требовалось в духе, ОК.
О, пошли отмазки. )))
V>Вот такая инициализация глобальных правил, по которым могут работать несколько экземпляров парсера — это очень даже в духе С. V>С точностью до перегрузки операторов, ес-но. V>Без этой перегрузки было бы что-то вроде: V>
V>Rule * A = ruleOr(B, ruleOr(ruleCat(A, C), ruleCat(ruleCat(A, B), C);
V>То бишь, задание AST этого БНФ-выражения... Тоже вполне работоспособно, но лучше не стоит так упарываться. ))
Даже если забыть про дикую уродливость подобного решения... Ты действительно считаешь, что данный код скомпилируется в те же инструкции, что и изначальный пример? )))
_>>А в C у нас имеется только последний вариант, так что точного аналога Spirit'a просто не существует. Именно в этом был мой тезис, который очевиден каждому вменяемому читателю. ))) V>Каждому вменяемому читателю видна насосанность из пальца вот этого требования аналога Spirit под С. Мало того, что о такой постановке вопроса речи даже не было (!!!), дык, по современным меркам пытаться гнуть в эту сторону — это заведомо сливать любой спор, бо ограничений на распространённость С++ давно уже нет.
Хех, вообще то именно об этом я тут и писал. Что Spirit является максимально плохим примером для нашей дискуссии (она же вообще то не про парсеры, а про стили) и надо взять любой (ну почти — надо чтобы он всё же был реализуем на C) другой пример современного шаблонного кода на C++ и тогда уже обсуждать. Так что похоже ты тут споришь с какими-то голосами в своей голове. )))
Здравствуйте, vdimas, Вы писали:
_>>Ну т.е. если перевести с твоего языка на русский, то будет: "не могу". ))) V>
V>- Можешь предложить более близкий аналог Spirit'a из мира C? )
V>Тут сначала упал со стула, затем поднялся и внятно тебе ответил: V>
V>Слава богу, редко кому в голову приходила идея реализовывать комбинаторные парсеры на С. Комбинаторные парсеры — это изобретение далёких от программирования людей, которые пользовали в ежедневной практике функциональные языки. Они не знали теорию грамматик и писали парсеры "в лоб", получая естественные тормоза и жор памяти.
V>Похоже, ты не понял ответа моего и так не слишком завуалированного ответа, поэтому, перевожу на совсем прямую речь: V>- комбинаторные парсеры предназначены для случайных в отрасли людей; V>- случайные в отрасли люди редко пишут на С (как минимум редко пишут генераторы парсеров на С, ы-ы-ы). V>Тем не менее, реализаций парсеров семейства PEG на С существует болееодной. Сие означает, что я-то как раз "могу" (могу привести примеры), но считаю их эээ... малость "неприличными" для приличного общества. Потому что упоминание PEG всуе, это как выйти на Красную площадь и ругаться матом. Судя по твоему ответу, ты не в курсе всех этих тонкостей, но опять и снова поторопился выступить в роли тролля. )) ИМХО, тролль должен хорошо разбираться в предмете, иначе это не тролль, а так, неудачная мимикрия из разряда "обалажался — притворись троллем".
Молодец, домашнее задание по владению гуглом ты выполнил. Но понимания фундаментальных архитектурных принципов у тебя по прежнему нет, так что пока зачёта не предвидится.
Показанные тобой примеры парсеров при всей алгоритмической похожести не имеют ничего общего со Spirit'ом с точки зрения архитектуры. Они все представляю собой просто обычный парсер с кастомизируемым форматом. Он однажды собирается в приложение и потом его поведение настраивается внешними рантайм данными (строкой с грамматикой). В противоположность этому Spirit (так же как и Bison+Flex) генерирует под каждую грамматику разный код, который потом активно оптимизируется (включая глубокий инлайн) компилятором. Именно этим и обусловлена высокая эффективность всех парсеров на базе кодогенераторов. А уникальность Spirit'а заключается только в том, что это EDSL генератор, а не внешний.
Да, кстати, могу тебе сделать подсказку для дальнейших попыток найти более адекватный аналог на C (и тем самым показать что твоя придирка не была глупой). По идее единственным способом написать аналог Spirit'а на C будет построение некого страшного монстра на макросах. Сомневаюсь, что кто-то подобное делал, но если нет такого решения, то скорее всего нет и никакого другого.
Тут задавали вопросы про сферический коммерческий код, типа что это такое и как он выглядит. Далее две ссылки, реализующие разные принципы построения парсеров, какой из них, по мнению здешней публики, больше достоен приниматься за эталон понятия "коммерческого кода".
1 более-менее понятно, хотя кода дофига. 2 вообще непонятно ничего. 1 лучше. А лучше написать кодогенератор, который сгенерирует код, похожий на 1 вариант из читабельного формата.
Здравствуйте, vsb, Вы писали:
vsb>1 более-менее понятно, хотя кода дофига. 2 вообще непонятно ничего. 1 лучше. А лучше написать кодогенератор, который сгенерирует код, похожий на 1 вариант из читабельного формата.
Да. В многих либах Boost-а вообще самый запутаный код, который мне приходилось изучать. В исходниках некоторых либ из boost-а, таких как boost::asio или boost::coroutine, всё хорошо понятно, но вот Spirit-это пример ужаса на крыльях ночи. Этот примёр только фрагмента файла из Spirit-а, дерево каталогов этой либы ещё более запутанно, всё раскидано по разным закоулкам и все закоулки с одинаковым названиями файлов и директорий, как будто специально что-то пытаются спрятать, или просто пишут очень небрежно, сваливая куда придётся в пределах дерева. Но, возможно сейчас появятся фанаты boost-а (Nixman), и расскажут, что это так и должно быть.
K>Да никакой, ибо сам вопрос — глупый! Нет такого "коммерческого" кода.
Ну, это чисто для прикола, на этом форуме иногда появлялись начинающие, которые спрашивали как выглядит "типичный коммерческий код", типа умение писать именно такой код есть требование для успешного трудоустройства. Но те два примера интересны ещё как пример различия дизайнов, первый есть олдскульный C-like, второй есть modern C++, в которой даже запятые являются шаблонными классами. Какой из них более предпочителен в 2017 году? Прошу высказаться.
Сравнение некорректно, потому что приведённый пример кода в стиле C является парсером конкретного протокола, а пример кода в стиле современного C++ является универсальным средством для построения произвольных парсеров. Если есть желание продемонстрировать честный аналог Spirit'a в стиле C, то надо взять исходники Bison + Flex.
P.S. Если бы в моём проект стоял выбор между использованием Bison + Flex и Spirit, то скорее всего я бы предпочёл последнее, в силу более удобного API.
хех, а вам-то какое до них дело? Когда они вырастут профессионально, они сами поймут, что любой код может оказаться "правильным". А показывать примеры сейчас — только ещё больше их запутывать, ибо критерии "лучшести" неизвестны.
S> Но те два примера интересны ещё как пример различия дизайнов .... Какой из них более предпочителен в 2017 году?
Критерии лучшести не зависят от года. Выше я привёл 4 критерия, по которым любая программа может оказаться ужасной, хотя и написанной по всем канонам.
Если говорить о самых минимальных критериях, программа должна быть ПОДДЕРЖИВАЕМОЙ, что включает в себя простоту кода, лёгкое переиспользование и заимствование кода. Этот критерий работает как для профи, так и для любых хобби-проектов.
Здравствуйте, alex_public, Вы писали:
_>Сравнение некорректно, потому что приведённый пример кода в стиле C является парсером конкретного протокола, а пример кода в стиле современного C++ является универсальным средством для построения произвольных парсеров. Если есть желание продемонстрировать честный аналог Spirit'a в стиле C, то надо взять исходники Bison + Flex.
+1
Зануда мод он: не "исходники Bison + Flex", и сгенеренный ими код/API и входную грамматику.
_>P.S. Если бы в моём проект стоял выбор между использованием Bison + Flex и Spirit, то скорее всего я бы предпочёл последнее, в силу более удобного API.
Где здесь "коммерция"? Упустим, что это вообще несравнимый код.
Первый — "честно скоммунизденный" код из продукта, по волею случая ставшего "почти чуть" коммерческим.
Второй — частичка части монстра, развиваемого сообществом.
Здравствуйте, Skorodum, Вы писали:
_>>Сравнение некорректно, потому что приведённый пример кода в стиле C является парсером конкретного протокола, а пример кода в стиле современного C++ является универсальным средством для построения произвольных парсеров. Если есть желание продемонстрировать честный аналог Spirit'a в стиле C, то надо взять исходники Bison + Flex. S>+1 S>Зануда мод он: не "исходники Bison + Flex", и сгенеренный ими код/API и входную грамматику.
Нет, как раз аналогом исходников Spirit будут исходники Bison + Flex. Аналогом входной грамматики будет исходный код (обычно несколько строк), использующий Spirit. А сгенерированным кодом/API будет то, вот что компилятор раскроет все эти шаблоны при компиляции кода, использующего Spirit.
Здравствуйте, fin_81, Вы писали:
_>Второй — частичка части монстра, развиваемого сообществом.
Он, этот монстр, в коммерческих проектах задействуется стохановскии темпами. Сейчас почти всё коммерческое, что пишется на C++, обязательно содержит код из буста, тенденция только нарастает. Верно и обратное, сам boost представляет собой собрание наработок, сделанных в разработке различных проектов разработки коммерческого софта.
Здравствуйте, alex_public, Вы писали:
_>Ну так это и логично. Если бы скажем реализовать с помощью Spirit парсер из твоего первого примера, то он гарантированно занял бы в разы меньше кода, причём максимально красивого (в котором чётко видно отдельное описание формата).
Чёрта с два он будет производительней, если использовать стандартную схему с построением дерева в контейнерах на основе правил qi::grammar, и последующем его обходе. В первом же случае переходы парсинга определяется по ходу чтения байтов-символов с сырого текста, и по достижению спайса уже известно куда идти дальше. Если такую схему реализовать spirit-ом, то получится то же самое, только записанное в ином стиле: цикл будет не в стиле
Какой из методов более предпочтителен, в этом и есть суть вопроса в треде, олдскульный while(){}, или в стиле фантазий разрабов буста, в виде type type type.
Здравствуйте, smeeld, Вы писали:
_>>Второй — частичка части монстра, развиваемого сообществом.
S>Он, этот монстр, в коммерческих проектах задействуется стохановскии темпами. Сейчас почти всё коммерческое, что пишется на C++, обязательно содержит код из буста, тенденция только нарастает. Верно и обратное, сам boost представляет собой собрание наработок, сделанных в разработке различных проектов разработки коммерческого софта.
Люблю аналогии.
Сейчас все коммерческое, сто пишется на С++, обязательно содержит оператор префиксного инкремента, тенденция только нарастает. Верно и обратное, само использование префиксного инкремента есть следствие нароботок, сделанных в разработке коммерческого софта.
Какой вывод? Префиксный инкремент — это коммерческий софт?
Второй вопрос, первый листинг — это пример коммерческого или некоммерческого софта?
В-нулевых, где здесь "коммерция"?
Во-первых, ты сравниваешь не сравнимое, генератор парсера на так-скажем тьюринг-полном языке шаблонов С++ сравниваешь с конкретной реализацией.
Во-вторых, опять сравниваешь несравнимое, неэквивалентный код так-скажем императивного цикла while и так-скажем функциональный стиль метапрограммирования на шаблонах.
Здравствуйте, fin_81, Вы писали:
_>В-нулевых, где здесь "коммерция"?
А вот это и хотел бы узнать, что для "типично коммерческого" более приемлемо.
_>Во-первых, ты сравниваешь не сравнимое, генератор парсера на так-скажем тьюринг-полном языке шаблонов С++ сравниваешь с конкретной реализацией.
Там, вообще говоря, неважно, реализация чего именно там. Приводились примеры дизайна кода, и спрашивалось, какой из них более предпочтителен в 2017 в разработке на C++ в проектах коммерческого кода (тот, что за бабки будет продаваться).
_>Во-вторых, опять сравниваешь несравнимое, неэквивалентный код так-скажем императивного цикла while и так-скажем функциональный стиль метапрограммирования на шаблонах.
Вот для того и сравниваю, чтоб узнать мнение местной публики, какой из них предпочтительней для, см. выше.
Здравствуйте, 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 просто не существует. Именно в этом был мой тезис, который очевиден каждому вменяемому читателю. )))
Здравствуйте, 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++" вполне имеет право на жизнь. Но для его вменяемого обсуждения надо в начале найти два соответствующих примера решения одной и той же задачи. Тогда с удовольствием пообсуждаем...
Здравствуйте, alex_public, Вы писали:
_>>>Если есть желание продемонстрировать честный аналог Spirit'a в стиле C, то надо взять исходники Bison + Flex. V>>А давно у нас Бизоны и Флексы являются аналогами комбинаторных парсеров? _>Можешь предложить более близкий аналог Spirit'a из мира C? )
Слава богу, редко кому в голову приходила идея реализовывать комбинаторные парсеры на С. Комбинаторные парсеры — это изобретение далёких от программирования людей, которые пользовали в ежедневной практике функциональные языки. Они не знали теорию грамматик и писали парсеры "в лоб", получая естественные тормоза и жор памяти.
Если же брать язык С, то он получил свой расцвет в те времена, когда память была еще ресурсом, а программисты еще были обучены по целевой специальности. ))
Здравствуйте, smeeld, Вы писали:
V>>Для чего-то более-менее серьезного оба не годятся, ес-но. S>Есть ли что-то в открытом доступе, которое было бы примером пригодного для чего-то более-менее серьёзного?
Здравствуйте, vdimas, Вы писали:
_>>>>Если есть желание продемонстрировать честный аналог Spirit'a в стиле C, то надо взять исходники Bison + Flex. V>>>А давно у нас Бизоны и Флексы являются аналогами комбинаторных парсеров? _>>Можешь предложить более близкий аналог Spirit'a из мира C? ) V>Слава богу, редко кому в голову приходила идея реализовывать комбинаторные парсеры на С. Комбинаторные парсеры — это изобретение далёких от программирования людей, которые пользовали в ежедневной практике функциональные языки. Они не знали теорию грамматик и писали парсеры "в лоб", получая естественные тормоза и жор памяти. V>Если же брать язык С, то он получил свой расцвет в те времена, когда память была еще ресурсом, а программисты еще были обучены по целевой специальности. ))
Ну т.е. если перевести с твоего языка на русский, то будет: "не могу". )))
Здравствуйте, alex_public, Вы писали:
_>>>Перегрузка операторов в C? А ты как всегда шедеврален... ))) V>>Релэкс, я знал, что тебе нечего будет возразить, кроме этого. V>>Но я ж специально проверил, что "в стиле C" написано в кавычках. V>>Т.е. не требовалось на С, требовалось в духе, ОК.
_>О, пошли отмазки. )))
Ожидаемо скатился в троллизм.
Твои слова?
Так вот написать его полноценный аналог "в стиле C" просто невозможно
Здравствуйте, vdimas, Вы писали:
_>>>>Перегрузка операторов в C? А ты как всегда шедеврален... ))) V>>>Релэкс, я знал, что тебе нечего будет возразить, кроме этого. V>>>Но я ж специально проверил, что "в стиле C" написано в кавычках. V>>>Т.е. не требовалось на С, требовалось в духе, ОК. _>>О, пошли отмазки. ))) V>Ожидаемо скатился в троллизм. V>Твои слова? V>
V>Так вот написать его полноценный аналог "в стиле C" просто невозможно
Ну т.е. перегрузка операторов — это по твоему код "в стиле C", да?
Здравствуйте, alex_public, Вы писали:
_>Молодец, домашнее задание по владению гуглом ты выполнил.
Смишно. Гугл как раз даёт ссылки на обсуждения тем с парсерами на RSDN с моим участием в разные годы. ))
На этом сайте уже достаточно инфы и всё разжевано не раз, было бы желание учиться...
Кароч, заканчивай маяться фигней, ты принципиально не в ту сторону рассуждаешь.