Я пытаюсь создать программу, которая анализирует и перечисляет содержимое файлов заголовков. До сих пор все было хорошо, мне было легко анализировать и перечислять заголовки, которые я написал, но когда я начал анализировать заголовки кроссплатформенного API, все стало беспорядочно.
Мой текущий подход довольно упрощен, вот пример псевдокода разбора следующей функции:
void foo(int a);
void is a type, so we are dealing with instancing a type
foo is the name of that type
foo is followed by brackets, meaning it is a function of type void named foo
int is a type...
a is the name of that type instance
foo is a function of type void that takes one parameter of type int named a
Однако, когда я занялся более крупными и сложными заголовками, я наткнулся на несколько неправильные прототипы, включающие макросы и черт знает что. Пример:
GLAPI void APIENTRY glEvalCoord1d( GLdouble u );
GLAPI и APIENTRY являются макросами, зависящими от платформы. Что портит мою простую схему синтаксического анализа, поскольку она ожидает, что имя объекта будет соответствовать его типу. Эти два макроса транслируются в __stdcall, __declspec(dllimport) или extern, но теоретически они могут означать что угодно, и их значение остается неясным до момента компиляции.
Как написать свой парсер, чтобы он справлялся с такими сценариями и не запутался? Сами макросы определяются на более ранней стадии, поэтому синтаксический анализатор может знать, что GLAPI и APIENTRY являются макросами, поэтому их можно просто игнорировать, так ли это? Естественно, это всего лишь одна из многих вариаций нарушений, с которыми синтаксический анализатор может столкнуться при анализе различных заголовков, поэтому приветствуются любые общие методы обработки любого «легального» содержимого заголовков.