Форум программистов, компьютерный форум, киберфорум
Наши страницы
Boost C++
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.60/5: Рейтинг темы: голосов - 5, средняя оценка - 4.60
billz
0 / 0 / 0
Регистрация: 14.09.2014
Сообщений: 2
1

Boost::Spirit. Разбор конфигурационного файла

14.09.2014, 16:16. Просмотров 835. Ответов 1
Метки нет (Все метки)

Есть конфигурационный файл, содержащий текстовое описание данных.
Каждая запись конфигурационного файла состоит из полей.

Формальное описание:

поле ::= простое_поле | структурное_поле | список

простое_поле ::= -ключ значение (пример: -LENGTH 300 или -VISIBILE "show"|"hide")

значение ::= {любой символ} (все символы, включая пробел, дефис и перевод на новую строку)

структурное поле ::= -ключ поле1 ... полеN (пример: -DATETIME -DAY 20140101 -TIME 120000)

список ::= -BEGIN ключ поле1 .. полеN -END ключ
Пример списка:

-BEGIN POLYGON -COLOR "red"|"green" -POINT -POSX 100 -POSZ 300 -POSY 100 -POINT -POSX 200 -POSY 200 -END POLIGON

Пробел или перевод на новую строку может быть в любом месте записи:

-
DATETIME - DAY 20140101 -TIME
120000

Структурные поля имеют произвольный порядок следования, не все поля могут присутствовать, например:

-DATETIME -TIME 120000 -DAY 20140101 или
-DATETIME -DAY 20140101

Внутри списка последовательность полей имеет семантическую значимость, то есть первая точка имеет
координаты -POSX 100 -POSY 100 -POSZ 300, а вторая -POSX 200 -POSY 200.

Каждая запись имеет обязательный ключ (TYPE), который определяет возможные поля, которые могут присутствовать,
например:

-TYPE POINT -COLOR RGB(0,200,100) -NAME 'name' -POSY 100 -POSX 200
-TYPE LINE -NAME 'name' -BEGIN POINTS -POSX 200 -POSY 200 -POSX 400 -POSY 400 -END POINTS -COLOR "blue"
-TYPE CIRCLE -CENTER -POSZ 400. -POSX 300. -COLOR "yellow" -NAME 'name'
При встрече неизвестного обязательно ключа или неизвестного ключа в простом или структурном поле
надо пропускать все последующие символы до следующего известного "-ключ значение".

При встрече неизвестного ключа внутри списка надо пропустить все символы, включая -END ключ.


Подскажите пожалуйста шаблон разбора подобных файлов с помощью Boost::Spirit.

Добавлено через 10 часов 44 минуты
Вопрос попроще.

Пытаюсь адаптировать под свои нужды boost/libs/spirit/repository/example/qi/keywords.cpp

В нем из заданной строки формируется структура:

C++
1
2
3
4
5
6
7
struct person {
    std::string name;
    int age;
    double size;
};
 
person Bill;
Вместо приведенного в примере правила разбора:

C++
1
2
3
4
5
       no_constraint_person_rule %=
            kwd("name")['=' > parse_string ]
          / kwd("age")   ['=' > int_]
          / kwd("size")   ['=' > double_ > 'm']
          ;
пишу свой вариант:

C++
1
2
3
4
5
        my_constraint_person_rule %=
            kwd("-name")[my_parse_string ]
          / kwd("-age")   [int_]
          / kwd("-size")   [double_]
          ;
Как видно, в названии параметров я добавил дефис, убрал ненужный мне
знак равенства и в параметре size удалил окончание 'm'.

Кроме того, разбор строки

C++
1
         parse_string   %= '"'> *(char_-'"') > '"';

заменил на свой вариант

C++
1
         my_parse_string   %= +(char_-' ');
То есть, мои строки не находятся в кавычках и нужен хотя бы один символ.

Вызываю разбор строки:

C++
1
2
3
4
5
6
7
8
        Bill.name = "";
        Bill.age = -1;
        Bill.size = -1.;
 
        test_phrase_parser_attr(
                         "-age 1 -size 2.3 -name Bill"
                        ,my_constraint_person_rule
                        ,Bill);
