Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

The Switch Parser

Boost , ,

The Switch Parser

Переключатели могут использоваться для упрощения определенных конструкций чередования. Рассмотрим следующий код:

    rule<> rule_overall =
            ch_p('a') >> parser_a
        |   ch_p('b') >> parser_b
            // ...
        |   ch_p('n') >> parser_n
        ;

Каждая из альтернатив обычно оценивается последовательно. Это, как правило, неэффективно, особенно для большого количества альтернатив. Чтобы избежать этой неэффективности и дать возможность писать такие конструкции в более читаемой форме, Spirit содержитswitch_p.Семейство парсеров. Парсер switch_p позволяет переписать предыдущую конструкцию следующим образом:

    rule<> rule_overall =
            switch_p
            [
                case_p<'a'>(parser_a),
                case_p<'b'>(parser_b),
                // ...
                case_p<'n'>(parser_n)
            ]
        ;

Этоswitch_pпарсер берет следующий символ (или токен) из входного потока и пытается сопоставить его с заданными интегральными константами времени компиляции, поставляемыми в качестве параметров шаблона вcase_pПарсеры. Если этот персонаж соответствует одному изcase_pветви, ассоциированный парсер выполняется (т.е. если «а» совпадает,парсер_а)выполняется, если «b» совпадает,parser_bвыполняется и так далее. Если нетcase_pветвь соответствует следующему входному символу, общая конструкция не совпадает вообще.

Nabialek trick

The "Nabialek trick" (from the name of its inventor, Sam Nabialek), can also improve the rule dispatch from linear non-deterministic to deterministic. This is similar to the switch_p parser, yet, can handle grammars where a keyword (operator, etc), instead of a single character or token, precedes a production.

Иногда желательно добавить обработку дела по умолчанию (ни одна из ветвейcase_pне совпадает). Это может быть достигнуто с помощью ветвиdefault_p:

    rule<> rule_overall =
            switch_p
            [
                case_p<'a'>(parser_a),
                case_p<'b'>(parser_b),
                // ...
                case_p<'n'>(parser_n),
                default_p(parser_default)
            ]
        ;

Эта форма выбирает парсерparser_default, если ни один из случаев не соответствует следующему символу из входного потока. Обратите внимание, что в конструкцию парсераможет быть добавлена только одна ветвьdefault_p.

Кроме того, можно опустить скобки и корпус из конструкцииdefault_p, и в этом случае не выполняется дополнительный парсер, а общая конструкцияswitch_pпросто возвращает соответствие на любой символ входного потока, который не соответствует ни одной из ветвейcase_p:

    rule<> rule_overall =
            switch_p
            [
                case_p<'a'>(parser_a),
                case_p<'b'>(parser_b),
                // ...
                case_p<'n'>(parser_n),
                default_p
            ]
        ;

Существует еще одна форма конструкции switch_p. Эта форма позволяет нам четко указать значение, которое будет использоваться для сопоставления с ветвямиcase_p:

    rule<> rule_overall =
            switch_p(cond)
            [
                case_p<'a'>(parser_a),
                case_p<'b'>(parser_b),
                // ...
                case_p<'n'>(parser_n)
            ]
        ;

гдеcondявляется парсером или нулевой функцией или функциональным объектом (функтором). Если это парсер, то его пробуют и используют его возвращаемое значение для сопоставления с ветвямиcase_p. Если это нулевая функция или функтор, то будет использоваться его обратное значение.

Обратите внимание, что во время его компиляции конструкцияswitch_pтрансформируется в реальное утверждение C++switch. Это делает процесс выполнения очень эффективным.

BOOST_SPIRIT_SWITCH_CASE_LIMIT

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

Пример:

// Define these before including switch.hpp
#define BOOST_SPIRIT_SWITCH_CASE_LIMIT 10




Статья The Switch Parser раздела может быть полезна для разработчиков на c++ и boost.




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.



:: Главная :: ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-05-20 07:03:36/0.0079910755157471/1