Функция привязки boost :: spirit, предоставляющая параметры как spirit: qi :: _ val

Существует необходимость в предоставлении значений из объекта типа boost :: option для объекта std :: pair. Как бы вы реализовали эту идею, используя другие ресурсы? Любой другой способ, чем это сделано ниже?

    struct aggr_pair_visitor : public ::boost::static_visitor
    {
    public:
        explicit aggr_pair_visitor( column_and_aggregate & pair_ ) : pair(pair_)
        {
        }
        void operator()(column_name_t const & column)
        {
            pair.first = column;
        }
        void operator()(unsigned const & faggr)
        {
            if ( faggr > static_cast(sql_faggregate::SUM) || faggr < static_cast(sql_faggregate::AVG) )
                throw std::runtime_error("Failed to parse aggregate type : Not valid integer");
            else pair.second = static_cast(faggr);
        }
    private:
        column_and_aggregate & pair;
    };
    void apply_col_and_aggr_visitor( column_and_aggregate & col_and_aggr_pair, ::boost::variant< column_name_t, unsigned > const & val )
    {
        aggr_pair_visitor pair_visitor( col_and_aggr_pair );
        ::boost::apply_visitor( pair_visitor, val ); // N.B.!!! Runtime execution of operator()!
    }
    spirit::qi::rule< iterator, column_and_aggregate(), ascii::space_type > agg_pair =
        quoted_string[::boost::bind( &apply_col_and_aggr_visitor, spirit::qi::_val, spirit::qi::_1 )]
        > ':'
        > spirit::int_[::boost::bind( &apply_col_and_aggr_visitor, spirit::qi::_val, spirit::qi::_1 )];
    spirit::qi::rule< iterator, column_and_aggregate_container(), ascii::space_type > aggregates_parser =
          '{'
        > agg_pair[phoenix::push_back(spirit::qi::_val, spirit::qi::_1)] % ',' // N.B.!!! list-redux technic
        > '}';
 sehe27 июн. 2013 г., 17:43
Я могу думать о дюжине других способов сделать это. Какой из них выбрать, зависит от того, где выбуду использовать это. Ты можешь ("пожалуйста") приведите соответствующую часть вашего синтаксического анализатора или, желательно, уменьшенный минимальный пример »грамматика» показывая только это? Без дополнительной информации яскажу, что вы хотите использоватьqi::attr для значений по умолчанию иqi::symbols для агрегатных типов. Еще один намек: не надоне использовать семантические действия, если вынеобходимость реализоватьгосударство и / илилогика (не для сохранения результата). Я'Я буду ждать дальнейшего ввода, прежде чем пытаться продемонстрировать какой-либо конкретный метод.

Ответы на вопрос(1)

Решение Вопроса

слияние адаптировать станд :: пара:

#include <boost fusion="" adapted="" std_pair.hpp="">
// Or:
#include <boost fusion="" adapted.hpp="">
</boost></boost>

Используя это, вся сложность исчезает, и нет необходимости во всем, что связано с вариантом. Позволять'Предполагают следующие типы:

typedef std::string column_name_t;

enum sql_faggregate
{
    SUM,
    // ....
    AVG,
};

typedef std::pair<column_name_t, sql_faggregate=""> column_and_aggregate;
typedef std::vector<column_and_aggregate> column_and_aggregate_container;
</column_and_aggregate></column_name_t,>

Простая грамматика будет:

template <typename it,="" typename="" skipper="qi::space_type">
    struct parser : qi::grammar<it, column_and_aggregate_container(),="" skipper="">
{
    parser() : parser::base_type(aggregates_parser)
    {
        using namespace qi;
        // using phx::bind; using phx::ref; using phx::val;

        quoted_string = lexeme [ "'" >> *~qi::char_("'") >> "'" ];
        faggr = int_;
        agg_pair = quoted_string > ':' > faggr;
        aggregates_parser = '{' > agg_pair % ',' > '}';
    }

  private:
    qi::rule<it, std::string(),="" qi::space_type="">           quoted_string;
    qi::rule<it, sql_faggregate(),="" qi::space_type="">        faggr;
    qi::rule<it, column_and_aggregate(),="" qi::space_type="">   agg_pair;
    qi::rule<it, column_and_aggregate_container(),="" qi::space_type=""> aggregates_parser;
};
</it,></it,></it,></it,></it,></typename>

Вы также можете добавить проверку ввода:

faggr %= int_ [ qi::_pass = (qi::_1 >=SUM and qi::_1<=AVG) ];

Заметка %= обеспечить распространение атрибутов.

Полная рабочая демонстрация

Код программы:

#include <boost fusion="" adapted="" std_pair.hpp="">
#include <boost spirit="" include="" qi.hpp="">
// #include <boost spirit="" include="" phoenix.hpp="">

namespace qi    = boost::spirit::qi;
namespace phx   = boost::phoenix;

typedef std::string column_name_t;

enum sql_faggregate
{
    SUM,
    // ....
    AVG,
};

