Приблизительно, то что получилось в аттачменте.
пишу парсер (сканер) конфига.
так же хотел уточнить, как лучше организовать результаты парсинга.
Пока я это представляю следующим образом:
например, данные секции global хранить в структуре cfg_global,
данные секции wokers хранить в структуре cfg_wokers
данные секции pool хранить в массиве структур cfg_pool[n], n - кол-во пулов.
некоторые секции, такие как listen_options носят чисто формальный характер (для удобочитаемости), т.е. сами данные, могут находится в структуре cfg_pool
Если есть у кого какие замечания по структуре, или организации данных конфига то готов к критике.
Александр
было предложено использовать генератор лексем re2c, который генерит парсер. Быстро и красиво.
где-то неделю у меня ушло на опробацию решения, вот теперь дошли руки до реализации, времени катострофически не хватает, но стараюсь как-то помочь проекту.
а сами замечания по структуре конфига есть?
Структура то, что надо. Детали отшлифую, когда буду все сводить воедино.
--
Andrei Nigmatulin
GPG PUB KEY 6449830D
Now I lay me down to sleep(3)
Pray the OS my core to keep
If I die before I wake
Pray the Disk my core to take
Это как раз не библиотека, а кодогенератор. На входе у него специальный язык -
смесь си и regex выражений, на выходе - чистый си, без всяких зависимостей. В
php-fpm будет включен и исходник re2c и готовый .с файл, для удобства.
в двух словах re2c- это генератор с-кода на основе лексем регулярных выражений и конструкций #define.
по данным лексемам генерится в соответствии с внутренним алгоритмом си-код парсера, т.е. это вспомогательная тулза, на основе которой будет сгенерирован код парсера конфига, который просто напросто будет включен в дистрибутив. с самим re2c оконечный пользователь иметь дело не будет ни каким боком.
> > а сами замечания по структуре конфига есть?
> На первый взгляд все красиво и логично. про "include" не забудь пожалуйста.
Лично я не представляю каким боком впихнуть инклуде,
я так понимаю - проинклудить разные части конфига? Тогда я продумаю над этим вопросом, пока бы реализовать в наименьшем формате (один с-style конфиг).
Александр
pool {
# Name of pool. Used in logs and stats.
name default;
может быть
pool <name> {
по аналогии с location в nginx?
Можно как-то так
pool template1 {
...
}
pool site1 {
defaults template1;
...
listen 9000;
...
это существенное добавление, вставка <имени> перед началом секции - учтено.
Александр
> > abstract pool template1 {...}
> > pool somepool extends template1 {...}
> >
полностью согласен,
остановимся на ранее предложенном варианте:
pool template1 {...}
pool somepool {
extends template1 // или иное ключевое слово
...}
Это уже есть в коде - если пул не имеет listening сокета - то это
автоматически template.
инклуды реализуем следующим этапом.
я пока вижу следующий путь:
1) парсить первым проходом на #include и сделать один общий конфиг, который распарсить вторым проходом
2-й вариант) парсить файл, все инклуды обработать ка теги и сложить в стек, далее пропарсить каждый инклуд и данные добавить в конфиг_структуру.
как я вижу практическое применение, директивой #include хорошо включать пулы разных пользователей. т.е в принципе использовать инклуд только для пользователей.
мне кажется первый подход проще, тем более, если реализую парсинг данных, то сделать надстройку будет проще.
Александр
в каком-то роде - да,
это будет первый шаг парсинга, используя тот же re2c,
который собирет из трех-пяти конфигов - один.
вторым шагом - распарсить сводный конфиг.
А зачем так сложно ?
Я думал сделать так - лексер бежит по тексту, на все найденные конструкции и
директивы вызываются callbacks с текущим контекстом конфигурации. Как только
попалась директива include - создается новый, дочерний контекст конфигурации,
открывается файл и лексер бежит по нему. Добежал до конца - вернулся к
предыдущему контексту.
re2c вроде это умеет, разве нет ?
Судя по мануалу - умеет:
SCANNER WITH STORABLE STATES
When the -f flag is specified, re2c generates a scanner that can store its
current state, return to the caller, and later resume operations exactly
where it left off.
но мне казалось, что лучше распарсить все за один проход.
OK, присмотрюсь к этому подходу.
Это и будет один проход, разве не так ?
А вот так будет два:
> >Имеется ввиду написать свой собственный "пред-парсер"?
>
> в каком-то роде - да,
> это будет первый шаг парсинга, используя тот же re2c,
> который собирет из трех-пяти конфигов - один.
>
> вторым шагом - распарсить сводный конфиг.
Александр
кстати насчёт сериализации древовидных данных
там синтакс тоже на {} построен
незнаю что в данном случае более удобно, но мне лично офигенно
понравился "The Lemon Parser Generator"
На входе у него БНФ (помешанный с С)
на выходе чистый С
тоже без всяких зависимостей
Спасибо, посмотрю.