Files
pip/libs/main/code/picodeparser.h
2026-03-12 14:46:57 +03:00

388 lines
16 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! \~\file picodeparser.h
//! \~\ingroup Code
//! \~\brief
//! \~english C++ code parser
//! \~russian Разбор C++ кода
/*
PIP - Platform Independent Primitives
C++ code parser
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PICODEPARSER_H
#define PICODEPARSER_H
#include "pievaluator.h"
#include "pifile.h"
inline bool _isCChar(const PIChar & c) {
return (c.isAlpha() || (c.toAscii() == '_'));
}
inline bool _isCChar(const PIString & c) {
if (c.isEmpty()) return false;
return _isCChar(c[0]);
}
//! \~\ingroup Code
//! \~\brief
//! \~english Parser of C/C++ declarations used by the code model tools.
//! \~russian Разборщик объявлений C/C++, используемый инструментами модели кода.
//! \~\details
//! \~english Parser for analyzing C++ source files. Extracts information about classes, structures, enums, macros, functions, and members.
//! \~russian Парсер для анализа C++ исходных файлов. Извлекает информацию о классах, структурах, перечислениях, макросах, функциях и
//! членах.
class PIP_EXPORT PICodeParser {
public:
//! \~english Constructs a parser with built-in PIP macro presets.
//! \~russian Создает разборщик со встроенными предустановками макросов PIP.
PICodeParser();
//! \~english Visibility of a parsed declaration inside the current scope.
//! \~russian Видимость разобранного объявления в текущей области.
enum Visibility {
Global /** \~english Global or namespace-level declaration. \~russian Глобальное объявление или объявление уровня пространства имен.
*/
,
Public /** \~english Public class member. \~russian Открытый член класса. */,
Protected /** \~english Protected class member. \~russian Защищенный член класса. */,
Private /** \~english Private class member. \~russian Закрытый член класса. */
};
//! \~english Parsed declaration attributes.
//! \~russian Атрибуты разобранного объявления.
enum Attribute {
NoAttributes = 0x0 /** \~english No attributes. \~russian Атрибуты отсутствуют. */,
Const = 0x01 /** \~english \c const declaration. \~russian Объявление с \c const. */,
Static = 0x02 /** \~english \c static declaration. \~russian Объявление с \c static. */,
Mutable = 0x04 /** \~english \c mutable declaration. \~russian Объявление с \c mutable. */,
Volatile = 0x08 /** \~english \c volatile declaration. \~russian Объявление с \c volatile. */,
Inline = 0x10 /** \~english \c inline declaration. \~russian Объявление с \c inline. */,
Virtual = 0x20 /** \~english \c virtual declaration. \~russian Объявление с \c virtual. */,
Extern = 0x40 /** \~english \c extern declaration. \~russian Объявление с \c extern. */
};
//! \~english Bitmask of parsed declaration attributes.
//! \~russian Битовая маска атрибутов разобранного объявления.
typedef PIFlags<Attribute> Attributes;
//! \~english Preprocessor define name and value.
//! \~russian Имя и значение макроса \c define.
typedef PIPair<PIString, PIString> Define;
//! \~english Typedef alias and target type.
//! \~russian Псевдоним typedef и целевой тип.
typedef PIPair<PIString, PIString> Typedef;
//! \~english Parsed metadata map.
//! \~russian Карта разобранных метаданных.
typedef PIMap<PIString, PIString> MetaMap;
//! \~english Parsed function-like macro.
//! \~russian Разобранный функциональный макрос.
struct PIP_EXPORT Macro {
Macro(const PIString & n = PIString(), const PIString & v = PIString(), const PIStringList & a = PIStringList()) {
name = n;
value = v;
args = a;
}
//! \~english Expands the macro body with arguments from \a args_.
//! \~russian Разворачивает тело макроса с аргументами из \a args_.
PIString expand(PIString args_, bool * ok = 0) const;
//! \~english Macro name.
//! \~russian Имя макроса.
PIString name;
//! \~english Macro replacement text.
//! \~russian Текст замены макроса.
PIString value;
//! \~english Ordered list of macro argument names.
//! \~russian Упорядоченный список имен аргументов макроса.
PIStringList args;
};
//! \~english Parsed member declaration or function signature.
//! \~russian Разобранное объявление члена или сигнатура функции.
struct PIP_EXPORT Member {
Member() {
visibility = Global;
size = 0;
bits = -1;
is_type_ptr = false;
attributes = NoAttributes;
}
//! \~english Returns whether the member is declared as a bitfield.
//! \~russian Возвращает, объявлен ли член как битовое поле.
bool isBitfield() const { return bits > 0; }
//! \~english Parsed metadata attached to the member.
//! \~russian Разобранные метаданные, привязанные к члену.
MetaMap meta;
//! \~english Member type or return type.
//! \~russian Тип члена или возвращаемый тип.
PIString type;
//! \~english Member name.
//! \~russian Имя члена.
PIString name;
//! \~english Full textual argument declarations.
//! \~russian Полные текстовые объявления аргументов.
PIStringList arguments_full;
//! \~english Argument types only.
//! \~russian Только типы аргументов.
PIStringList arguments_type;
//! \~english Parsed array dimensions.
//! \~russian Разобранные размеры массива.
PIStringList dims;
//! \~english Member visibility.
//! \~russian Видимость члена.
Visibility visibility;
//! \~english Member attributes.
//! \~russian Атрибуты члена.
Attributes attributes;
//! \~english Indicates that the parsed type is a pointer.
//! \~russian Показывает, что разобранный тип является указателем.
bool is_type_ptr;
//! \~english Parsed size in bytes when available.
//! \~russian Разобранный размер в байтах, если он известен.
int size;
//! \~english Bit count for bitfields, or \c -1 otherwise.
//! \~russian Количество бит для битового поля или \c -1 в остальных случаях.
int bits;
};
//! \~english Parsed class, struct or namespace.
//! \~russian Разобранный класс, структура или пространство имен.
struct PIP_EXPORT Entity {
Entity() {
visibility = Global;
is_anonymous = false;
size = 0;
parent_scope = 0;
}
//! \~english Parsed metadata attached to the entity.
//! \~russian Разобранные метаданные, привязанные к сущности.
MetaMap meta;
//! \~english Entity kind, for example \c class, \c struct or \c namespace.
//! \~russian Вид сущности, например \c class, \c struct или \c namespace.
PIString type;
//! \~english Entity name.
//! \~russian Имя сущности.
PIString name;
//! \~english Source file where the entity was parsed.
//! \~russian Исходный файл, в котором была разобрана сущность.
PIString file;
//! \~english Entity visibility inside its parent scope.
//! \~russian Видимость сущности внутри родительской области.
Visibility visibility;
//! \~english Parsed size in bytes when available.
//! \~russian Разобранный размер в байтах, если он известен.
int size;
//! \~english Indicates that the entity was declared without a name.
//! \~russian Показывает, что сущность объявлена без имени.
bool is_anonymous;
//! \~english Immediate containing entity, or \c nullptr for the root scope.
//! \~russian Непосредственная содержащая сущность или \c nullptr для корневой области.
Entity * parent_scope;
//! \~english Direct base entities.
//! \~russian Непосредственные базовые сущности.
PIVector<Entity *> parents;
//! \~english Parsed member functions.
//! \~russian Разобранные функции-члены.
PIVector<Member> functions;
//! \~english Parsed data members.
//! \~russian Разобранные поля данных.
PIVector<Member> members;
//! \~english Typedefs declared inside the entity.
//! \~russian Typedef-объявления внутри сущности.
PIVector<Typedef> typedefs;
};
//! \~english Parsed enumerator entry.
//! \~russian Разобранный элемент перечисления.
struct PIP_EXPORT EnumeratorInfo {
EnumeratorInfo(const PIString & n = PIString(), int v = 0, const MetaMap & m = MetaMap()) {
name = n;
value = v;
meta = m;
}
//! \~english Parsed metadata attached to the enumerator.
//! \~russian Разобранные метаданные, привязанные к элементу перечисления.
MetaMap meta;
//! \~english Enumerator name.
//! \~russian Имя элемента перечисления.
PIString name;
//! \~english Enumerator value.
//! \~russian Значение элемента перечисления.
int value;
};
//! \~english Parsed enumeration.
//! \~russian Разобранное перечисление.
struct PIP_EXPORT Enum {
Enum(const PIString & n = PIString()) { name = n; }
//! \~english Parsed metadata attached to the enum.
//! \~russian Разобранные метаданные, привязанные к перечислению.
MetaMap meta;
//! \~english Enum name.
//! \~russian Имя перечисления.
PIString name;
//! \~english Parsed enumerators.
//! \~russian Разобранные элементы перечисления.
PIVector<EnumeratorInfo> members;
};
//! \~english Parses one source file and optionally follows its includes.
//! \~russian Разбирает один исходный файл и при необходимости следует по его include-зависимостям.
void parseFile(const PIString & file, bool follow_includes = true);
//! \~english Parses several source files into one parser state.
//! \~russian Разбирает несколько исходных файлов в одном состоянии разборщика.
void parseFiles(const PIStringList & files, bool follow_includes = true);
//! \~english Parses source text provided directly in memory.
//! \~russian Разбирает исходный текст, переданный напрямую из памяти.
void parseFileContent(PIString fc);
//! \~english Adds a directory to the include search list.
//! \~russian Добавляет каталог в список поиска include-файлов.
void includeDirectory(const PIString & dir) { includes << dir; }
//! \~english Adds a custom preprocessor definition before parsing.
//! \~russian Добавляет пользовательское препроцессорное определение перед разбором.
void addDefine(const PIString & def_name, const PIString & def_value) { custom_defines << Define(def_name, def_value); }
//! \~english Returns whether an enum with \a name was parsed.
//! \~russian Возвращает, было ли разобрано перечисление с именем \a name.
bool isEnum(const PIString & name);
//! \~english Finds a parsed entity by its full name.
//! \~russian Ищет разобранную сущность по ее полному имени.
Entity * findEntityByName(const PIString & en);
//! \~english Returns the set of files already processed by the parser.
//! \~russian Возвращает набор файлов, уже обработанных разборщиком.
PIStringList parsedFiles() const { return PIStringList(proc_files.toVector()); }
//! \~english Returns the file detected as the main translation unit.
//! \~russian Возвращает файл, определенный как основной единицей трансляции.
PIString mainFile() const { return main_file; }
//! \~english Returns the synthetic global scope entity.
//! \~russian Возвращает синтетическую сущность глобальной области.
const PICodeParser::Entity * global() const { return &root_; }
//! \~english Returns the maximum number of macro substitution passes.
//! \~russian Возвращает максимальное число проходов подстановки макросов.
int macrosSubstitutionMaxIterations() const { return macros_iter; }
//! \~english Sets the maximum number of macro substitution passes.
//! \~russian Задает максимальное число проходов подстановки макросов.
void setMacrosSubstitutionMaxIterations(int value) { macros_iter = value; }
//! \~english Parsed \c define directives, including built-in and custom ones.
//! \~russian Разобранные директивы \c define, включая встроенные и пользовательские.
PIVector<Define> defines, custom_defines;
//! \~english Parsed function-like macros.
//! \~russian Разобранные функциональные макросы.
PIVector<Macro> macros;
//! \~english Parsed enums from the processed files.
//! \~russian Разобранные перечисления из обработанных файлов.
PIVector<Enum> enums;
//! \~english Parsed top-level typedef declarations.
//! \~russian Разобранные typedef-объявления верхнего уровня.
PIVector<Typedef> typedefs;
//! \~english Parsed entities discovered in the processed files.
//! \~russian Разобранные сущности, найденные в обработанных файлах.
PIVector<Entity *> entities;
private:
void clear();
bool parseFileInternal(const PIString & file, bool follow_includes);
bool parseFileContent(PIString & fc, bool main);
bool parseDirective(PIString d);
Entity * parseClassDeclaration(const PIString & fc);
Entity * parseClass(Entity * parent, PIString & fc, bool is_namespace);
MetaMap parseMeta(PIString & fc);
bool parseEnum(Entity * parent, const PIString & name, PIString fc, const MetaMap & meta);
Typedef parseTypedef(PIString fc);
bool parseMember(Entity * parent, PIString & fc);
int extractMemberBits(PIString & fc);
void restoreTmpTemp(Member * e);
void restoreTmpMeta(Member * e);
MetaMap maybeMeta(PIString & fc);
bool macroCondition(const PIString & mif, PIString mifcond);
bool isDefineExists(const PIString & dn);
double defineValue(const PIString & dn);
void replaceMeta(PIString & dn);
PIString procMacros(PIString fc);
double procMacrosCond(PIString fc);
bool isDeclaration(const PIString & fc, int start, int * end);
bool isMainFile(const PIString & fc);
void normalizeEntityNamespace(PIString & n);
int macros_iter, anon_num;
bool with_includes;
PIEvaluator evaluator;
PISet<PIString> proc_files;
PIString cur_file, main_file;
PIStringList includes;
Entity root_;
Visibility cur_def_vis;
PIString cur_namespace;
PIMap<PIString, PIString> tmp_temp;
PIMap<PIString, MetaMap> tmp_meta;
};
#endif // PICODEPARSER_H