Вы, вероятно, ищет атрибут контейнера настройки точек:
Для вашего типа, это будет выглядеть так:
namespace boost { namespace spirit { namespace traits {
template <typename T>
struct container_value<SimpleLinkList<T>, void> {
typedef T type;
};
template <typename T>
struct push_back_container<SimpleLinkList<T>, T, void> {
static bool call(SimpleLinkList<T>& c, T const& val) {
c.push_back(val);
return true;
}
};
}}}
Простая демонстрация (с использованием фиктивной реализации SimpleLinkList
):
struct AbstractDataType
{
int number;
SimpleLinkList<int> list1, list2;
};
BOOST_FUSION_ADAPT_STRUCT(AbstractDataType, (int, number)(SimpleLinkList<int>, list1)(SimpleLinkList<int>, list2))
template<typename Iterator>
struct parser_expression : qi::grammar<Iterator, AbstractDataType(), qi::space_type>
{
parser_expression() : parser_expression::base_type(start)
{
list = '[' >> -(qi::int_ % ',') >> ']';
start = qi::int_ >> list >> -list >> '=';
BOOST_SPIRIT_DEBUG_NODES((list)(start))
}
qi::rule<Iterator, AbstractDataType(), qi::space_type> start;
qi::rule<Iterator, SimpleLinkList<int>(), qi::space_type> list;
};
Примечания
- Я заменил
qi::char_
на (неявном) qi::lit
где это возможно, потому что вы на самом деле не хочет проанализировать знаки пунктуации в атрибуте (правильно?)
- Я использовал оператор парсера списка
%
вместо многословной альтернативы
- Я использовал синтаксический анализатор оператор
-
, чтобы сделать список элементов (необязательный позволяют нулевые элементы)
- Аналогично, используемого
list >> -list
, чтобы сделать второй список факультативно ALLtogether.
следующие testcases:
void test(const std::string input)
{
static const parser_expression<std::string::const_iterator> p;
AbstractDataType parsed;
auto f(input.begin()), l(input.end());
bool ok = qi::phrase_parse(f, l, p, qi::space, parsed);
if (ok)
std::cout << "Result: " << parsed.number << " " << parsed.list1 << parsed.list2 << "\n";
else
std::cout << "Parse failed\n";
if (f!=l)
std::cout << "Unparsed: '" << std::string(f,l) << "'\n";
}
int main()
{
test("1 [2, 3, 4] [5, 6] =");
test("2 [] [6, 7] =");
test("3 [4, 5, 6] [ ] =");
test("4 [5, 6, 7] =");
}
печати выход:
Result: 1 [2 3 4 ][5 6 ]
Result: 2 [][6 7 ]
Result: 3 [4 5 6 ][]
Result: 4 [5 6 7 ][]
Смотреть все интегрированы: http://ideone.com/odqhBz. Предотвращение ссылки:
// #define BOOST_SPIRIT_DEBUG
#include <boost/fusion/adapted.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
template <typename T> struct ChainLink;
template <typename T>
class SimpleLinkList {
public:
void push_back(T const& v) { /* todo */ _for_debug.push_back(v); }
std::list<int> _for_debug;
friend std::ostream& operator<<(std::ostream& os, SimpleLinkList const& list) {
os << "["; std::copy(list._for_debug.begin(), list._for_debug.end(), std::ostream_iterator<T>(os, " ")); return os << "]";
}
private:
ChainLink<T>* head;
};
namespace boost { namespace spirit { namespace traits {
template <typename T>
struct container_value<SimpleLinkList<T>, void> {
typedef T type;
};
template <typename T>
struct push_back_container<SimpleLinkList<T>, T, void> {
static bool call(SimpleLinkList<T>& c, T const& val) {
c.push_back(val);
return true;
}
};
}}}
struct AbstractDataType
{
int number;
SimpleLinkList<int> list1, list2;
};
BOOST_FUSION_ADAPT_STRUCT(AbstractDataType, (int, number)(SimpleLinkList<int>, list1)(SimpleLinkList<int>, list2))
template<typename Iterator>
struct parser_expression : qi::grammar<Iterator, AbstractDataType(), qi::space_type>
{
parser_expression() : parser_expression::base_type(start)
{
list = '[' >> -(qi::int_ % ',') >> ']';
start = qi::int_ >> list >> -list >> '=';
BOOST_SPIRIT_DEBUG_NODES((list)(start))
}
qi::rule<Iterator, AbstractDataType(), qi::space_type> start;
qi::rule<Iterator, SimpleLinkList<int>(), qi::space_type> list;
};
void test(const std::string input)
{
static const parser_expression<std::string::const_iterator> p;
AbstractDataType parsed;
auto f(input.begin()), l(input.end());
bool ok = qi::phrase_parse(f, l, p, qi::space, parsed);
if (ok)
std::cout << "Result: " << parsed.number << " " << parsed.list1 << parsed.list2 << "\n";
else
std::cout << "Parse failed\n";
if (f!=l)
std::cout << "Unparsed: '" << std::string(f,l) << "'\n";
}
int main()
{
test("1 [2, 3, 4] [5, 6] =");
test("2 [] [6, 7] =");
test("3 [4, 5, 6] [ ] =");
test("4 [5, 6, 7] =");
}
Да, ваше право, я не хочу разбирать знаки пунктуации. У меня есть только одна проблемы с компиляцией, он говорит /home/bilb/test.cpp: В функции «ничтожного тест (станд :: строка)»: /home/bilb/test.cpp:67:12: ошибка: ISO C++ запрещает объявление 'f' без типа [-fpermissive] Здесь вы используете ключевое слово 'auto'. Я не знаю этого, это автоматический парсер в духе, верно? Нужно ли мне включать что-то еще? – audric
Хорошо, нет, это не парсер синтаксиса auto_, а ключевое слово auto в C++ вообще. Я не понимаю, почему он не может определить хороший тип для этого, но замена auto на 'std :: string :: const_iterator' решила проблему. Большое спасибо! – audric
@ user1680951 Скорее всего, ваш компилятор отключил функции C++ 0x/C++ 11. Для gcc поставьте '-std = C++ 0x' /' -std = C++ 11' для включения. Cheers – sehe