Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Помогите разобраться почему неработет парсер Spiri


Автор: Elfet 13.1.2010, 21:57
Приветствую!

Пожалуйста помогите разобраться почему не работает парсер Boost::Spirit (Classic)

Хочу отпарсить вот такой вот файл:
Цитата
(0 1223123)
(2 3231233)
(31 укукукучик)
.....


Пытаюсь обработать таким вот парсером:
Код

 if(parse(buffer,
                 // Parser Start

                 *( '(' >> 

                 int_p[push_back_a(blocks)] >> 

                 ~ch_p('x')  // Вот тут точно не знаю что должно стоять. Мне нужно принять всё что может быть. Даже возможно такую конструкцию: (0 tes(tr io 12 32))

                 >> ')' )

                 ,space_p

                 // Parser End
                 ).hit)


Но почему то выдаёт только номер первого блока.  smile 


Вот весь код примера:
Код

#include <QtCore/QCoreApplication>

#include <fstream>
#include <iostream>
#include <string>
#include <sstream>
using namespace std;

#include <boost/spirit/include/classic_core.hpp>
using namespace boost::spirit::classic;


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);


    ifstream ifs;
    ifs.open("_g.txt", std::ios::in);

    if(ifs.is_open())
    {
        char * buffer;
        int length;

        //узнаем размер файла, и выделяем память в строке
        ifs.seekg( 0, std::ios_base::end );
        length = ifs.tellg();
        ifs.seekg( 0, std::ios_base::beg );

        // выделяем память:
        buffer = new char [length];

        // читаем как блок:
        ifs.read(buffer,length);
        ifs.close();

        vector<int> blocks;

        if(parse(buffer,
                 // Parser Start

                 *( '(' >> int_p[push_back_a(blocks)] >> ~ch_p('x') >> ')' )

                 ,space_p

                 // Parser End
                 ).hit)
        {

            for(unsigned i = 0; i < blocks.size(); i++)
            {
                stringstream oss;
                oss << i;

                cout << "block: " << oss.str() << endl;
            }
        }
        else
        {
            cout << "Parse Error..." << endl;
        }

        delete[] buffer;
    }
    else
    {
        cout << "Open Error..." << endl;
    }

     cout << "All Done!" << endl;

    return a.exec();
}



Заранее спасибо! 

Автор: bsa 13.1.2010, 23:06
Попробуй так:
Код
if( parse(buffer,
           *( ch_p('(') >> int_p[push_back_a(blocks)] >> lexeme_d[+anychar_p >> ')']),
           space_p
          ).hit)

Автор: Elfet 14.1.2010, 00:25
bsa, всё равно находит только первый блок :(

Автор: bsa 14.1.2010, 12:46
А если так?
Код
if( parse(buffer,
           lexeme_d[*( ch_p('(') >> *space_p >> int_p[push_back_a(blocks)] >> +space_p >> +anychar_p >> ')')],
           space_p
          ).hit)

Автор: Elfet 14.1.2010, 14:15
Мне удалось разобрать немного при помощи вот такой вот конструкции:
Код

MyGrammar inner;

        if(parse(buffer,
                 // Parser Start

                 *( ch_p('(') >> int_p[push_back_a(blocks)] >> +inner >> ')' ) ,

                 space_p

                 // Parser End
                 ).hit)

Где MyGrammar:
Код

class MyGrammar : public grammar<MyGrammar> {
public:

    template<typename ScannerT> class definition {
    public:

        definition( const MyGrammar & self ) {

            word = +int_p;

            wordGroup = word | '(' >> *( word | wordGroup ) >> ')' ;
        }

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

    private:
        rule<ScannerT> wordGroup, word;
    };
};


Но странно то что если пробую писать так, то ничего не выходит:
Код

rule<> intlist, rounded;

        intlist = +int_p;
        rounded = intlist | '(' >> *( intlist | rounded ) >> ')' ;

        if(parse(buffer,
                 // Parser Start

                 *( ch_p('(') >> int_p[push_back_a(blocks)] >> +rounded >> ')' ) ,

                 space_p

                 // Parser End
                 ).hit)


 smile 

Можно ли как-нибудь записать то что обработала грамматика MyGrammar?  Типа этого:  int_p[push_back_a(blocks)]  ?

Автор: Elfet 14.1.2010, 14:53
smile 

И ещё странность: если заменить +int_p на block_body 
где rule<> block_body =  +int_p; тоже перестаёт работать. 

 smile 

Мне как-то нужно собрать всё вот это:
Цитата

(INT   что то ещё, включая цифры, знаки, пробелы, переносы строк, скобки "(", ")")
(INT   ...)
(INT   ...)
(INT   ...)
....


 smile

Добавлено через 3 минуты и 39 секунд
Ещё вопрос: а как можно поместить в строку всё что собрал +anychar_p[assign_a(str)] ?

Автор: kosmonaFFFt 17.1.2010, 13:38
Нужен именно spirit?
Может стоит посмотреть в сторону flex+byacc или flex+bison?

Автор: Elfet 17.1.2010, 17:14
kosmonaFFFt, ага, хотелось бы на бусте. В бусте ещё есть QI и Karama. Но я не нашёл документации по ним :(

Автор: zim22 17.1.2010, 18:44
Цитата(Elfet @  17.1.2010,  16:14 Найти цитируемый пост)
 В бусте ещё есть QI и Karama. Но я не нашёл документации по ним :(

http://www.boost.org/doc/libs/1_36_0/libs/spirit/doc/html/spirit/qi_and_karma.html
***
волшебные слова для гугла "boost karma qi"

Автор: Elfet 17.1.2010, 20:54
А на русском ничего гугл не выдаёт :(

Автор: zim22 17.1.2010, 22:06
Цитата(Elfet @  17.1.2010,  19:54 Найти цитируемый пост)
А на русском ничего гугл не выдаёт :(

ну уж извините. без английского никуда.

Автор: Elfet 18.1.2010, 00:26
zim22, ясно. Буду переводить smile

Автор: chaos 18.1.2010, 13:55
Elfet, по подробнее бы рассказали бы про файл исходный

Автор: chaos 18.1.2010, 14:13
я бы написал нечто подобное(не проверял, тк негде)
Код

element = '(' >> uint_ >> space >> +char_ >> ')';
paresr = element >> *(eol >> element);


далее добавил бы действия по добавлению "key-value" в map

Автор: bsa 18.1.2010, 16:26
chaos, пока не вышел C++0x (в частности, тип auto), твой вариант не очень рабочий...

Автор: Elfet 18.1.2010, 21:18
chaos, а какого типа должны быть element,paresr? rule<????>?

Автор: chaos 19.1.2010, 09:08
Цитата(Elfet @  18.1.2010,  18:18 Найти цитируемый пост)
а какого типа должны быть element,paresr?

к сожалению не знаю smile ибо Spirit 2.1 не пользовал, только предыдущие версии 

Добавлено @ 09:10
Цитата(bsa @ 18.1.2010,  13:26)
chaos, пока не вышел C++0x (в частности, тип auto), твой вариант не очень рабочий...

это вы про то что отсутствует тип у element & parser? 

ну это я так написал smile типо псевдокод smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)