Все в порядке: согласно примеру выводится строка:
Person : Bill, 1, 2.3
Пробую переставить параметры местами:

C++
1
2
3
4
        test_phrase_parser_attr(
                         "-size 2.3 -age 1 -name Bill"
                        ,my_constraint_person_rule
                        ,Bill);
Как и в первом случае, получаю правильные значения.

А вот если ставлю на первое место параметр name, то происходит ошибка:

C++
1
2
3
4
        test_phrase_parser_attr(
                         "-name Bill -age 1 -size 2.3"
                        ,my_constraint_person_rule
                        ,Bill);
Person : Bill-age1-size2.3, -1, -1
То есть разбор правильно нашел имя первого параметра (name), стал искать значение имени,
но не остановился на первом пробеле, а прошел до конца строки. В результате другие параметры
не получили значений.

Пробую в качестве ограничителя имени поставить символ 'l':

C++
1
         my_parse_string   %= +(char_-'l');
Результат:

Person : Bi, -1, -1

По идее все правильно: разбор имени закончился как только встретился первый символ 'l',
а остальные параметры не разобраны, потому что встретился второй символ 'l'.

Меняю вызов:

C++
1
2
3
4
        test_phrase_parser_attr(
                         "-name Bil -age 1 -size 2.3"
                        ,my_constraint_person_rule
                        ,Bill);
и ожидаю, что строка будет разобрана до конца.

Не тут-то было, результат аналогичен предыдущему:

Person : Bi, -1, -1
Если пропустить "символ окончания строки":

C++
1
2
3
4
5
        my_constraint_person_rule %=
            kwd("-name")[my_parse_string > 'l']
          / kwd("-age")   [int_]
          / kwd("-size")   [double_]
          ;
то все разбирается правильно:

Person : Bi, 1, 2.3

Но у меня-то параметры разделяет пробел, а не 'l'.

--------

Собственно вопрос один: где я напутал в правиле разбора строки {my_parse_string %= +(char_-' ')} ?

Чувствую, что ответ простой, но я - новичок и похоже еще не знаю самых элементарных вещей.


Если это имеет значение, использую Boost 1.56.0, Mingw 4.6. Пробовал Mingw 4.8: при компиляции выдал
кучу предупреждений, при выполнении выдал ошибку, но самое существенное я успел углядеть - пробел
в правиле разбора строки так же не воспринимается.
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
14.09.2014, 16:16
Ответы с готовыми решениями:

Метапрограммирование в boost::proto (boost::spirit)
В библиотеке boost:: proto есть такой код calculator<proto::terminal<placeholder<0> >::type>...

boost::spirit
Пишу парсер на спирите. Задаюсь вопросом как нормально сделать примерно такое lexeme Где...

Производительность boost::spirit::qi
#include <iostream> #include <sstream> #include <chrono> #include...

Boost начало работы: Undefined reference to `boost::system::generic_category() '
Добрый день Собственно говоря возникла необходимость использовать boost в работе. Поставил так: ...

Boost Log - undefined reference to `boost::system::system_category()'
Пытаюсь скомпилировать код из примеров Boost Log:#include <boost/log/trivial.hpp> int main(int,...

1
billz
0 / 0 / 0
Регистрация: 14.09.2014
Сообщений: 2
17.09.2014, 05:57  [ТС] 2
Переход на нанотехнологии не состоялся. Вернулся к сохе и топору.
Применение пары вложенных хэш-таблиц решило все проблемы.
Вопрос закрыт. Всем спасибо.
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
17.09.2014, 05:57

Узнать о переименовании файла (boost::filesystem)
Всем хорошего времени :) У меня есть процесс, который мониторит папку. если там какой-то файл...

Использование boost и boost.build с несколькими компиляторами
Здравствуйте! Собрал библиотеку boost и boost.build для двух компиляторов: MinGW 4.5.2 и Visual...

Boost Asio Передача файла от клиента к клиенту
Есть у кого нибудь реализация сервера-передатчика для передачи файлов от клиента к клиенту?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
2
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru