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

Employee - Parsing into structs

Boost , Spirit 2.5.2 , Tutorials

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

Это общий вопрос в спискеSpirit General List.: Как мне разобрать и поместить результаты в структуру C++? Конечно, на данный момент вы уже знаете различные способы сделать это, используя семантические действия. Есть много способов снять кожу с кошки. Spirit2, будучи полностью приписанным, делает его еще проще. Следующий пример демонстрирует некоторые особенности Spirit2, которые делают это легко. В процессе вы узнаете о:

  • Больше об атрибутах
  • Правила авто
  • Несколько встроенных парсеров
  • Директивы

Во-первых, давайте создадим структуру, представляющую сотрудника:

struct employee
{
    int age;
    std::string surname;
    std::string forename;
    double salary;
};

Затем мы должны рассказатьBoost.Fusionо структуре нашего сотрудника, чтобы сделать его первоклассным гражданином слияния, который может использовать грамматика. Если вы еще не знаете синтеза, это библиотекаBoostдля работы с разнородными коллекциями данных, обычно называемыми кортежами. Spirit широко использует слияние как часть своей инфраструктуры.

По мнению Фьюжна, структура — это просто форма кортежа. Вы можете адаптировать любую конструкцию, чтобы полностью соответствовать термоядерному кортежу:

BOOST_FUSION_ADAPT_STRUCT(
    client::employee,
    (int, age)
    (std::string, surname)
    (std::string, forename)
    (double, salary)
)

Теперь мы напишем парсер для нашего сотрудника. Входы будут иметь форму:

employee{ age, "surname", "forename", salary }

Вот так:

template <typename Iterator>
struct employee_parser : qi::grammar<Iterator, employee(), ascii::space_type>
{
    employee_parser() : employee_parser::base_type(start)
    {
        using qi::int_;
        using qi::lit;
        using qi::double_;
        using qi::lexeme;
        using ascii::char_;
        quoted_string %= lexeme['"' >> +(char_ - '"') >> '"'];
        start %=
            lit("employee")
            >> '{'
            >>  int_ >> ','
            >>  quoted_string >> ','
            >>  quoted_string >> ','
            >>  double_
            >>  '}'
            ;
    }
    qi::rule<Iterator, std::string(), ascii::space_type> quoted_string;
    qi::rule<Iterator, employee(), ascii::space_type> start;
};

The full cpp file for this example can be found here: ../../example/qi/employee.cpp

Давайте пройдем этот шаг за раз (не обязательно сверху вниз).

template <typename Iterator>
struct employee_parser : grammar<Iterator, employee(), space_type>

<employee_parser>является грамматикой. Как и раньше, мы делаем его шаблоном, чтобы мы могли повторно использовать его для различных типов итераторов. Подпись грамматики:

employee()

Это означает, что парсер генерирует структуры сотрудников.<employee_parser>пропускает белые пространства, используя<space_type>в качестве парсера пропуска.

employee_parser() : employee_parser::base_type(start)

Инициирует базовый класс.

rule<Iterator, std::string(), space_type> quoted_string;
rule<Iterator, employee(), space_type> start;

Объявляют два правила:<quoted_string>и<start>.<start>имеет те же шаблонные параметры, что и сама грамматика.<quoted_string>имеет<std::string>атрибут.

Lexeme
lexeme['"' >> +(char_ - '"') >> '"'];

<lexeme>препятствует пропуску пространства из открытой скобы в закрывающую скобу. Выражение parses цитирует строки.

+(char_ - '"')

Разбирает один или несколько заклинаний, кроме двойной цитаты. Он останавливается, когда видит двойную цитату.

Difference

Выражение:

a - b

<a>, но не<b>. Его атрибут — всего лишь<A>; атрибут<a>.<b>атрибут игнорируется. Следовательно, атрибут:

char_ - '"'

Это всего лишь<char>.

Plus
+a

