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

In-depth: The Parser Context

Boost , ,

In-depth: The Parser Context

Overview

Контекст парсераявляется еще одной концепцией. Пример (объект) классаконтекстсоздается до начала нетерминального анализа и разрушается после завершения анализа. Нетерминал — это либо правило, либо подправило, либо грамматика. Нетерминалы имеютКонтекстПараметр шаблона. Следующий псевдокод показывает, что происходит, когда используется нетерминал:

    return_type
    a_non_terminal::parse(ScannerT const& scan)
    {
        context_t ctx(/**/);
        ctx.pre_parse(/**/);
        //  main parse code of the non-terminal here...
        return ctx.post_parse(/**/);
    }

Контекст предусмотрен для расширения. Его основная цель состоит в том, чтобы выявить начало и конец функции нетерминала для размещения внешних крючков. Мы можем расширить нетерминал множеством способов, написав специализированные классы контекста, не изменяя сам класс. Например, мы можем сделать информацию о нетерминальном излучении отладкой диагностики, написав класс контекста, который распечатывает текущее состояние сканера в каждой точке прохождения разбора, где нетерминал вызывается.

Пример парсерного контекста, который распечатывает информацию отладки:

    pre_parse:      non-terminal XXX is entered. The current state of the input
                    is "hello world, this is a test"
    post_parse:     non-terminal XXX has concluded, the non-terminal matched "hello world".
                    The current state of the input is ", this is a test"

В большинстве случаев контекст будет невидимым с точки зрения пользователя. В общем, клиентам фреймворка не нужно иметь дело напрямую или даже знать о контекстах. Однако опытные пользователи могут найти некоторое применение контекстам. Это часть публичного API. Другие части структуры в других слоях над ядром используют контекст для расширения нетерминалов.

Class declaration

Классparser_contextявляется классом контекста по умолчанию, который используется нетерминалом.

    template <typename AttrT = nil_t>
struct
parser_context { typedef AttrT attr_t; typedef implementation_defined base_t; typedef parser_context_linker<parser_context<AttrT> > context_linker_t; template <typename ParserT> parser_context(ParserT const& p) {} template <typename ParserT, typename ScannerT> void pre_parse(ParserT const& p, ScannerT const& scan) {} template <typename ResultT, typename ParserT, typename ScannerT> ResultT& post_parse(ResultT& hit, ParserT const& p, ScannerT const& scan) { return hit; } };

Параметр шаблона non-terminalContextTявляется концепцией. Классparser_contextвыше является простейшей моделью этого понятия. Функции по умолчаниюparser_context'spre_parseиpost_parseявляются просто не-ops. Вы можете думать о шаблонном параметре нетерминалаContextTкак о политике, которая определяет, как нетерминал будет вести себя до и после анализа. Клиент может предоставить свою собственную политику контекста, передав параметр шаблона контекста, определенный пользователем, определенному нетерминалу.

Parser Context Policies
attr_t typedef: the attribute type of the non-terminal. See the match.
base_t typedef: the base class of the non-terminal. The non-terminal inherits from this class.
context_linker_t typedef: this class type opens up the possibility for Spirit to plug in additional functionality into the non-terminal parse function or even bypass the given context. This should simply be typedefed to parser_context_linker<T> where T is the type of the user defined context class.
constructor Construct the context. The non-terminal is passed as an argument to the constructor.
pre_parse Do something prior to parsing. The non-terminal and the current scanner are passed as arguments.
post_parse Do something after parsing. This is called regardless of the parse result. A reference to the parser's result is passed in. The context has the power to modify this. The non-terminal and the current scanner are also passed as arguments.

Базазаслуживает дальнейшего объяснения. Вот идет... Контекст - это строго стек-класс. Он создается до разбора и разрушается после выхода функции неконцевого члена. Иногда нам нужны вспомогательные данные, которые существуют на протяжении всего срока службы нетерминального хоста. Поскольку нетерминал наследует от контекстаbase_t, сам контекст при создании получает доступ к этому при строительстве, когда нетерминал передается в качестве аргумента конструктору.и.

Нетерминал наследует от контекстаbase_ttypedef. Единственным требованием является то, что это класс, который по умолчанию можно построить. Требования к копированию и назначению зависят от хоста. Если хост требует этого, то и контекстbase_t. В общем, не помешало бы обеспечить эти базовые требования.

Non-default Attribute Type

Прямо из коробки классparser_contextможет быть параматерирован с типом, отличным от по умолчаниюnil_t. Следующий код демонстрирует использование шаблонаparser_contextс явным аргументом для объявления правил с результатами соответствия, отличными отnil_t:

    rule<parser_context<int> > int_rule = int_p;
    parse(
        "123",
        // Using a returned value in the semantic action
        int_rule[cout << arg1 << endl] 
    ); 

В этом примереint_ruleобъявляется сintатрибутным типом. Следовательно, переменнаяint_ruleможет содержать любой парсер, который возвращает значениеint(например,int_pилиbin_p). Важно отметить, что мы можем использовать возвращенное значение в семантическом действии, связанном сint_rule.

См.parser_context.cppв примерах. Это часть духовного распределения.

An Example

В качестве примера давайте посмотрим на контекст парсера Spirit, который вставляет некоторый вывод отладки в процесс парсинга:

    template<typename ContextT>
    struct parser_context_linker : public ContextT
    {
        typedef ContextT base_t;
        template <typename ParserT>
        parser_context_linker(ParserT const& p)
        : ContextT(p) {}
        
    // This is called just before parsing of this non-terminal
        template <typename ParserT, typename ScannerT>
        void pre_parse(ParserT const& p, ScannerT &scan)
        {
        // call the pre_parse function of the base class
            this->base_t::pre_parse(p, scan);

#if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
            if (trace_parser(p.derived())) {
            // print out pre parse info
                impl::print_node_info(
                false, scan.get_level(), false,
                parser_name(p.derived()),
                scan.first, scan.last);
            }
            scan.get_level()++;  // increase nesting level
#endif 
        }
    // This is called just after parsing of the current non-terminal
        template <typename ResultT, typename ParserT, typename ScannerT>
        ResultT& post_parse(
            ResultT& hit, ParserT const& p, ScannerT& scan)
        {

#if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
            --scan.get_level();  // decrease nesting level
            if (trace_parser(p.derived())) {
                impl::print_node_info(
                    hit, scan.get_level(), true,
                    parser_name(p.derived()),
                    scan.first, scan.last);
            }
#endif
        // call the post_parse function of the base class
            return this->base_t::post_parse(hit, p, scan);
        }
    };

При отладкеBOOST_SPIRIT_DEBUGэтот парсерный контекст вводится в производную иерархию текущегоparser_context, который первоначально был указан для использования для конкретного парсера, поэтому параметр шаблонаContextTпредставляет исходныйparser_context. По этой причине функцииpre_parseиpost_parseназывают его аналогами из базового класса. Кроме того, эти функции называют специальной функциейprint_node_info, которая выполняет фактический вывод информации о состоянии парсера текущего нетерминала. Для получения дополнительной информации о печатной информации, вы можете захотеть взглянуть на темуОтладка.



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




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



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


реклама


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

Время компиляции файла: 2024-08-30 11:47:00
2025-05-20 05:10:58/0.0067710876464844/1