typedef std::pair<column_name_t, sql_faggregate=""> column_and_aggregate;
typedef std::vector<column_and_aggregate> column_and_aggregate_container;

template <typename it,="" typename="" skipper="qi::space_type">
    struct parser : qi::grammar<it, column_and_aggregate_container(),="" skipper="">
{
    parser() : parser::base_type(aggregates_parser)
    {
        using namespace qi;
        // using phx::bind; using phx::ref; using phx::val;

        quoted_string = lexeme [ "'" >> *~qi::char_("'") >> "'" ];
        faggr = int_;
        agg_pair = quoted_string > ':' > faggr;
        aggregates_parser = '{' > agg_pair % ',' > '}';

        BOOST_SPIRIT_DEBUG_NODE(aggregates_parser);
    }

  private:
    qi::rule<it, std::string(),="" qi::space_type="">           quoted_string;
    qi::rule<it, sql_faggregate(),="" qi::space_type="">        faggr;
    qi::rule<it, column_and_aggregate(),="" qi::space_type="">           agg_pair;
    qi::rule<it, column_and_aggregate_container(),="" qi::space_type=""> aggregates_parser;
};

bool doParse(const std::string& input)
{
    typedef std::string::const_iterator It;
    auto f(begin(input)), l(end(input));

    parser<it, qi::space_type=""> p;
    column_and_aggregate_container data;

    try
    {
        bool ok = qi::phrase_parse(f,l,p,qi::space,data);
        if (ok)   
        {
            std::cout << "parse success\n";
            for (auto& pair : data)
                std::cout << "result: '" << pair.first << "' : " << (int) pair.second << "\n";
        }
        else      std::cerr << "parse failed: '" << std::string(f,l) << "'\n";

        if (f!=l) std::cerr << "trailing unparsed: '" << std::string(f,l) << "'\n";
        return ok;
    } catch(const qi::expectation_failure<it>& e)
    {
        std::string frag(e.first, e.last);
        std::cerr << e.what() << "'" << frag << "'\n";
    }

    return false;
}

int main()
{
    bool ok = doParse("{ 'column 1' : 1, 'column 2' : 0, 'column 3' : 1 }");
    return ok? 0 : 255;
}
</it></it,></it,></it,></it,></it,></it,></typename></column_and_aggregate></column_name_t,></boost></boost></boost>

Вывод на печать:

parse success
result: 'column 1' : 1
result: 'column 2' : 0
result: 'column 3' : 1

PS: Если вы хотите сделать то же самое в семантических действиях, вы 'Я бы хотел написать это так:

agg_pair = 
      quoted_string [ phx::bind(&column_and_aggregate::first, _val)  = _1 ]
    > ':'
    > faggr         [ phx::bind(&column_and_aggregate::second, _val) = _1 ];

Вы'Вы увидите, что вы можете просто вставить его в приведенный выше пример, и он будет работать точно так же. Для этой конкретной грамматики этопростоболее многословныйтак что я нене рекомендую это :)

 sehe27 июн. 2013 г., 18:43
PS. добавлено (показывает более простой подход Phoenix к назначению членам парынепосредственно изнутрисемантическое действие)
 programmist28 июн. 2013 г., 00:10
если бы вы сделали так, чтобы он поддерживал UTF-8, вы могли бы дать мне совет.
 programmist29 июн. 2013 г., 19:18
У вас есть тот же JSON-парсер, но компилируемый на VS2012?
 sehe01 июл. 2013 г., 00:31
@ user2496553 Просто наперед: я только что выдвинул версию JSON.hpp / JSON.cpp, которая нет использовать /wstringwchar_t и использует utf8 для внутреннего использования. Это может работать лучше в MSVC (потому что это больше не предполагает, чтоwchar_t быть 32 бита). Смотрите это здесьhttps://github.com/sehe/spirit-v2-json/tree/nowide
 programmist27 июн. 2013 г., 21:34
Если там'возможные строки UNICODE в подпарасерах на любом языке, как бы вы справились с ситуацией? постскриптум Пример, приведенный в первом посте, не компилируется, потому что _val и _1 имеют свои собственные типы.
 programmist27 июн. 2013 г., 23:05
Любой язык (итальянский, английский, китайский и т. Д.), Первый пост - мой пост.
 sehe27 июн. 2013 г., 22:26
@ user2496553 Я неТ понять. "на любом языке? Да. "первый пост "? Да. Конечно, код в моем ответе компилируется, я бы нет опубликовал это иначе. Возможно, вы можете уточнить, в чем вопрос, илипоиск информации о духе и Unicode (или жеВот)
 sehe27 июн. 2013 г., 23:08
@ user2496553 Хорошо :) Думаю, ссылки должны помочь вам начать. У меня также есть собственный демонстрационный JSON-анализатор на github, который поддерживает полный UTF-8 согласно спецификациям JSON:github.com/sehe/spirit-v2-json (см. напримерконтрольный пример 1)

Ваш ответ на вопрос