// ============================================================ // Заголовочный файл компилятора RUSI // ============================================================ #еслинеопр RUSI_H #определить RUSI_H #определить _POSIX_C_SOURCE 200809L #включить // стандартная библиотека #включить // стандартная библиотека #включить // стандартная библиотека #включить // стандартная библиотека #включить // стандартная библиотека #включить // стандартная библиотека #включить // стандартная библиотека #включить // стандартная библиотека #включить // стандартная библиотека #включить // стандартная библиотека #включить // стандартная библиотека #включить // стандартная библиотека #включить // стандартная библиотека #включить // стандартная библиотека #включить // стандартная библиотека #включить // стандартная библиотека #включить // стандартная библиотека #включить // стандартная библиотека пусто free_all_types(пусто); пусто free_all_tokens(пусто); пусто free_all_preprocess(пусто); // ============================================================ // Общие макросы // ============================================================ #определить MAX(a, b) ((a) < (b) ? (b) : (a)) #определить MIN(a, b) ((a) < (b) ? (a) : (b)) #еслинеопр __GNUC__ #определить __attribute__(x) #конецесли // ============================================================ // Предварительные объявления структур // ============================================================ типдеф структ Type Type; типдеф структ Node Node; типдеф структ Member Member; типдеф структ Relocation Relocation; типдеф структ Hideset Hideset; // ============================================================ // Модуль strings.c - Работа со строками // ============================================================ типдеф структ { символ **data; // Массив строк цел capacity; // Вместимость цел len; // Текущее количество } МассивСтрок; пусто массив_строк_добавить(МассивСтрок *массив, символ *строка); символ *формат(символ *строка_формата, ...) __attribute__((format(printf, 1, 2))); пусто массив_строк_освободить(МассивСтрок *массив); пусто массив_строк_очистить(МассивСтрок *массив); символ *массив_строк_получить(конст МассивСтрок *массив, size_t инд); бул массив_строк_установить(МассивСтрок *массив, size_t инд, символ *строка); бул массив_строк_вставить(МассивСтрок *массив, size_t поз, символ *строка); бул массив_строк_удалить(МассивСтрок *массив, size_t инд); ssize_t массив_строк_найти(конст МассивСтрок *массив, конст символ *строка); бул массив_строк_содержит(конст МассивСтрок *массив, конст символ *строка); // ============================================================ // Модуль tokenize.c - Лексический анализ // ============================================================ типдеф переч { TK_IDENT, // Идентификаторы TK_PUNCT, // Пунктуаторы TK_KEYWORD, // Ключевые слова TK_STR, // Строковые литералы TK_NUM, // Числовые литералы TK_PP_NUM, // Препроцессорные числа TK_EOF, // Маркер конца файла } TokenKind; типдеф структ { символ *name; // Имя файла цел file_no; // Номер файла символ *contents; // Содержимое файла символ *display_name; // Отображаемое имя (для #строка) цел line_delta; // Смещение строк } File; типдеф структ Token Token; структ Token { TokenKind kind; // Тип токена Token *next; // Следующий токен int64_t val; // Значение для TK_NUM длин двойн fval; // Значение с плавающей точкой для TK_NUM символ *loc; // Позиция в исходном коде цел len; // Длина токена Type *ty; // Тип (для TK_NUM или TK_STR) символ *str; // Содержимое строкового литерала (с \0) File *file; // Файл источника символ *filename; // Имя файла цел line_no; // Номер строки цел line_delta; // Смещение строки бул at_bol; // В начале строки бул has_space; // Есть пробел перед токеном Hideset *hideset; // Для раскрытия макросов Token *origin; // Исходный токен (если раскрыт из макроса) }; // Ошибки и предупреждения noreturn пусто error(символ *format, ...) __attribute__((format(printf, 1, 2))); noreturn пусто error_at(символ *location, символ *format, ...) __attribute__((format(printf, 2, 3))); noreturn пусто error_tok(Token *token, символ *format, ...) __attribute__((format(printf, 2, 3))); пусто warn_tok(Token *token, символ *format, ...) __attribute__((format(printf, 2, 3))); // Работа с токенами бул equal(Token *token, символ *operator); Token *skip(Token *token, символ *operator); бул consume(Token **rest, Token *token, символ *str); пусто convert_pp_tokens(Token *tokens); // Работа с файлами File **get_input_files(пусто); File *new_file(символ *name, цел file_no, символ *contents); // Токенизация Token *tokenize_string_literal(Token *token, Type *base_type); Token *tokenize(File *file); Token *tokenize_file(символ *filename); #определить unreachable() error("internal error at %s:%d", __ФАЙЛ__, __ЛИНИЯ__) // ============================================================ // Модуль preprocess.c - Препроцессинг // ============================================================ символ *search_include_paths(символ *filename); пусто init_macros(пусто); пусто define_macro(символ *name, символ *value); пусто undef_macro(символ *name); Token *preprocess(Token *tokens); // ============================================================ // Модуль parse.c - Синтаксический анализ // ============================================================ типдеф структ Obj Obj; структ Obj { Obj *next; символ *name; // Имя переменной Type *ty; // Тип Token *tok; // Представительный токен бул is_local; // Локальная или глобальная цел align; // Выравнивание // Локальные переменные цел offset; // Смещение в стеке // Глобальные переменные или функции бул is_function; // Это функция бул is_definition; // Это определение бул is_static; // Статическая // Глобальные переменные бул is_tentative; // Предварительное объявление бул is_tls; // TLS переменная символ *init_data; // Данные инициализации Relocation *rel; // Релокации // Функции бул is_inline; // Inline функция Obj *params; // Параметры Node *body; // Тело функции Obj *locals; // Локальные переменные Obj *va_area; // Область для va_list Obj *alloca_bottom; // Нижняя граница alloca цел stack_size; // Размер стека // Статические inline функции бул is_live; // Используется бул is_root; // Корневая МассивСтрок refs; // Ссылки (было StringArray) }; типдеф структ Relocation Relocation; структ Relocation { Relocation *next; цел offset; // Смещение символ **label; // Метка длин addend; // Добавка }; типдеф переч { ND_NULL_EXPR, // Пустое выражение ND_ADD, // Сложение ND_SUB, // Вычитание ND_MUL, // Умножение ND_DIV, // Деление ND_NEG, // Унарный минус ND_MOD, // Остаток от деления ND_BITAND, // Побитовое И ND_BITOR, // Побитовое ИЛИ ND_BITXOR, // Побитовое исключающее ИЛИ ND_SHL, // Сдвиг влево ND_SHR, // Сдвиг вправо ND_EQ, // Равно ND_NE, // Не равно ND_LT, // Меньше ND_LE, // Меньше или равно ND_ASSIGN, // Присваивание ND_COND, // Условный оператор ?: ND_COMMA, // Оператор запятая ND_MEMBER, // Доступ к члену структуры ND_ADDR, // Взятие адреса ND_DEREF, // Разыменование ND_NOT, // Логическое НЕ ND_BITNOT, // Побитовое НЕ ND_LOGAND, // Логическое И ND_LOGOR, // Логическое ИЛИ ND_RETURN, // возврат ND_IF, // если ND_FOR, // для или пока ND_DO, // делай-пока ND_SWITCH, // выбор ND_CASE, // случай ND_BLOCK, // Блок { ... } ND_GOTO, // перейти ND_GOTO_EXPR, // перейти с выражением (GNU) ND_LABEL, // Метка ND_LABEL_VAL, // Метка как значение (GNU) ND_FUNCALL, // Вызов функции ND_EXPR_STMT, // Выражение-инструкция ND_STMT_EXPR, // Инструкция-выражение (GNU) ND_VAR, // Переменная ND_VLA_PTR, // VLA дескриптор ND_NUM, // Число ND_CAST, // Приведение типа ND_MEMZERO, // Обнуление стековой переменной ND_ASM, // асм ND_CAS, // Атомарная compare-and-swap ND_EXCH, // Атомарный обмен } NodeKind; структ Node { NodeKind kind; // Тип узла Node *next; // Следующий узел Type *ty; // Тип Token *tok; // Представительный токен Node *lhs; // Левый операнд Node *rhs; // Правый операнд // Условные и циклические конструкции Node *cond; // Условие Node *then; // Ветвь then Node *els; // Ветвь else Node *init; // Инициализация Node *inc; // Инкремент // Метки для прерви и продолжи символ *brk_label; символ *cont_label; // Блок или выражение-инструкция Node *body; // Доступ к члену структуры Member *member; // Вызов функции Type *func_ty; // Тип функции Node *args; // Аргументы бул pass_by_stack; // Передача через стек Obj *ret_buffer; // Буфер для возврата // перейти, метки и метки как значения символ *label; символ *unique_label; Node *goto_next; // выбор Node *case_next; Node *default_case; // случай длин begin; длин end; // асм символ *asm_str; // Атомарные операции Node *cas_addr; Node *cas_old; Node *cas_new; Obj *atomic_addr; Node *atomic_expr; // Переменная Obj *var; // Числовой литерал int64_t val; длин двойн fval; }; Node *new_cast(Node *expression, Type *type); int64_t const_expr(Token **rest, Token *token); Obj *parse(Token *tokens); // ============================================================ // Модуль type.c - Система типов // ============================================================ типдеф переч { TY_VOID, // пусто TY_BOOL, // _Bool TY_CHAR, // символ TY_SHORT, // корот TY_INT, // цел TY_LONG, // длин TY_FLOAT, // плав TY_DOUBLE, // двойн TY_LDOUBLE, // длин двойн TY_ENUM, // переч TY_PTR, // указатель TY_FUNC, // функция TY_ARRAY, // массив TY_VLA, // массив переменной длины TY_STRUCT, // структ TY_UNION, // объед } TypeKind; структ Type { TypeKind kind; // Тип цел size; // Размер в байтах цел align; // Выравнивание бул is_unsigned; // Беззнаковый бул is_atomic; // _Atomic Type *origin; // Исходный тип (для типдеф) // Для указателей и массивов Type *base; // Имя (для объявлений) Token *name; Token *name_pos; // Для массивов цел array_len; // Длина массива Node *vla_len; // Длина VLA (выражение) Obj *vla_size; // Размер VLA // Для структур/объединений Member *members; бул is_flexible; // Гибкий массив бул is_packed; // Упакованный // Для функций Type *return_ty; // Возвращаемый тип Type *params; // Параметры бул is_variadic; // Функция с переменным числом аргументов Type *next; // Следующий параметр }; структ Member { Member *next; Type *ty; Token *tok; // Для сообщений об ошибках Token *name; цел idx; // Индекс цел align; // Выравнивание цел offset; // Смещение // Битовые поля бул is_bitfield; цел bit_offset; цел bit_width; }; // Базовые типы внеш Type *ty_void; внеш Type *ty_bool; внеш Type *ty_char; внеш Type *ty_short; внеш Type *ty_int; внеш Type *ty_long; внеш Type *ty_uchar; внеш Type *ty_ushort; внеш Type *ty_uint; внеш Type *ty_ulong; внеш Type *ty_float; внеш Type *ty_double; внеш Type *ty_ldouble; // Проверка типов бул is_integer(Type *type); бул is_flonum(Type *type); бул is_numeric(Type *type); бул is_compatible(Type *first, Type *second); // Создание типов Type *copy_type(Type *original); Type *pointer_to(Type *base_type); Type *func_type(Type *return_type); Type *array_of(Type *base_type, цел size); Type *vla_of(Type *base_type, Node *expr); Type *enum_type(пусто); Type *struct_type(пусто); // Вывод типов пусто add_type(Node *node); // ============================================================ // Модуль codegen.c - Генерация кода // ============================================================ пусто codegen(Obj *program, FILE *output); цел align_to(цел value, цел alignment); // ============================================================ // Модуль unicode.c - Поддержка Unicode // ============================================================ цел encode_utf8(символ *buffer, uint32_t code_point); uint32_t decode_utf8(символ **new_position, символ *input); бул is_ident1(uint32_t code_point); бул is_ident2(uint32_t code_point); цел display_width(символ *text, цел length); // ============================================================ // Модуль hashmap.c - Хеш-таблица // ============================================================ типдеф структ { символ *ключ; // Ключ цел длина_ключа; // Длина ключа пусто *значение; // Значение } ЗаписьХеша; типдеф структ { ЗаписьХеша *корзины; // Массив корзин цел вместимость; // Вместимость цел использовано; // Использовано } ХешТаблица; пусто *хеш_получить(ХешТаблица *таблица, символ *ключ); пусто *хеш_получить2(ХешТаблица *таблица, символ *ключ, цел длина_ключа); пусто хеш_вставить(ХешТаблица *таблица, символ *ключ, пусто *значение); пусто хеш_вставить2(ХешТаблица *таблица, символ *ключ, цел длина_ключа, пусто *значение); пусто хеш_удалить(ХешТаблица *таблица, символ *ключ); пусто хеш_удалить2(ХешТаблица *таблица, символ *ключ, цел длина_ключа); пусто хеш_тест(пусто); // ============================================================ // Модуль main.c - Основная программа // ============================================================ бул file_exists(символ *path); внеш МассивСтрок include_paths; // было StringArray внеш бул opt_fpic; внеш бул opt_fcommon; внеш символ *base_file; #конецесли // RUSI_H