2013-06-11 2 views
4

У меня есть проблемы с повышающим духом, чтобы разобрать файл так:подталкивания духа разбор целое для пользовательского шаблона списка

int  [int, int, int] [ int, int] 

... 

Ничего действительно трудно, следующая грамматика работает для этого:

template<typename Iterator> 
struct parser_expression : qi::grammar<Iterator,ascii::space_type> 
{ 
    parser_expression() : parser_expression::base_type(start) { 
     using qi::double_; 
     using qi::int_; 
     using boost::spirit::qi::char_; 
     using qi::alpha; 
     using qi::alnum; 
     using qi::digit; 
     using qi::eps; 
     using qi::_val; 
     using boost::phoenix::bind; 

     start = int_ >> list1 >> list2 >> char_('='); 

     list1 = ('[' >> int_ >> *(char_(',') >> int_) >> char_(']')) | (char_('[') >> char_(']')); 
     list2 = ('[' >> int_ >> *(char_(',') >> int_) >> char_(']')) | -(char_('[') >> char_(']')); 
    } 



    qi::rule<Iterator,ascii::space_type> start; 

    qi::rule<Iterator,ascii::space_type> list1; 
    qi::rule<Iterator,ascii::space_type> list2; 
}; 

Моих проблема в том, что мне нужно сохранить результат разбора. Например, мне нужно сохранить list1 и List2 ИНТ в шаблон пользовательского списка:

template <typename T> 
class SimpleLinkList { 
private: 
    ChainLink<T>* head; 

... 
} 

где ограда является:

template<typename T> 
class ChainLink { 
private: 
    T object; 
    ChainLink* next; 
... 
} 

У меня есть метод теряемое в SimpleLinkList так же, как вектор, но я не понимаю, как разбирать int, сохранять его в ChainLink и добавлять его в SimpleLinkList.

Я уже видел, как адаптировать структуру шаблона к последовательности слияния в http://boost-spirit.com/home/2010/02/08/how-to-adapt-templates-as-a-fusion-sequence/.

Мне нужен пользовательский LinkList, чтобы иметь возможность удалять и добавлять элементы во время цикла.

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

Thx для вашей помощи.

ответ

2

Вы, вероятно, ищет атрибут контейнера настройки точек:

Для вашего типа, это будет выглядеть так:

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]  ="); 
} 
+0

Да, ваше право, я не хочу разбирать знаки пунктуации. У меня есть только одна проблемы с компиляцией, он говорит /home/bilb/test.cpp: В функции «ничтожного тест (станд :: строка)»: /home/bilb/test.cpp:67:12: ошибка: ISO C++ запрещает объявление 'f' без типа [-fpermissive] Здесь вы используете ключевое слово 'auto'. Я не знаю этого, это автоматический парсер в духе, верно? Нужно ли мне включать что-то еще? – audric

+0

Хорошо, нет, это не парсер синтаксиса auto_, а ключевое слово auto в C++ вообще. Я не понимаю, почему он не может определить хороший тип для этого, но замена auto на 'std :: string :: const_iterator' решила проблему. Большое спасибо! – audric

+0

@ user1680951 Скорее всего, ваш компилятор отключил функции C++ 0x/C++ 11. Для gcc поставьте '-std = C++ 0x' /' -std = C++ 11' для включения. Cheers – sehe

 Смежные вопросы

  • Нет связанных вопросов^_^