Он похож на звезду Клин. Вместо того, чтобы соответствовать всему,<+a>соответствует одному или нескольким. Как и связанная с ней функция, звезда Клин, ее атрибут —<std::vector<A>>, где<A>— атрибут<a>. Собрав воедино все эти атрибуты,

+(char_ - '"')

Тогда:

std::vector<char>
Sequence Attribute

Что является атрибутом

'"' >> +(char_ - '"') >> '"'

?

Ну, как правило, атрибут:

a >> b >> c

Это:

fusion::vector<A, B, C>

<A>является атрибутом<a>,<B>является атрибутом<b>и<C>является атрибутом<c>. Что это такое<fusion::vector>?

[Note]Note

Если вы не знаете, о чем я говорю, см.Фьюжн вектор. Это может быть хорошей идеей, чтобы посмотреть наBoost.Fusionна данный момент. Вы определенно увидите больше на следующих страницах.

Attribute Collapsing

Некоторые парсеры, особенно те очень маленькие буквальные парсеры, которые вы видите, как<'"'>, не имеют атрибутов.

Узлы без атрибутов игнорируются. В последовательности, как и выше, все узлы без атрибутов отфильтровываются из<fusion::vector>. Так как<'"'>не имеет атрибута, а<+(char_ -'"')>имеет<std::vector<char>>атрибут, то весь атрибут выражения должен был быть:

fusion::vector<std::vector<char> >

Но подождите, есть еще одно рушащееся правило: Если за атрибутом следует один элемент<fusion::vector>, элемент снимается голым с его контейнера. Чтобы сделать длинный рассказ коротким, атрибут выражения:

'"' >> +(char_ - '"') >> '"'

Это:

std::vector<char>
Auto Rules

Типично видеть такие правила, как:

r = p[_val = _1];

Если у вас есть определение правила, такое как выше, где атрибут RHS (правая сторона) правила совместим с атрибутом LHS (левая сторона руки), то вы можете переписать его как:

r %= p;

Атрибут<p>автоматически использует атрибут<r>.

Возвращаясь к нашему правилу<quoted_string>:

quoted_string %= lexeme['"' >> +(char_ - '"') >> '"'];

Это упрощенная версия:

quoted_string = lexeme['"' >> +(char_ - '"') >> '"'][_val = _1];

Атрибут правила<quoted_string>:<std::string>совместимс атрибутом RHS:<std::vector<char>>. RHS извлекает парсированный атрибут непосредственно в атрибут правила in-situ.

[Note]Note

<r%= p>и<r =p>эквивалентны, если нет семантических действий, связанных с<p>.

Finally

Мы придерживаемся одного правила, правила старта:

start %=
    lit("employee")
    >> '{'
    >>  int_ >> ','
    >>  quoted_string >> ','
    >>  quoted_string >> ','
    >>  double_
    >>  '}'
    ;

Применяя наши разрушающиеся правила выше, RHS имеет атрибут:

fusion::vector<int, std::string, std::string, double>

Эти узлы не имеют атрибута:

  • <lit("employee")>
  • <'{'>
  • <','>
  • <'}'>
[Note]Note

Если вам интересно,<lit("employee")>это то же самое, что «работник». Мы должны были завернуть его внутрь<lit>, потому что сразу после этого<>> '{'>. Вы не можете правильно изменить a<char[]>и a<char>- вы знаете, правила синтаксиса C++.

Напоминаем, что атрибутом<start>является<employee>структура:

struct employee
{
    int age;
    std::string surname;
    std::string forename;
    double salary;
};

Теперь все ясно, верно?<struct employee>совместим с<fusion::vector<int,std::string,std::string,double>>. Таким образом, RHS<start>использует атрибут старта<struct employee>in-situ, когда он выполняет свою работу.


PrevUpHomeNext

Статья Employee - Parsing into structs раздела Spirit 2.5.2 Tutorials может быть полезна для разработчиков на c++ и boost.




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



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


реклама


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

Время компиляции файла: 2024-08-30 11:47:00
2025-05-19 21:40:48/0.010992050170898/1