boost::spirit и структура
От: TimurSPB Интернет  
Дата: 13.05.09 17:39
Оценка:
Есть файл вида:

cmd1 10,20,15;cmd2 40 30 15;cmd3 2 1 15;

И массив структур вида:

typedef struct 
{
  int CmdID;
  int x;
  int y;
  int z;
} CMD;

typedef std::vector< CMD > Commands;




Как средствами spirit (!) заполнить Commands из такого файла?

В доках есть пример, который парсерит числа, разделенные запятыми в вектор:

    bool
    parse_numbers(char const* str, vector<double>& v)
    {
        return parse(str,

            //  Begin grammar
            (
                real_p[append(v)] >> *(',' >> real_p[append(v)])
            )
            ,
            //  End grammar

            space_p).full;
    }


Можно ли сделать что-то такое?

bool
    parse_numbers(char const* str, vector<CMD>& v) 
    {
        //...            
    }
Make flame.politics Great Again!
Re: boost::spirit и структура
От: jazzer Россия Skype: enerjazzer
Дата: 14.05.09 00:34
Оценка: 3 (2)
Здравствуйте, TimurSPB, Вы писали:

TSP>Есть файл вида:


TSP>cmd1 10,20,15;cmd2 40 30 15;cmd3 2 1 15;


TSP>И массив структур вида:


TSP>
TSP>typedef struct 
TSP>{
TSP>  int CmdID;
TSP>  int x;
TSP>  int y;
TSP>  int z;
TSP>} CMD;

TSP>typedef std::vector< CMD > Commands;
TSP>




TSP>Как средствами spirit (!) заполнить Commands из такого файла?


Я бы не извращался и сделал по-простому (пишу прямо в браузере, не компилировал):
CMD tmp;
// read "cmd1 10,20,15" and store in tmp
rule<> cmd = "cmd" >> uint_p[ assign_a(tmp.CmdID) ]
                   >> uint_p[ assign_a(tmp.x) ] >> ',' 
                   >> uint_p[ assign_a(tmp.y) ] >> ',' 
                   >> uint_p[ assign_a(tmp.z) ];
// read "cmd1;cmd2..." and put everything to Commands мусещк
rule<> commands = list_p( cmd[ push_back_a(Commands, tmp) ], ';' );

потом скорми
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: boost::spirit и структура
От: TimurSPB Интернет  
Дата: 14.05.09 09:07
Оценка:
Здравствуйте, jazzer, Вы писали:

J>потом скорми


Если сделать вот так:


bool parse_numbers(char const* str, vector< CMD >& v)
      {
        CMD tmp;
        // read "cmd1 10,20,15" and store in tmp
        rule<> cmd = "cmd" >> uint_p[ assign_a(tmp.CmdID) ]
        >> uint_p[ assign_a(tmp.x) ] >> ',' 
          >> uint_p[ assign_a(tmp.y) ] >> ',' 
          >> uint_p[ assign_a(tmp.z) ];

        // read "cmd1;cmd2..." and put everything to Commands
        rule<> commands = list_p( cmd[ push_back_a(Commands, tmp) ] >> ';');

          return parse(str, commands, space_p).full;
      }


То выдает загадочную ошибку:

Error 2 error C2664: 'boost::spirit::impl::abstract_parser<ScannerT,AttrT>::do_parse_virtual' : cannot convert parameter 1 from 'const scanner_t' to 'const boost::spirit::scanner<> &' \trunk_out\.packages\win32.vc8\rootsboost\include\boost\spirit\core\non_terminal\impl\rule.ipp 190

Во всей документации не найти тривиального считывания данных в структурку.
Make flame.politics Great Again!
Re[3]: boost::spirit и структура
От: jazzer Россия Skype: enerjazzer
Дата: 14.05.09 09:34
Оценка: 3 (1)
Здравствуйте, TimurSPB, Вы писали:

TSP>Здравствуйте, jazzer, Вы писали:


J>>потом скорми


TSP>Если сделать вот так:

TSP>То выдает загадочную ошибку:

TSP>Error 2 error C2664: 'boost::spirit::impl::abstract_parser<ScannerT,AttrT>::do_parse_virtual' : cannot convert parameter 1 from 'const scanner_t' to 'const boost::spirit::scanner<> &' \trunk_out\.packages\win32.vc8\rootsboost\include\boost\spirit\core\non_terminal\impl\rule.ipp 190


TSP>Во всей документации не найти тривиального считывания данных в структурку.


То, что я написал — это и есть способ.
Твоя ошибка мне ни о чем не говорит, разбирайся, попробуй тривиальные правила, типа считать все в одну строку.
Я не компилировал свой код.

Кстати, если у тебя всегда точка с запятой стоит после команды, то лист-парсер тут не нужен, можешь просто использовать плюсик
bool parse_numbers(char const* str, vector< CMD >& v)
      {
        CMD tmp;
        // read "cmd1 10,20,15" and store in tmp
        rule<> cmd = "cmd" >> uint_p[ assign_a(tmp.CmdID) ]
          >> uint_p[ assign_a(tmp.x) ] >> ',' 
          >> uint_p[ assign_a(tmp.y) ] >> ',' 
          >> uint_p[ assign_a(tmp.z) ] >> ';';

        // read "cmd1;cmd2;..." and put everything to Commands
        rule<> commands = +( cmd[ push_back_a(v, tmp) ] );

        return parse(str, commands, space_p).full;
      }

