Форум программистов, компьютерный форум, киберфорум
Boost C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.75/8: Рейтинг темы: голосов - 8, средняя оценка - 4.75
0 / 0 / 0
Регистрация: 14.09.2014
Сообщений: 3

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

14.09.2014, 16:16. Показов 1690. Ответов 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
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
14.09.2014, 16:16
Ответы с готовыми решениями:

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

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

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

1
0 / 0 / 0
Регистрация: 14.09.2014
Сообщений: 3
17.09.2014, 05:57  [ТС]
Переход на нанотехнологии не состоялся. Вернулся к сохе и топору.
Применение пары вложенных хэш-таблиц решило все проблемы.
Вопрос закрыт. Всем спасибо.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
17.09.2014, 05:57
Помогаю со студенческими работами здесь

Чтение и сохранение данных из конфигурационного файла
Привет всем!! Есть программа на C с конфигурационным файлом!!! Надо сделать так чтобы при старте программы конфиг файл читался один раз,...

Размер конфигурационного файла MD
Резко вырос размер конфигурационного файла, примерно в 10 раз. Добавлен отчет и изменен документ. При открытии блокнотом, появилось много...

Создание конфигурационного файла
Добрый день, форумчане! Такая проблема: надо создать свой конфигурационный файл для задания в нем имени сервера и номера порта для...

Защита конфигурационного файла
Есть файл config.php в котором содержатся реквизиты к mysql. К нему закрыт доступ "извне" через .htaccess. Как можно закрыть к...

backup конфигурационного файла
не могу создать backup конфигурационного файла. Cisco 871 и ПК под Win XP. роутер подключен до ПК через патч-корд до ЛАН-порта. на ПК...


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

Или воспользуйтесь поиском по форуму:
2
Ответ Создать тему
Новые блоги и статьи
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru