madf: (Default)
[personal profile] madf
Довгими холодними зимовими вечорами займаюсь однією "шабашкою". І як я уже для себе завів, беру від шабашки не тільки гроші а і новий досвід. Цього разу вирішив зайняти себе вивченням Boost. А точніше Boost.Asio і Boost.Spirit.

Якщо з першою все зрозуміло, то з другою я маявся 2 тижні. Спочатку отримав загальні відомості вивчаючи tutorial, потім взяв готовий код ini-парсера осьо звідси і прикрутив його до проекту (як не педагогічно!). Все працює, все добре... тільки код для першої версії, а вивчаю я вже другу!
"Добре!", подумав я, "Візьму і перероблю код для Spirit 2. Як раз і навчусь чогось". І почалось! Мучав я його цілий тиждень. І так його крутив, і інакше. То з одного боку, то з іншого... Компілюється, зараза, по хвилині. Викидає полотна повідомлень про помилки, які навіть при детальному розборі нічого мені не кажуть. Намучився я з ним, плюнув, і написав парсер "з нуля". Треба було бачити мій подив коли він просто взяв... і запрацював! Без жодної помилки компіляції! Мабуть таки не дарма я стільки мучався :)
Враження від Spirit 2:

  • дуже-дуже-дуже повільно компілюється навіть найпростіший код;

  • помилки важкувато виявити, але і допустити, маючи досвід, майже неможливо;

  • для стороннього погляду замість коду - каша (правда потім починаєш бачити у ньому нормальну БНФ);

  • вражаючий приклад потужності мови (особливо з Boost.Phoenix і Boost.Fusion);

  • швидкість розробки і швидкість роботи;


Якщо комусь знадобиться - наводжу код парсера (граматика, мабуть, жахлива):


namespace qi = boost::spirit::qi;


typedef std::map<std::string, std::string> PairsType;
typedef std::map<std::string, PairsType> SectionsType;


template <typename Iterator>
struct IniGrammar
  : qi::grammar<Iterator, SectionsType()>
{
    IniGrammar()
      : IniGrammar::base_type(query)
    {
        query           = +(section | (comment >> eol) | (space >> eol));
        section         =  sectionHeader >> -sectionContent;
        sectionHeader   =  '[' >> space >> key >> space >> ']' >> eol;
        sectionContent  = +((line | comment | space) >> eol);
        comment         =  (qi::char_(';') | '#') >> *qi::print;
        line            =  space >> key >> space >> -('=' >> space >> value >> space);
        key             =  qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9");
        value           = +qi::print;
        space           = *qi::char_("\t ");
        eol             =  qi::lit("\r\n") | '\r' | '\n';
    }

    qi::rule<Iterator, SectionsType()> query;
    qi::rule<Iterator, std::pair<std::string, PairsType>()> section;
    qi::rule<Iterator, PairsType()> sectionContent;
    qi::rule<Iterator, std::pair<std::string, std::string>()> line;
    qi::rule<Iterator, std::string()> key, value, sectionHeader;
    qi::rule<Iterator> comment, space, eol;
};


Вживати для розбору ini-файлів, за смаком перевіривши розбір на повноту порівнянням ітераторів після розбору (ох і накаламбурив):


std::string::iterator begin = text.begin();
std::string::iterator end = text.end();

SectionsType data;
IniGrammar<std::string::iterator> parser;

bool result = qi::parse(begin, end, parser, data);


This account has disabled anonymous posting.
If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting

Profile

madf: (Default)
madf

April 2018

S M T W T F S
1234567
891011121314
15161718192021
22232425262728
2930     

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jun. 24th, 2025 01:59 am
Powered by Dreamwidth Studios