Еще раз — я не компилировал, пишу прямо в браузере.
Ошибки компиляции тебе придется побороть самому
Также я не уверен насчет space_p — не помню, чтоб я его явно указывал у себя...
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[3]: boost::spirit и структура
От: Аноним  
Дата: 14.05.09 09:42
Оценка: 3 (1)
TSP>Во всей документации не найти тривиального считывания данных в структурку.

Плохо ищите мне кажется
вот вам мой примерчег


#include <boost/spirit/include/classic.hpp>
#include <boost/spirit/include/classic_assign_actor.hpp>
#include <boost/spirit/include/classic_insert_at_actor.hpp>
#include <iostream>
#include <vector>
#include <boost/foreach.hpp>

using namespace BOOST_SPIRIT_CLASSIC_NS;

typedef struct {
    int m_id;
    std::string m_text;
    float m_value;
} my_struct_t;

typedef std::vector<my_struct_t> ms_array_t;

int main()
{
    my_struct_t ms;
    ms_array_t array;

    const std::string text = "1;Gopa1;2.50|2;Gopa2;2.59|3;Gopa3;2.54|4;Gopa4;2.56";

    rule<> my_rule = int_p[assign_a(ms.m_id)] >> ch_p(";") >>
            (+(~ch_p(";")))[assign_a(ms.m_text)] >> ch_p(";") >> real_p[assign_a(ms.m_value)];

    rule<> my_rule2 = my_rule[push_back_a(array, ms)];

    rule<> my_rule3 = my_rule2 >> *(ch_p("|") >> my_rule2);

    if (parse(text.c_str(), my_rule3).full) {
        BOOST_FOREACH(my_struct_t ms_, array) {
            std::cout << "Id " << ms_.m_id << std::endl;
            std::cout << "Text " << ms_.m_text << std::endl;
            std::cout << "Value " << ms_.m_value << std::endl;
        }
    }

    return 0;
}
Re[4]: boost::spirit и структура
От: TimurSPB Интернет  
Дата: 14.05.09 11:41
Оценка:
Спасибо jazzer и Аноним =)
Вроде пришло мне просвлетние!
Make flame.politics Great Again!
Re[5]: boost::spirit и структура
От: jazzer Россия Skype: enerjazzer
Дата: 14.05.09 11:56
Оценка: 2 (1)
Здравствуйте, TimurSPB, Вы писали:

TSP>Спасибо jazzer и Аноним =)

TSP>Вроде пришло мне просвлетние!

для спасибо кнопки есть специальные
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[6]: boost::spirit и структура
От: TimurSPB Интернет  
Дата: 14.05.09 14:10
Оценка:
Снова возник вопрос:

Например:
 uint_parser< unsigned, 10, n, n > uint_n_p;

выделяет РОВНО n цифр для преобразования в число
Как сделать что типа:
str_parser< n > str_n_p;
т. е. описать парсер, который выделяет равно n символов?
Make flame.politics Great Again!
Re[7]: boost::spirit и структура
От: jazzer Россия Skype: enerjazzer
Дата: 14.05.09 15:19
Оценка:
Здравствуйте, TimurSPB, Вы писали:

TSP>т. е. описать парсер, который выделяет равно n символов?



lexeme_d[ repeat_p(n)[ anychar_p ] ]
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[6]: boost::spirit и структура
От: denis_k0  
Дата: 15.05.09 06:16
Оценка: 1 (1)
Здравствуйте, jazzer, Вы писали:

J>Здравствуйте, TimurSPB, Вы писали:


TSP>>Спасибо jazzer и Аноним =)


не за что

ЗЫ Зарегался
Re: boost::spirit и структура
От: Аноним  
Дата: 28.05.09 11:57
Оценка:
Те примеры, которые приведены не очень хорошо работают (точнее не работают) при разборе больших грамматик. Скорее всего Вам прийдётся обявлять свои грамматики, которые отвечают за какое-либо подмножество грамматики.
В общем, способ такой:

struct SMyStruct
{
long _n1;
long _n2;
}
struct SClosureMy : boost::spirit::closure<Sxxx , SMyStruct>
{
member1 sResult;
};

struct CGrammMy: grammar<CGrammMy, SClosureMy ::context_t>
{
template <typename ScannerT>
struct definition
{
definition(CGrammMyconst& self)
{
xxx = uint_p [bind(&SMyStruct::_n1)(self.sResult) = arg1]
>> space_p
>> uint_p [bind(&SMyStruct::_n2)(self.sResult) = arg1]
>> space_p
>> eps_p [/*какие-либо действия по сохранению данных*/];
BOOST_SPIRIT_DEBUG_RULE(xxx );
}

rule<ScannerT> const& start() const { return xxx; }
rule<ScannerT> xxx;
}
}

Сохранить результат м
Вот из такого рода элементов можно уже состряпать сколь угодно сложную грамматику (я си-подобный синтаксис парсил, чтобы вытащить все определения типов и переменных).
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.