rusi/parse.c

2096 lines
111 KiB
C
Raw Permalink 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.

// Этот файл содержит рекурсивный спуск-парсер для языка C.
#включить "руси.з"
// Вспомогательные функции для поддержки русских синонимов
стат Token *пропустить_любой(Token *ток, символ *с1, символ *с2) {
если (equal(ток, с1)) возврат ток->next;
если (equal(ток, с2)) возврат ток->next;
возврат NULL;
}
стат Token *поглотить_любой(Token **остаток, Token *ток, символ *с1, символ *с2) {
Token *след = пропустить_любой(ток, с1, с2);
если (след) {
*остаток = след;
возврат след;
}
возврат NULL;
}
типдеф структ {
Obj *перем;
Type *определение_типа;
Type *тип_переч;
цел знач_переч;
} ОблПерем;
типдеф структ Область Область;
структ Область {
Область *след;
ХешТаблица перем;
ХешТаблица теги;
};
типдеф структ {
бул это_типдеф;
бул это_статик;
бул это_внеш;
бул это_инлайн;
бул это_tls;
цел выравн;
} АтрПерем;
типдеф структ Инициализатор Инициализатор;
структ Инициализатор {
Инициализатор *след;
Type *тип;
Token *ток;
бул гибкий;
Node *выр;
Инициализатор **дочерние;
Member *член;
};
типдеф структ Десигнатор Десигнатор;
структ Десигнатор {
Десигнатор *след;
цел инд;
Member *член;
Obj *перем;
};
стат Obj *лок_перем;
стат Obj *глоб_перем;
стат Область *тек_обл = &(Область){};
стат Obj *актункция;
стат Node *ожид_goto;
стат Node *опредетки;
стат символ *цель_прерви;
стат символ *цель_продолжи;
стат Node *акт_выбор;
стат Obj *встр_alloca;
стат бул это_имя_типа(Token *ток);
стат Type *спецификатор_типа(Token **остаток, Token *ток, АтрПерем *атр);
стат Type *имя_типа(Token **остаток, Token *ток);
стат Type *спец_переч(Token **остаток, Token *ток);
стат Type *спец_типоф(Token **остаток, Token *ток);
стат Type *суффикс_типа(Token **остаток, Token *ток, Type *тип);
стат Type *декларатор(Token **остаток, Token *ток, Type *тип);
стат Node *объявление(Token **остаток, Token *ток, Type *баз_тип, АтрПерем *атр);
стат пусто иницассива2(Token **остаток, Token *ток, Инициализатор *инит, цел ш);
стат пусто иниц_структуры2(Token **остаток, Token *ток, Инициализатор *инит, Member *член);
стат пусто инициализатор2(Token **остаток, Token *ток, Инициализатор *инит);
стат Инициализатор *инициализатор(Token **остаток, Token *ток, Type *тип, Type **нов_тип);
стат Node *иницок_перем(Token **остаток, Token *ток, Obj *перем);
стат пусто иниц_глоб_перем(Token *остаток, Token *ток, Obj *перем);
стат Node *составной_оператор(Token **остаток, Token *ток);
стат Node *оператор(Token **остаток, Token *ток);
стат Node *выр_оператор(Token **остаток, Token *ток);
стат Node *выражение(Token **остаток, Token *ток);
стат int64_t вычислить(Node *узел);
стат int64_t вычислить2(Node *узел, символ ***метка);
стат int64_t вычислить_rval(Node *узел, символ ***метка);
стат бул этоонст_выр(Node *узел);
стат Node *присваивание(Token **остаток, Token *ток);
стат Node *лог_или(Token **остаток, Token *ток);
стат двойн вычробное(Node *узел);
стат Node *условное(Token **остаток, Token *ток);
стат Node *лог(Token **остаток, Token *ток);
стат Node *побит_или(Token **остаток, Token *ток);
стат Node *побитскл_или(Token **остаток, Token *ток);
стат Node *побит(Token **остаток, Token *ток);
стат Node *равенство(Token **остаток, Token *ток);
стат Node *сравнение(Token **остаток, Token *ток);
стат Node *сдвиг(Token **остаток, Token *ток);
стат Node *сложение(Token **остаток, Token *ток);
стат Node *нов_слож(Node *лев, Node *прав, Token *ток);
стат Node *нов_выч(Node *лев, Node *прав, Token *ток);
стат Node *умножение(Token **остаток, Token *ток);
стат Node *приведение(Token **остаток, Token *ток);
стат Member *найти_член_стр(Type *тип, Token *ток);
стат Type *объяв_структ(Token **остаток, Token *ток);
стат Type *объяв_объед(Token **остаток, Token *ток);
стат Node *постфикс(Token **остаток, Token *ток);
стат Node *вызов_фн(Token **остаток, Token *ток, Node *узел);
стат Node *унарный(Token **остаток, Token *ток);
стат Node *первичный(Token **остаток, Token *ток);
стат Token *разбор_типдеф(Token *ток, Type *баз_тип);
стат бул этоункция(Token *ток);
стат Token *функция(Token *ток, Type *баз_тип, АтрПерем *атр);
стат Token *глоб_перем_объяв(Token *ток, Type *баз_тип, АтрПерем *атр);
стат цел округлить_вниз(цел ч, цел выр) {
возврат align_to(ч - выр + 1, выр);
}
стат пусто войти_в_обл(пусто) {
Область *обл = calloc(1, размер(Область));
обл->след = тек_обл;
тек_обл = обл;
}
стат пусто выйти_из_обл(пусто) {
тек_обл = тек_обл->след;
}
стат ОблПерем *найти_перем(Token *ток) {
для (Область *обл = тек_обл; обл; обл = обл->след) {
ОблПерем *обл2 = хеш_получить2(&обл->перем, ток->loc, ток->len);
если (обл2)
возврат обл2;
}
возврат NULL;
}
стат Type *найтиег(Token *ток) {
для (Область *обл = тек_обл; обл; обл = обл->след) {
Type *тип = хеш_получить2(&обл->теги, ток->loc, ток->len);
если (тип)
возврат тип;
}
возврат NULL;
}
стат Node *создать_узел(NodeKind вид, Token *ток) {
Node *узел = calloc(1, размер(Node));
узел->kind = вид;
узел->tok = ток;
возврат узел;
}
стат Node *создать_бин_узел(NodeKind вид, Node *лев, Node *прав, Token *ток) {
Node *узел = создать_узел(вид, ток);
узел->lhs = лев;
узел->rhs = прав;
возврат узел;
}
стат Node *создать_ун_узел(NodeKind вид, Node *выр, Token *ток) {
Node *узел = создать_узел(вид, ток);
узел->lhs = выр;
возврат узел;
}
стат Node *создать_число(int64_t знач, Token *ток) {
Node *узел = создать_узел(ND_NUM, ток);
узел->val = знач;
возврат узел;
}
стат Node *создать_длин_число(int64_t знач, Token *ток) {
Node *узел = создать_узел(ND_NUM, ток);
узел->val = знач;
узел->ty = ty_long;
возврат узел;
}
стат Node *создать_бузн_длин_число(длин знач, Token *ток) {
Node *узел = создать_узел(ND_NUM, ток);
узел->val = знач;
узел->ty = ty_ulong;
возврат узел;
}
стат Node *создать_узел_перем(Obj *перем, Token *ток) {
Node *узел = создать_узел(ND_VAR, ток);
узел->var = перем;
возврат узел;
}
стат Node *создать_узел_vla(Obj *перем, Token *ток) {
Node *узел = создать_узел(ND_VLA_PTR, ток);
узел->var = перем;
возврат узел;
}
Node *new_cast(Node *выр, Type *тип) {
add_type(выр);
Node *узел = calloc(1, размер(Node));
узел->kind = ND_CAST;
узел->tok = выр->tok;
узел->lhs = выр;
узел->ty = copy_type(тип);
возврат узел;
}
стат ОблПерем *зарег_перем(символ *имя) {
ОблПерем *обл = calloc(1, размер(ОблПерем));
хешставить(&тек_обл->перем, имя, обл);
возврат обл;
}
стат Инициализатор *создать_инит(Type *тип, бул гибкий) {
Инициализатор *инит = calloc(1, размер(Инициализатор));
инит->тип = тип;
если (тип->kind == TY_ARRAY) {
если (гибкий && тип->size < 0) {
инит->гибкий = истина;
возврат инит;
}
инит->дочерние = calloc(тип->array_len, размер(Инициализатор *));
для (цел ш = 0; ш < тип->array_len; ш++)
инит->дочерние[ш] = создать_инит(тип->base, ложь);
возврат инит;
}
если (тип->kind == TY_STRUCT || тип->kind == TY_UNION) {
цел длина = 0;
для (Member *член = тип->members; член; член = член->next)
длина++;
инит->дочерние = calloc(длина, размер(Инициализатор *));
для (Member *член = тип->members; член; член = член->next) {
если (гибкий && тип->is_flexible && !член->next) {
Инициализатор *доч = calloc(1, размер(Инициализатор));
доч->тип = член->ty;
доч->гибкий = истина;
инит->дочерние[член->idx] = доч;
} иначе {
инит->дочерние[член->idx] = создать_инит(член->ty, ложь);
}
}
возврат инит;
}
возврат инит;
}
стат Obj *создать_перем(символ *имя, Type *тип) {
Obj *перем = calloc(1, размер(Obj));
перем->name = имя;
перем->ty = тип;
перем->align = тип->align;
зарег_перем(имя)->перем = перем;
возврат перем;
}
стат Obj *создатьок_перем(символ *имя, Type *тип) {
Obj *перем = создать_перем(имя, тип);
перем->is_local = истина;
перем->next = лок_перем;
лок_перем = перем;
возврат перем;
}
стат Obj *создать_глоб_перем(символ *имя, Type *тип) {
Obj *перем = создать_перем(имя, тип);
перем->next = глоб_перем;
перем->is_static = истина;
перем->is_definition = истина;
глоб_перем = перем;
возврат перем;
}
стат символ *создать_уник_метку(пусто) {
стат цел щ = 0;
возврат формат(".L..%d", щ++);
}
стат Obj *создать_аноним_глоб(Type *тип) {
возврат создать_глоб_перем(создать_уник_метку(), тип);
}
стат Obj *создать_строк_литерал(символ *стр, Type *тип) {
Obj *перем = создать_аноним_глоб(тип);
перем->init_data = стр;
возврат перем;
}
стат символ *извлечь_ид(Token *ток) {
если (ток->kind != TK_IDENT)
error_tok(ток, "ожидался идентификатор");
возврат strndup(ток->loc, ток->len);
}
стат Type *найти_типдеф(Token *ток) {
если (ток->kind == TK_IDENT) {
ОблПерем *обл = найти_перем(ток);
если (обл)
возврат обл->определение_типа;
}
возврат NULL;
}
стат пусто зарегег(Token *ток, Type *тип) {
хешставить2(&тек_обл->теги, ток->loc, ток->len, тип);
}
стат Type *спецификатор_типа(Token **остаток, Token *ток, АтрПерем *атр) {
переч {
VOID = 1 << 0, BOOL = 1 << 2, CHAR = 1 << 4,
SHORT = 1 << 6, INT = 1 << 8, LONG = 1 << 10,
FLOAT = 1 << 12, DOUBLE = 1 << 14, OTHER = 1 << 16,
SIGNED = 1 << 17, UNSIGNED = 1 << 18,
};
Type *тип = ty_int;
цел счет = 0;
бул атом = ложь;
пока (это_имя_типа(ток)) {
если ((equal(ток, "typedef") || equal(ток, "типдеф")) || (equal(ток, "static") || equal(ток, "стат")) ||
(equal(ток, "extern") || equal(ток, "внеш")) || (equal(ток, "inline") || equal(ток, "инлайн")) ||
equal(ток, "_Thread_local") || equal(ток, "__thread")) {
если (!атр)
error_tok(ток, "спецификатор класса памяти не допускается в данном контексте");
если ((equal(ток, "typedef") || equal(ток, "типдеф"))) атр->это_типдеф = истина;
иначе если ((equal(ток, "static") || equal(ток, "стат"))) атр->это_статик = истина;
иначе если ((equal(ток, "extern") || equal(ток, "внеш"))) атр->это_внеш = истина;
иначе если ((equal(ток, "inline") || equal(ток, "инлайн"))) атр->это_инлайн = истина;
иначе атр->это_tls = истина;
если (атр->это_типдеф && атр->это_статик + атр->это_внеш + атр->это_инлайн + атр->это_tls > 1)
error_tok(ток, "типдеф не может использоваться вместе с стат, внеш, инлайн, __thread или _Thread_local");
ток = ток->next;
продолжи;
}
если (поглотить_любой(&ток, ток, "const", "конст") || поглотить_любой(&ток, ток, "volatile", "летуч") ||
поглотить_любой(&ток, ток, "auto", "авто") || поглотить_любой(&ток, ток, "register", "регистр") ||
поглотить_любой(&ток, ток, "restrict", "огранич") || consume(&ток, ток, "__restrict") ||
consume(&ток, ток, "__restrict__") || consume(&ток, ток, "_Noreturn") || consume(&ток, ток, "езвозврат"))
продолжи;
если (equal(ток, "_Atomic") || equal(ток, "_Атом")) {
ток = ток->next;
если (equal(ток, "(")) {
тип = имя_типа(&ток, ток->next);
ток = skip(ток, ")");
}
атом = истина;
продолжи;
}
если (equal(ток, "_Alignas") || equal(ток, "_Выравнивание")) {
если (!атр) error_tok(ток, "_Alignas (или _Выравнивание) не допускается в данном контексте");
ток = skip(ток->next, "(");
если (это_имя_типа(ток)) атр->выравн = имя_типа(&ток, ток)->align;
иначе атр->выравн = const_expr(&ток, ток);
ток = skip(ток, ")");
продолжи;
}
Type *т2 = найти_типдеф(ток);
если ((equal(ток, "struct") || equal(ток, "структ")) || (equal(ток, "union") || equal(ток, "объед")) ||
(equal(ток, "enum") || equal(ток, "переч")) || (equal(ток, "typeof") || equal(ток, "типоф")) || т2) {
если (счет) прерви;
если ((equal(ток, "struct") || equal(ток, "структ"))) тип = объяв_структ(&ток, ток->next);
иначе если ((equal(ток, "union") || equal(ток, "объед"))) тип = объяв_объед(&ток, ток->next);
иначе если ((equal(ток, "enum") || equal(ток, "переч"))) тип = спец_переч(&ток, ток->next);
иначе если ((equal(ток, "typeof") || equal(ток, "типоф"))) тип = спец_типоф(&ток, ток->next);
иначе { тип = т2; ток = ток->next; }
счет += OTHER;
продолжи;
}
если ((equal(ток, "void") || equal(ток, "пусто"))) счет += VOID;
иначе если (equal(ток, "_Bool")) счет += BOOL;
иначе если ((equal(ток, "char") || equal(ток, "символ"))) счет += CHAR;
иначе если ((equal(ток, "short") || equal(ток, "корот"))) счет += SHORT;
иначе если ((equal(ток, "int") || equal(ток, "цел"))) счет += INT;
иначе если ((equal(ток, "long") || equal(ток, "длин"))) счет += LONG;
иначе если ((equal(ток, "float") || equal(ток, "плав"))) счет += FLOAT;
иначе если ((equal(ток, "double") || equal(ток, "двойн"))) счет += DOUBLE;
иначе если ((equal(ток, "signed") || equal(ток, "знак"))) счет |= SIGNED;
иначе если ((equal(ток, "unsigned") || equal(ток, "беззнак"))) счет |= UNSIGNED;
иначе unreachable();
выбор (счет) {
случай VOID: тип = ty_void; прерви;
случай BOOL: тип = ty_bool; прерви;
случай CHAR: случай SIGNED + CHAR: тип = ty_char; прерви;
случай UNSIGNED + CHAR: тип = ty_uchar; прерви;
случай SHORT: случай SHORT + INT: случай SIGNED + SHORT: случай SIGNED + SHORT + INT: тип = ty_short; прерви;
случай UNSIGNED + SHORT: случай UNSIGNED + SHORT + INT: тип = ty_ushort; прерви;
случай INT: случай SIGNED: случай SIGNED + INT: тип = ty_int; прерви;
случай UNSIGNED: случай UNSIGNED + INT: тип = ty_uint; прерви;
случай LONG: случай LONG + INT: случай LONG + LONG: случай LONG + LONG + INT:
случай SIGNED + LONG: случай SIGNED + LONG + INT: случай SIGNED + LONG + LONG: случай SIGNED + LONG + LONG + INT:
тип = ty_long; прерви;
случай UNSIGNED + LONG: случай UNSIGNED + LONG + INT: случай UNSIGNED + LONG + LONG: случай UNSIGNED + LONG + LONG + INT:
тип = ty_ulong; прерви;
случай FLOAT: тип = ty_float; прерви;
случай DOUBLE: тип = ty_double; прерви;
случай LONG + DOUBLE: тип = ty_ldouble; прерви;
умолч: error_tok(ток, "недопустимый тип");
}
ток = ток->next;
}
если (атом) { тип = copy_type(тип); тип->is_atomic = истина; }
*остаток = ток;
возврат тип;
}
стат Type *разбор_парам(Token **остаток, Token *ток, Type *тип) {
если ((equal(ток, "void") || equal(ток, "пусто")) && equal(ток->next, ")")) {
*остаток = ток->next->next;
возврат func_type(тип);
}
Type голова = {};
Type *тек = &голова;
бул вариад = ложь;
пока (!equal(ток, ")")) {
если (тек != &голова) ток = skip(ток, ",");
если (equal(ток, "...")) { вариад = истина; ток = ток->next; skip(ток, ")"); прерви; }
Type *т2 = спецификатор_типа(&ток, ток, NULL);
т2 = декларатор(&ток, ток, т2);
Token *имя = т2->name;
если (т2->kind == TY_ARRAY) { т2 = pointer_to(т2->base); т2->name = имя; }
иначе если (т2->kind == TY_FUNC) { т2 = pointer_to(т2); т2->name = имя; }
тек = тек->next = copy_type(т2);
}
если (тек == &голова) вариад = истина;
тип = func_type(тип);
тип->params = голова.next;
тип->is_variadic = вариад;
*остаток = ток->next;
возврат тип;
}
стат Type *разбор_изм_масс(Token **остаток, Token *ток, Type *тип) {
пока ((equal(ток, "static") || equal(ток, "стат")) || (equal(ток, "restrict") || equal(ток, "огранич")))
ток = ток->next;
если (equal(ток, "]")) {
тип = суффикс_типа(остаток, ток->next, тип);
возврат array_of(тип, -1);
}
Node *выр = условное(&ток, ток);
ток = skip(ток, "]");
тип = суффикс_типа(остаток, ток, тип);
если (тип->kind == TY_VLA || !этоонст_выр(выр))
возврат vla_of(тип, выр);
возврат array_of(тип, вычислить(выр));
}
стат Type *суффикс_типа(Token **остаток, Token *ток, Type *тип) {
если (equal(ток, "(")) возврат разбор_парам(остаток, ток->next, тип);
если (equal(ток, "[")) возврат разбор_изм_масс(остаток, ток->next, тип);
*остаток = ток;
возврат тип;
}
стат Type *разбор_указ(Token **остаток, Token *ток, Type *тип) {
пока (consume(&ток, ток, "*")) {
тип = pointer_to(тип);
пока ((equal(ток, "const") || equal(ток, "конст")) || (equal(ток, "volatile") || equal(ток, "летуч")) ||
(equal(ток, "restrict") || equal(ток, "огранич")) || equal(ток, "__restrict") || equal(ток, "__restrict__"))
ток = ток->next;
}
*остаток = ток;
возврат тип;
}
стат Type *декларатор(Token **остаток, Token *ток, Type *тип) {
тип = разбор_указ(&ток, ток, тип);
если (equal(ток, "(")) {
Token *старт = ток;
Type загл = {};
декларатор(&ток, старт->next, &загл);
ток = skip(ток, ")");
тип = суффикс_типа(остаток, ток, тип);
возврат декларатор(&ток, старт->next, тип);
}
Token *имя = NULL;
Token *поз_имени = ток;
если (ток->kind == TK_IDENT) { имя = ток; ток = ток->next; }
тип = суффикс_типа(остаток, ток, тип);
тип->name = имя;
тип->name_pos = поз_имени;
возврат тип;
}
стат Type *абстрекл(Token **остаток, Token *ток, Type *тип) {
тип = разбор_указ(&ток, ток, тип);
если (equal(ток, "(")) {
Token *старт = ток;
Type загл = {};
абстрекл(&ток, старт->next, &загл);
ток = skip(ток, ")");
тип = суффикс_типа(остаток, ток, тип);
возврат абстрекл(&ток, старт->next, тип);
}
возврат суффикс_типа(остаток, ток, тип);
}
стат Type *имя_типа(Token **остаток, Token *ток) {
Type *тип = спецификатор_типа(&ток, ток, NULL);
возврат абстрекл(остаток, ток, тип);
}
стат бул этоаверш(Token *ток) {
возврат equal(ток, "}") || (equal(ток, ",") && equal(ток->next, "}"));
}
стат бул поглаверш(Token **остаток, Token *ток) {
если (equal(ток, "}")) { *остаток = ток->next; возврат истина; }
если (equal(ток, ",") && equal(ток->next, "}")) { *остаток = ток->next->next; возврат истина; }
возврат ложь;
}
стат Type *спец_переч(Token **остаток, Token *ток) {
Type *тип = enum_type();
Token *тег = NULL;
если (ток->kind == TK_IDENT) { тег = ток; ток = ток->next; }
если (тег && !equal(ток, "{")) {
Type *т = найтиег(тег);
если (!т) error_tok(тег, "неизвестный тип перечисления");
если (т->kind != TY_ENUM) error_tok(тег, "не является тегом перечисления");
*остаток = ток;
возврат т;
}
ток = skip(ток, "{");
цел ш = 0;
цел знач = 0;
пока (!поглаверш(остаток, ток)) {
если (ш++ > 0) ток = skip(ток, ",");
символ *имя = извлечь_ид(ток);
ток = ток->next;
если (equal(ток, "=")) знач = const_expr(&ток, ток->next);
ОблПерем *обл = зарег_перем(имя);
обл->тип_переч = тип;
обл->знач_переч = знач++;
}
если (тег) зарегег(тег, тип);
возврат тип;
}
стат Type *спец_типоф(Token **остаток, Token *ток) {
ток = skip(ток, "(");
Type *тип;
если (это_имя_типа(ток)) {
тип = имя_типа(&ток, ток);
} иначе {
Node *узел = выражение(&ток, ток);
add_type(узел);
тип = узел->ty;
}
*остаток = skip(ток, ")");
возврат тип;
}
стат Node *создать_выч_vla(Type *тип, Token *ток) {
Node *узел = создать_узел(ND_NULL_EXPR, ток);
если (тип->base) узел = создать_бин_узел(ND_COMMA, узел, создать_выч_vla(тип->base, ток), ток);
если (тип->kind != TY_VLA) возврат узел;
Node *баз_разм;
если (тип->base->kind == TY_VLA) баз_разм = создать_узел_перем(тип->base->vla_size, ток);
иначе баз_разм = создать_число(тип->base->size, ток);
тип->vla_size = создатьок_перем("", ty_ulong);
Node *выр = создать_бин_узел(ND_ASSIGN, создать_узел_перем(тип->vla_size, ток),
создать_бин_узел(ND_MUL, тип->vla_len, баз_разм, ток), ток);
возврат создать_бин_узел(ND_COMMA, узел, выр, ток);
}
стат Node *создать_узел_alloca(Node *разм) {
Node *узел = создать_ун_узел(ND_FUNCALL, создать_узел_перем(встр_alloca, разм->tok), разм->tok);
узел->func_ty = встр_alloca->ty;
узел->ty = встр_alloca->ty->return_ty;
узел->args = разм;
add_type(разм);
возврат узел;
}
стат Node *объявление(Token **остаток, Token *ток, Type *баз_тип, АтрПерем *атр) {
Node голова = {};
Node *тек = &голова;
цел ш = 0;
пока (!equal(ток, ";")) {
если (ш++ > 0) ток = skip(ток, ",");
Type *тип = декларатор(&ток, ток, баз_тип);
если (тип->kind == TY_VOID) error_tok(ток, "переменная объявлена как пусто (void)");
если (!тип->name) error_tok(тип->name_pos, "имя переменной опущено");
если (атр && атр->это_статик) {
Obj *перем = создать_аноним_глоб(тип);
зарег_перем(извлечь_ид(тип->name))->перем = перем;
если (equal(ток, "=")) иниц_глоб_перем(&ток, ток->next, перем);
продолжи;
}
тек = тек->next = создать_ун_узел(ND_EXPR_STMT, создать_выч_vla(тип, ток), ток);
если (тип->kind == TY_VLA) {
если (equal(ток, "=")) error_tok(ток, "объект переменного размера не может быть инициализирован");
Obj *перем = создатьок_перем(извлечь_ид(тип->name), тип);
Token *т = тип->name;
Node *выр = создать_бин_узел(ND_ASSIGN, создать_узел_vla(перем, т),
создать_узел_alloca(создать_узел_перем(тип->vla_size, т)), т);
тек = тек->next = создать_ун_узел(ND_EXPR_STMT, выр, т);
продолжи;
}
Obj *перем = создатьок_перем(извлечь_ид(тип->name), тип);
если (атр && атр->выравн) перем->align = атр->выравн;
если (equal(ток, "=")) {
Node *выр = иницок_перем(&ток, ток->next, перем);
тек = тек->next = создать_ун_узел(ND_EXPR_STMT, выр, ток);
}
если (перем->ty->size < 0) error_tok(тип->name, "переменная имеет неполный тип");
если (перем->ty->kind == TY_VOID) error_tok(тип->name, "переменная объявлена как пусто (void)");
}
Node *узел = создать_узел(ND_BLOCK, ток);
узел->body = голова.next;
*остаток = ток->next;
возврат узел;
}
стат Token *проп_лишний_инит(Token *ток) {
если (equal(ток, "{")) { ток = проп_лишний_инит(ток->next); возврат skip(ток, "}"); }
присваивание(&ток, ток);
возврат ток;
}
стат пусто разбор_стр_инит(Token **остаток, Token *ток, Инициализатор *инит) {
если (инит->гибкий)
*инит = *создать_инит(array_of(инит->тип->base, ток->ty->array_len), ложь);
цел длина = MIN(инит->тип->array_len, ток->ty->array_len);
выбор (инит->тип->base->size) {
случай 1: { символ *стр = ток->str; для (цел ш = 0; ш < длина; ш++) инит->дочерние[ш]->выр = создать_число(стр[ш], ток); прерви; }
случай 2: { uint16_t *стр = (uint16_t *)ток->str; для (цел ш = 0; ш < длина; ш++) инит->дочерние[ш]->выр = создать_число(стр[ш], ток); прерви; }
случай 4: { uint32_t *стр = (uint32_t *)ток->str; для (цел ш = 0; ш < длина; ш++) инит->дочерние[ш]->выр = создать_число(стр[ш], ток); прерви; }
умолч: unreachable();
}
*остаток = ток->next;
}
стат пусто разборесигасс(Token **остаток, Token *ток, Type *тип, цел *начало, цел *конец) {
*начало = const_expr(&ток, ток->next);
если (*начало >= тип->array_len) error_tok(ток, "индекс десигнатора массива выходит за его границы");
если (equal(ток, "...")) {
*конец = const_expr(&ток, ток->next);
если (*конец >= тип->array_len) error_tok(ток, "индекс десигнатора массива выходит за его границы");
если (*конец < *начало) error_tok(ток, "диапазон десигнатора массива [%d, %d] пуст", *начало, *конец);
} иначе { *конец = *начало; }
*остаток = skip(ток, "]");
}
стат Member *разборесиг_стр(Token **остаток, Token *ток, Type *тип) {
Token *старт = ток;
ток = skip(ток, ".");
если (ток->kind != TK_IDENT) error_tok(ток, "ожидался десигнатор поля");
для (Member *член = тип->members; член; член = член->next) {
если (член->ty->kind == TY_STRUCT && !член->name) {
если (найти_член_стр(член->ty, ток)) { *остаток = старт; возврат член; }
продолжи;
}
если (член->name->len == ток->len && !strncmp(член->name->loc, ток->loc, ток->len)) {
*остаток = ток->next;
возврат член;
}
}
error_tok(ток, "в структуре нет такого члена");
}
стат пусто разбор_обозн(Token **остаток, Token *ток, Инициализатор *инит) {
если (equal(ток, "[")) {
если (инит->тип->kind != TY_ARRAY) error_tok(ток, "индекс массива в инициализаторе не-массива");
цел начало, конец;
разборесигасс(&ток, ток, инит->тип, &начало, &конец);
Token *т2;
для (цел ш = начало; ш <= конец; ш++) разбор_обозн(&т2, ток, инит->дочерние[ш]);
иницассива2(остаток, т2, инит, начало + 1);
возврат;
}
если (equal(ток, ".") && инит->тип->kind == TY_STRUCT) {
Member *член = разборесиг_стр(&ток, ток, инит->тип);
разбор_обозн(&ток, ток, инит->дочерние[член->idx]);
инит->выр = NULL;
иниц_структуры2(остаток, ток, инит, член->next);
возврат;
}
если (equal(ток, ".") && инит->тип->kind == TY_UNION) {
Member *член = разборесиг_стр(&ток, ток, инит->тип);
инит->член = член;
разбор_обозн(остаток, ток, инит->дочерние[член->idx]);
возврат;
}
если (equal(ток, ".")) error_tok(ток, "имя поля не в инициализаторе структуры или объединения");
если (equal(ток, "=")) ток = ток->next;
инициализатор2(остаток, ток, инит);
}
стат цел подсч_эл_инит(Token *ток, Type *тип) {
бул первый = истина;
Инициализатор *загл = создать_инит(тип->base, истина);
цел ш = 0, макс = 0;
пока (!поглаверш(&ток, ток)) {
если (!первый) ток = skip(ток, ",");
первый = ложь;
если (equal(ток, "[")) {
ш = const_expr(&ток, ток->next);
если (equal(ток, "...")) ш = const_expr(&ток, ток->next);
ток = skip(ток, "]");
разбор_обозн(&ток, ток, загл);
} иначе { инициализатор2(&ток, ток, загл); }
ш++;
макс = MAX(макс, ш);
}
возврат макс;
}
стат пусто разбор_иниц_масс(Token **остаток, Token *ток, Инициализатор *инит) {
ток = skip(ток, "{");
если (инит->гибкий) {
цел длина = подсч_эл_инит(ток, инит->тип);
*инит = *создать_инит(array_of(инит->тип->base, длина), ложь);
}
бул первый = истина;
если (инит->гибкий) {
цел длина = подсч_эл_инит(ток, инит->тип);
*инит = *создать_инит(array_of(инит->тип->base, длина), ложь);
}
для (цел ш = 0; !поглаверш(остаток, ток); ш++) {
если (!первый) ток = skip(ток, ",");
первый = ложь;
если (equal(ток, "[")) {
цел начало, конец;
разборесигасс(&ток, ток, инит->тип, &начало, &конец);
Token *т2;
для (цел щ = начало; щ <= конец; щ++) разбор_обозн(&т2, ток, инит->дочерние[щ]);
ток = т2;
ш = конец;
продолжи;
}
если (ш < инит->тип->array_len) инициализатор2(&ток, ток, инит->дочерние[ш]);
иначе ток = проп_лишний_инит(ток);
}
}
стат пусто иницассива2(Token **остаток, Token *ток, Инициализатор *инит, цел ш) {
если (инит->гибкий) {
цел длина = подсч_эл_инит(ток, инит->тип);
*инит = *создать_инит(array_of(инит->тип->base, длина), ложь);
}
для (; ш < инит->тип->array_len && !этоаверш(ток); ш++) {
Token *старт = ток;
если (ш > 0) ток = skip(ток, ",");
если (equal(ток, "[") || equal(ток, ".")) { *остаток = старт; возврат; }
инициализатор2(&ток, ток, инит->дочерние[ш]);
}
*остаток = ток;
}
стат пусто разбор_иниц_стр(Token **остаток, Token *ток, Инициализатор *инит) {
ток = skip(ток, "{");
Member *член = инит->тип->members;
бул первый = истина;
пока (!поглаверш(остаток, ток)) {
если (!первый) ток = skip(ток, ",");
первый = ложь;
если (equal(ток, ".")) {
член = разборесиг_стр(&ток, ток, инит->тип);
разбор_обозн(&ток, ток, инит->дочерние[член->idx]);
член = член->next;
продолжи;
}
если (член) { инициализатор2(&ток, ток, инит->дочерние[член->idx]); член = член->next; }
иначе ток = проп_лишний_инит(ток);
}
}
стат пусто иниц_структуры2(Token **остаток, Token *ток, Инициализатор *инит, Member *член) {
бул первый = истина;
для (; член && !этоаверш(ток); член = член->next) {
Token *старт = ток;
если (!первый) ток = skip(ток, ",");
первый = ложь;
если (equal(ток, "[") || equal(ток, ".")) { *остаток = старт; возврат; }
инициализатор2(&ток, ток, инит->дочерние[член->idx]);
}
*остаток = ток;
}
стат пусто разбор_иниц_объед(Token **остаток, Token *ток, Инициализатор *инит) {
если (equal(ток, "{") && equal(ток->next, ".")) {
Member *член = разборесиг_стр(&ток, ток->next, инит->тип);
инит->член = член;
разбор_обозн(&ток, ток, инит->дочерние[член->idx]);
*остаток = skip(ток, "}");
возврат;
}
инит->член = инит->тип->members;
если (equal(ток, "{")) {
инициализатор2(&ток, ток->next, инит->дочерние[0]);
consume(&ток, ток, ",");
*остаток = skip(ток, "}");
} иначе { инициализатор2(остаток, ток, инит->дочерние[0]); }
}
стат пусто инициализатор2(Token **остаток, Token *ток, Инициализатор *инит) {
если (инит->тип->kind == TY_ARRAY && ток->kind == TK_STR) { разбор_стр_инит(остаток, ток, инит); возврат; }
если (инит->тип->kind == TY_ARRAY) {
если (equal(ток, "{")) разбор_иниц_масс(остаток, ток, инит);
иначе иницассива2(остаток, ток, инит, 0);
возврат;
}
если (инит->тип->kind == TY_STRUCT) {
если (equal(ток, "{")) { разбор_иниц_стр(остаток, ток, инит); возврат; }
Node *выр = присваивание(остаток, ток);
add_type(выр);
если (выр->ty->kind == TY_STRUCT) { инит->выр = выр; возврат; }
иниц_структуры2(остаток, ток, инит, инит->тип->members);
возврат;
}
если (инит->тип->kind == TY_UNION) { разбор_иниц_объед(остаток, ток, инит); возврат; }
если (equal(ток, "{")) { инициализатор2(&ток, ток->next, инит); *остаток = skip(ток, "}"); возврат; }
инит->выр = присваивание(остаток, ток);
}
стат Type *продубл_стр(Type *тип) {
тип = copy_type(тип);
Member голова = {};
Member *тек = &голова;
для (Member *член = тип->members; член; член = член->next) {
Member *м = calloc(1, размер(Member));
*м = *член;
тек = тек->next = м;
}
тип->members = голова.next;
возврат тип;
}
стат Инициализатор *инициализатор(Token **остаток, Token *ток, Type *тип, Type **нов_тип) {
Инициализатор *инит = создать_инит(тип, истина);
инициализатор2(остаток, ток, инит);
если ((тип->kind == TY_STRUCT || тип->kind == TY_UNION) && тип->is_flexible) {
тип = продубл_стр(тип);
Member *член = тип->members;
пока (член->next) член = член->next;
член->ty = инит->дочерние[член->idx]->тип;
тип->size += член->ty->size;
*нов_тип = тип;
возврат инит;
}
*нов_тип = инит->тип;
возврат инит;
}
стат Node *постр_выресиг(Десигнатор *дес, Token *ток) {
если (дес->перем) возврат создать_узел_перем(дес->перем, ток);
если (дес->член) {
Node *узел = создать_ун_узел(ND_MEMBER, постр_выресиг(дес->след, ток), ток);
узел->member = дес->член;
возврат узел;
}
Node *лев = постр_выресиг(дес->след, ток);
Node *прав = создать_число(дес->инд, ток);
возврат создать_ун_узел(ND_DEREF, нов_слож(лев, прав, ток), ток);
}
стат Node *построк_инит(Инициализатор *инит, Type *тип, Десигнатор *дес, Token *ток) {
если (тип->kind == TY_ARRAY) {
Node *узел = создать_узел(ND_NULL_EXPR, ток);
для (цел ш = 0; ш < тип->array_len; ш++) {
Десигнатор д2 = {дес, ш};
Node *прав = построк_инит(инит->дочерние[ш], тип->base, &д2, ток);
узел = создать_бин_узел(ND_COMMA, узел, прав, ток);
}
возврат узел;
}
если (тип->kind == TY_STRUCT && !инит->выр) {
Node *узел = создать_узел(ND_NULL_EXPR, ток);
для (Member *член = тип->members; член; член = член->next) {
Десигнатор д2 = {дес, 0, член};
Node *прав = построк_инит(инит->дочерние[член->idx], член->ty, &д2, ток);
узел = создать_бин_узел(ND_COMMA, узел, прав, ток);
}
возврат узел;
}
если (тип->kind == TY_UNION) {
Member *член = инит->член ? инит->член : тип->members;
Десигнатор д2 = {дес, 0, член};
возврат построк_инит(инит->дочерние[член->idx], член->ty, &д2, ток);
}
если (!инит->выр) возврат создать_узел(ND_NULL_EXPR, ток);
Node *лев = постр_выресиг(дес, ток);
возврат создать_бин_узел(ND_ASSIGN, лев, инит->выр, ток);
}
стат Node *иницок_перем(Token **остаток, Token *ток, Obj *перем) {
Инициализатор *инит = инициализатор(остаток, ток, перем->ty, &перем->ty);
Десигнатор дес = {NULL, 0, NULL, перем};
Node *лев = создать_узел(ND_MEMZERO, ток);
лев->var = перем;
Node *прав = построк_инит(инит, перем->ty, &дес, ток);
возврат создать_бин_узел(ND_COMMA, лев, прав, ток);
}
стат uint64_t проч_буф(символ *буф, цел разм) {
если (разм == 1) возврат *буф;
если (разм == 2) возврат *(uint16_t *)буф;
если (разм == 4) возврат *(uint32_t *)буф;
если (разм == 8) возврат *(uint64_t *)буф;
unreachable();
}
стат пусто запиш_буф(символ *буф, uint64_t знач, цел разм) {
если (разм == 1) *буф = знач;
иначе если (разм == 2) *(uint16_t *)буф = знач;
иначе если (разм == 4) *(uint32_t *)буф = знач;
иначе если (разм == 8) *(uint64_t *)буф = знач;
иначе unreachable();
}
стат Relocation *
сериал_глоб(Relocation *тек, Инициализатор *инит, Type *тип, символ *буф, цел смещ) {
если (тип->kind == TY_ARRAY) {
цел разм = тип->base->size;
для (цел ш = 0; ш < тип->array_len; ш++)
тек = сериал_глоб(тек, инит->дочерние[ш], тип->base, буф, смещ + разм * ш);
возврат тек;
}
если (тип->kind == TY_STRUCT) {
для (Member *член = тип->members; член; член = член->next) {
если (член->is_bitfield) {
Node *выр = инит->дочерние[член->idx]->выр;
если (!выр) прерви;
символ *поз = буф + смещ + член->offset;
uint64_t стар = проч_буф(поз, член->ty->size);
uint64_t нов = вычислить(выр);
uint64_t маска = (1L << член->bit_width) - 1;
uint64_t объед_знач = стар | ((нов & маска) << член->bit_offset);
запиш_буф(поз, объед_знач, член->ty->size);
} иначе {
тек = сериал_глоб(тек, инит->дочерние[член->idx], член->ty, буф, смещ + член->offset);
}
}
возврат тек;
}
если (тип->kind == TY_UNION) {
если (!инит->член) возврат тек;
возврат сериал_глоб(тек, инит->дочерние[инит->член->idx], инит->член->ty, буф, смещ);
}
если (!инит->выр) возврат тек;
если (тип->kind == TY_FLOAT) { *(плав *)(буф + смещ) = вычробное(инит->выр); возврат тек; }
если (тип->kind == TY_DOUBLE) { *(двойн *)(буф + смещ) = вычробное(инит->выр); возврат тек; }
символ **метка = NULL;
uint64_t знач = вычислить2(инит->выр, &метка);
если (!метка) { запиш_буф(буф + смещ, знач, тип->size); возврат тек; }
Relocation *рел = calloc(1, размер(Relocation));
рел->offset = смещ;
рел->label = метка;
рел->addend = знач;
тек->next = рел;
возврат тек->next;
}
стат пусто иниц_глоб_перем(Token **остаток, Token *ток, Obj *перем) {
Инициализатор *инит = инициализатор(остаток, ток, перем->ty, &перем->ty);
Relocation голова = {};
символ *буф = calloc(1, перем->ty->size);
сериал_глоб(&голова, инит, перем->ty, буф, 0);
перем->init_data = буф;
перем->rel = голова.next;
}
стат бул это_имя_типа(Token *ток) {
стат ХешТаблица карта;
если (карта.вместимость == 0) {
стат символ *кл[] = {
"void", "_Bool", "char", "short", "int", "long", "struct", "union",
"пусто", "символ", "корот", "цел", "длин", "структ", "объед",
"typedef", "enum", "static", "extern", "_Alignas", "_Выравнивание", "signed", "unsigned",
"типдеф", "переч", "стат", "внеш", "знак", "беззнак",
"const", "volatile", "auto", "register", "restrict", "__restrict",
"конст", "летуч", "авто", "регистр", "огранич",
"__restrict__", "_Noreturn", "езвозврат", "float", "double", "typeof", "inline",
"плав", "двойн", "типоф", "инлайн",
"_Thread_local", "__thread", "_Atomic",
};
для (цел ш = 0; ш < размер(кл) / размер(*кл); ш++)
хешставить(&карта, кл[ш], (пусто *)1);
}
возврат хеш_получить2(&карта, ток->loc, ток->len) || найти_типдеф(ток);
}
стат Node *разбор_асм(Token **остаток, Token *ток) {
Node *узел = создать_узел(ND_ASM, ток);
ток = ток->next;
пока ((equal(ток, "volatile") || equal(ток, "летуч")) || (equal(ток, "inline") || equal(ток, "инлайн")))
ток = ток->next;
ток = skip(ток, "(");
если (ток->kind != TK_STR || ток->ty->base->kind != TY_CHAR)
error_tok(ток, "ожидался строковый литерал");
узел->asm_str = ток->str;
*остаток = skip(ток->next, ")");
возврат узел;
}
стат Node *оператор(Token **остаток, Token *ток) {
если ((equal(ток, "return") || equal(ток, "возврат"))) {
Node *узел = создать_узел(ND_RETURN, ток);
если (consume(остаток, ток->next, ";")) возврат узел;
Node *выр = выражение(&ток, ток->next);
*остаток = skip(ток, ";");
add_type(выр);
Type *тип = актункция->ty->return_ty;
если (тип->kind != TY_STRUCT && тип->kind != TY_UNION)
выр = new_cast(выр, актункция->ty->return_ty);
узел->lhs = выр;
возврат узел;
}
если ((equal(ток, "if") || equal(ток, "если"))) {
Node *узел = создать_узел(ND_IF, ток);
ток = skip(ток->next, "(");
узел->cond = выражение(&ток, ток);
ток = skip(ток, ")");
узел->then = оператор(&ток, ток);
если ((equal(ток, "else") || equal(ток, "иначе")))
узел->els = оператор(&ток, ток->next);
*остаток = ток;
возврат узел;
}
если ((equal(ток, "switch") || equal(ток, "выбор"))) {
Node *узел = создать_узел(ND_SWITCH, ток);
ток = skip(ток->next, "(");
узел->cond = выражение(&ток, ток);
ток = skip(ток, ")");
Node *пред = акт_выбор;
акт_выбор = узел;
символ *прель = цель_прерви;
цель_прерви = узел->brk_label = создать_уник_метку();
узел->then = оператор(остаток, ток);
акт_выбор = пред;
цель_прерви = прель;
возврат узел;
}
если ((equal(ток, "case") || equal(ток, "случай"))) {
если (!акт_выбор) error_tok(ток, "бесхозный случай (case) вне выбора");
Node *узел = создать_узел(ND_CASE, ток);
цел начало = const_expr(&ток, ток->next);
цел конец;
если (equal(ток, "...")) {
конец = const_expr(&ток, ток->next);
если (конец < начало) error_tok(ток, "указан пустой диапазон случая");
} иначе { конец = начало; }
ток = skip(ток, ":");
узел->label = создать_уник_метку();
узел->lhs = оператор(остаток, ток);
узел->begin = начало;
узел->end = конец;
узел->case_next = акт_выбор->case_next;
акт_выбор->case_next = узел;
возврат узел;
}
если ((equal(ток, "default") || equal(ток, "умолч"))) {
если (!акт_выбор) error_tok(ток, "бесхозный умолч (default) вне выбора");
Node *узел = создать_узел(ND_CASE, ток);
ток = skip(ток->next, ":");
узел->label = создать_уник_метку();
узел->lhs = оператор(остаток, ток);
акт_выбор->default_case = узел;
возврат узел;
}
если ((equal(ток, "for") || equal(ток, "для"))) {
Node *узел = создать_узел(ND_FOR, ток);
ток = skip(ток->next, "(");
войти_в_обл();
символ *прель = цель_прерви;
символ *прдель = цель_продолжи;
цель_прерви = узел->brk_label = создать_уник_метку();
цель_продолжи = узел->cont_label = создать_уник_метку();
если (это_имя_типа(ток)) {
Type *баз = спецификатор_типа(&ток, ток, NULL);
узел->init = объявление(&ток, ток, баз, NULL);
} иначе { узел->init = выр_оператор(&ток, ток); }
если (!equal(ток, ";")) узел->cond = выражение(&ток, ток);
ток = skip(ток, ";");
если (!equal(ток, ")")) узел->inc = выражение(&ток, ток);
ток = skip(ток, ")");
узел->then = оператор(остаток, ток);
выйти_из_обл();
цель_прерви = прель;
цель_продолжи = прдель;
возврат узел;
}
если ((equal(ток, "while") || equal(ток, "пока"))) {
Node *узел = создать_узел(ND_FOR, ток);
ток = skip(ток->next, "(");
узел->cond = выражение(&ток, ток);
ток = skip(ток, ")");
символ *прель = цель_прерви;
символ *прдель = цель_продолжи;
цель_прерви = узел->brk_label = создать_уник_метку();
цель_продолжи = узел->cont_label = создать_уник_метку();
узел->then = оператор(остаток, ток);
цель_прерви = прель;
цель_продолжи = прдель;
возврат узел;
}
если ((equal(ток, "do") || equal(ток, "делай"))) {
Node *узел = создать_узел(ND_DO, ток);
символ *прель = цель_прерви;
символ *прдель = цель_продолжи;
цель_прерви = узел->brk_label = создать_уник_метку();
цель_продолжи = узел->cont_label = создать_уник_метку();
узел->then = оператор(&ток, ток->next);
цель_прерви = прель;
цель_продолжи = прдель;
ток = пропустить_любой(ток, "while", "пока");
ток = skip(ток, "(");
узел->cond = выражение(&ток, ток);
ток = skip(ток, ")");
*остаток = skip(ток, ";");
возврат узел;
}
если ((equal(ток, "asm") || equal(ток, "асм"))) возврат разбор_асм(остаток, ток);
если ((equal(ток, "goto") || equal(ток, "перейти"))) {
если (equal(ток->next, "*")) {
Node *узел = создать_узел(ND_GOTO_EXPR, ток);
узел->lhs = выражение(&ток, ток->next->next);
*остаток = skip(ток, ";");
возврат узел;
}
Node *узел = создать_узел(ND_GOTO, ток);
узел->label = извлечь_ид(ток->next);
узел->goto_next = ожид_goto;
ожид_goto = узел;
*остаток = skip(ток->next->next, ";");
возврат узел;
}
если ((equal(ток, "break") || equal(ток, "прерви"))) {
если (!цель_прерви) error_tok(ток, "бесхозный прерви (break) вне цикла или выбора");
Node *узел = создать_узел(ND_GOTO, ток);
узел->unique_label = цель_прерви;
*остаток = skip(ток->next, ";");
возврат узел;
}
если ((equal(ток, "continue") || equal(ток, "продолжи"))) {
если (!цель_продолжи) error_tok(ток, "бесхозный продолжи (continue) вне цикла");
Node *узел = создать_узел(ND_GOTO, ток);
узел->unique_label = цель_продолжи;
*остаток = skip(ток->next, ";");
возврат узел;
}
если (ток->kind == TK_IDENT && equal(ток->next, ":")) {
Node *узел = создать_узел(ND_LABEL, ток);
узел->label = strndup(ток->loc, ток->len);
узел->unique_label = создать_уник_метку();
узел->lhs = оператор(остаток, ток->next->next);
узел->goto_next = опредетки;
опредетки = узел;
возврат узел;
}
если (equal(ток, "{")) возврат составной_оператор(остаток, ток->next);
возврат выр_оператор(остаток, ток);
}
стат Node *составной_оператор(Token **остаток, Token *ток) {
Node *узел = создать_узел(ND_BLOCK, ток);
Node голова = {};
Node *тек = &голова;
войти_в_обл();
пока (!equal(ток, "}")) {
если (это_имя_типа(ток) && !equal(ток->next, ":")) {
АтрПерем атр = {};
Type *баз = спецификатор_типа(&ток, ток, &атр);
если (атр.это_типдеф) { ток = разбор_типдеф(ток, баз); продолжи; }
если (этоункция(ток)) { ток = функция(ток, баз, &атр); продолжи; }
если (атр.это_внеш) { ток = глоб_перем_объяв(ток, баз, &атр); продолжи; }
тек = тек->next = объявление(&ток, ток, баз, &атр);
} иначе { тек = тек->next = оператор(&ток, ток); }
add_type(тек);
}
выйти_из_обл();
узел->body = голова.next;
*остаток = ток->next;
возврат узел;
}
стат Node *выр_оператор(Token **остаток, Token *ток) {
если (equal(ток, ";")) { *остаток = ток->next; возврат создать_узел(ND_BLOCK, ток); }
Node *узел = создать_узел(ND_EXPR_STMT, ток);
узел->lhs = выражение(&ток, ток);
*остаток = skip(ток, ";");
возврат узел;
}
стат Node *выражение(Token **остаток, Token *ток) {
Node *узел = присваивание(&ток, ток);
если (equal(ток, ",")) возврат создать_бин_узел(ND_COMMA, узел, выражение(остаток, ток->next), ток);
*остаток = ток;
возврат узел;
}
стат int64_t вычислить(Node *узел) { возврат вычислить2(узел, NULL); }
стат int64_t вычислить2(Node *узел, символ ***метка) {
add_type(узел);
если (is_flonum(узел->ty)) возврат вычробное(узел);
выбор (узел->kind) {
случай ND_ADD: возврат вычислить2(узел->lhs, метка) + вычислить(узел->rhs);
случай ND_SUB: возврат вычислить2(узел->lhs, метка) - вычислить(узел->rhs);
случай ND_MUL: возврат вычислить(узел->lhs) * вычислить(узел->rhs);
случай ND_DIV:
если (узел->ty->is_unsigned) возврат (uint64_t)вычислить(узел->lhs) / вычислить(узел->rhs);
возврат вычислить(узел->lhs) / вычислить(узел->rhs);
случай ND_NEG: возврат -вычислить(узел->lhs);
случай ND_MOD:
если (узел->ty->is_unsigned) возврат (uint64_t)вычислить(узел->lhs) % вычислить(узел->rhs);
возврат вычислить(узел->lhs) % вычислить(узел->rhs);
случай ND_BITAND: возврат вычислить(узел->lhs) & вычислить(узел->rhs);
случай ND_BITOR: возврат вычислить(узел->lhs) | вычислить(узел->rhs);
случай ND_BITXOR: возврат вычислить(узел->lhs) ^ вычислить(узел->rhs);
случай ND_SHL: возврат вычислить(узел->lhs) << вычислить(узел->rhs);
случай ND_SHR:
если (узел->ty->is_unsigned && узел->ty->size == 8) возврат (uint64_t)вычислить(узел->lhs) >> вычислить(узел->rhs);
возврат вычислить(узел->lhs) >> вычислить(узел->rhs);
случай ND_EQ: возврат вычислить(узел->lhs) == вычислить(узел->rhs);
случай ND_NE: возврат вычислить(узел->lhs) != вычислить(узел->rhs);
случай ND_LT:
если (узел->lhs->ty->is_unsigned) возврат (uint64_t)вычислить(узел->lhs) < вычислить(узел->rhs);
возврат вычислить(узел->lhs) < вычислить(узел->rhs);
случай ND_LE:
если (узел->lhs->ty->is_unsigned) возврат (uint64_t)вычислить(узел->lhs) <= вычислить(узел->rhs);
возврат вычислить(узел->lhs) <= вычислить(узел->rhs);
случай ND_COND: возврат вычислить(узел->cond) ? вычислить2(узел->then, метка) : вычислить2(узел->els, метка);
случай ND_COMMA: возврат вычислить2(узел->rhs, метка);
случай ND_NOT: возврат !вычислить(узел->lhs);
случай ND_BITNOT: возврат ~вычислить(узел->lhs);
случай ND_LOGAND: возврат вычислить(узел->lhs) && вычислить(узел->rhs);
случай ND_LOGOR: возврат вычислить(узел->lhs) || вычислить(узел->rhs);
случай ND_CAST: {
int64_t знач = вычислить2(узел->lhs, метка);
если (is_integer(узел->ty)) {
выбор (узел->ty->size) {
случай 1: возврат узел->ty->is_unsigned ? (uint8_t)знач : (int8_t)знач;
случай 2: возврат узел->ty->is_unsigned ? (uint16_t)знач : (int16_t)знач;
случай 4: возврат узел->ty->is_unsigned ? (uint32_t)знач : (int32_t)знач;
}
}
возврат знач;
}
случай ND_ADDR: возврат вычислить_rval(узел->lhs, метка);
случай ND_LABEL_VAL: *метка = &узел->unique_label; возврат 0;
случай ND_MEMBER:
если (!метка) error_tok(узел->tok, "не является константой времени компиляции");
если (узел->ty->kind != TY_ARRAY) error_tok(узел->tok, "недопустимый инициализатор");
возврат вычислить_rval(узел->lhs, метка) + узел->member->offset;
случай ND_VAR:
если (!метка) error_tok(узел->tok, "не является константой времени компиляции");
если (узел->var->ty->kind != TY_ARRAY && узел->var->ty->kind != TY_FUNC)
error_tok(узел->tok, "недопустимый инициализатор");
*метка = &узел->var->name;
возврат 0;
случай ND_NUM: возврат узел->val;
}
error_tok(узел->tok, "не является константой времени компиляции");
}
стат int64_t вычислить_rval(Node *узел, символ ***метка) {
выбор (узел->kind) {
случай ND_VAR:
если (узел->var->is_local) error_tok(узел->tok, "не является константой времени компиляции");
*метка = &узел->var->name;
возврат 0;
случай ND_DEREF: возврат вычислить2(узел->lhs, метка);
случай ND_MEMBER: возврат вычислить_rval(узел->lhs, метка) + узел->member->offset;
}
error_tok(узел->tok, "недопустимый инициализатор");
}
стат бул этоонст_выр(Node *узел) {
add_type(узел);
выбор (узел->kind) {
случай ND_ADD: случай ND_SUB: случай ND_MUL: случай ND_DIV:
случай ND_BITAND: случай ND_BITOR: случай ND_BITXOR:
случай ND_SHL: случай ND_SHR:
случай ND_EQ: случай ND_NE: случай ND_LT: случай ND_LE:
случай ND_LOGAND: случай ND_LOGOR:
возврат этоонст_выр(узел->lhs) && этоонст_выр(узел->rhs);
случай ND_COND:
если (!этоонст_выр(узел->cond)) возврат ложь;
возврат этоонст_выр(вычислить(узел->cond) ? узел->then : узел->els);
случай ND_COMMA: возврат этоонст_выр(узел->rhs);
случай ND_NEG: случай ND_NOT: случай ND_BITNOT: случай ND_CAST:
возврат этоонст_выр(узел->lhs);
случай ND_NUM: возврат истина;
}
возврат ложь;
}
int64_t const_expr(Token **остаток, Token *ток) {
Node *узел = условное(остаток, ток);
возврат вычислить(узел);
}
стат двойн вычробное(Node *узел) {
add_type(узел);
если (is_integer(узел->ty)) {
если (узел->ty->is_unsigned) возврат (беззнак длин)вычислить(узел);
возврат вычислить(узел);
}
выбор (узел->kind) {
случай ND_ADD: возврат вычробное(узел->lhs) + вычробное(узел->rhs);
случай ND_SUB: возврат вычробное(узел->lhs) - вычробное(узел->rhs);
случай ND_MUL: возврат вычробное(узел->lhs) * вычробное(узел->rhs);
случай ND_DIV: возврат вычробное(узел->lhs) / вычробное(узел->rhs);
случай ND_NEG: возврат -вычробное(узел->lhs);
случай ND_COND: возврат вычробное(узел->cond) ? вычробное(узел->then) : вычробное(узел->els);
случай ND_COMMA: возврат вычробное(узел->rhs);
случай ND_CAST:
если (is_flonum(узел->lhs->ty)) возврат вычробное(узел->lhs);
возврат вычислить(узел->lhs);
случай ND_NUM: возврат узел->fval;
}
error_tok(узел->tok, "не является константой времени компиляции");
}
стат Node *преобр_в_присв(Node *бин) {
add_type(бин->lhs);
add_type(бин->rhs);
Token *ток = бин->tok;
если (бин->lhs->kind == ND_MEMBER) {
Obj *перем = создатьок_перем("", pointer_to(бин->lhs->lhs->ty));
Node *в1 = создать_бин_узел(ND_ASSIGN, создать_узел_перем(перем, ток),
создать_ун_узел(ND_ADDR, бин->lhs->lhs, ток), ток);
Node *в2 = создать_ун_узел(ND_MEMBER,
создать_ун_узел(ND_DEREF, создать_узел_перем(перем, ток), ток), ток);
в2->member = бин->lhs->member;
Node *в3 = создать_ун_узел(ND_MEMBER,
создать_ун_узел(ND_DEREF, создать_узел_перем(перем, ток), ток), ток);
в3->member = бин->lhs->member;
Node *в4 = создать_бин_узел(ND_ASSIGN, в2,
создать_бин_узел(бин->kind, в3, бин->rhs, ток), ток);
возврат создать_бин_узел(ND_COMMA, в1, в4, ток);
}
если (бин->lhs->ty->is_atomic) {
Node голова = {};
Node *тек = &голова;
Obj *адр = создатьок_перем("", pointer_to(бин->lhs->ty));
Obj *знач = создатьок_перем("", бин->rhs->ty);
Obj *стар = создатьок_перем("", бин->lhs->ty);
Obj *нов = создатьок_перем("", бин->lhs->ty);
тек = тек->next = создать_ун_узел(ND_EXPR_STMT,
создать_бин_узел(ND_ASSIGN, создать_узел_перем(адр, ток),
создать_ун_узел(ND_ADDR, бин->lhs, ток), ток), ток);
тек = тек->next = создать_ун_узел(ND_EXPR_STMT,
создать_бин_узел(ND_ASSIGN, создать_узел_перем(знач, ток), бин->rhs, ток), ток);
тек = тек->next = создать_ун_узел(ND_EXPR_STMT,
создать_бин_узел(ND_ASSIGN, создать_узел_перем(стар, ток),
создать_ун_узел(ND_DEREF, создать_узел_перем(адр, ток), ток), ток), ток);
Node *цикл = создать_узел(ND_DO, ток);
цикл->brk_label = создать_уник_метку();
цикл->cont_label = создать_уник_метку();
Node *тело = создать_бин_узел(ND_ASSIGN, создать_узел_перем(нов, ток),
создать_бин_узел(бин->kind, создать_узел_перем(стар, ток), создать_узел_перем(знач, ток), ток), ток);
цикл->then = создать_узел(ND_BLOCK, ток);
цикл->then->body = создать_ун_узел(ND_EXPR_STMT, тело, ток);
Node *cas = создать_узел(ND_CAS, ток);
cas->cas_addr = создать_узел_перем(адр, ток);
cas->cas_old = создать_ун_узел(ND_ADDR, создать_узел_перем(стар, ток), ток);
cas->cas_new = создать_узел_перем(нов, ток);
цикл->cond = создать_ун_узел(ND_NOT, cas, ток);
тек = тек->next = цикл;
тек = тек->next = создать_ун_узел(ND_EXPR_STMT, создать_узел_перем(нов, ток), ток);
Node *узел = создать_узел(ND_STMT_EXPR, ток);
узел->body = голова.next;
возврат узел;
}
Obj *перем = создатьок_перем("", pointer_to(бин->lhs->ty));
Node *в1 = создать_бин_узел(ND_ASSIGN, создать_узел_перем(перем, ток),
создать_ун_узел(ND_ADDR, бин->lhs, ток), ток);
Node *в2 = создать_бин_узел(ND_ASSIGN,
создать_ун_узел(ND_DEREF, создать_узел_перем(перем, ток), ток),
создать_бин_узел(бин->kind,
создать_ун_узел(ND_DEREF, создать_узел_перем(перем, ток), ток),
бин->rhs, ток), ток);
возврат создать_бин_узел(ND_COMMA, в1, в2, ток);
}
стат Node *присваивание(Token **остаток, Token *ток) {
Node *узел = условное(&ток, ток);
если (equal(ток, "=")) возврат создать_бин_узел(ND_ASSIGN, узел, присваивание(остаток, ток->next), ток);
если (equal(ток, "+=")) возврат преобр_в_присв(нов_слож(узел, присваивание(остаток, ток->next), ток));
если (equal(ток, "-=")) возврат преобр_в_присв(нов_выч(узел, присваивание(остаток, ток->next), ток));
если (equal(ток, "*=")) возврат преобр_в_присв(создать_бин_узел(ND_MUL, узел, присваивание(остаток, ток->next), ток));
если (equal(ток, "/=")) возврат преобр_в_присв(создать_бин_узел(ND_DIV, узел, присваивание(остаток, ток->next), ток));
если (equal(ток, "%=")) возврат преобр_в_присв(создать_бин_узел(ND_MOD, узел, присваивание(остаток, ток->next), ток));
если (equal(ток, "&=")) возврат преобр_в_присв(создать_бин_узел(ND_BITAND, узел, присваивание(остаток, ток->next), ток));
если (equal(ток, "|=")) возврат преобр_в_присв(создать_бин_узел(ND_BITOR, узел, присваивание(остаток, ток->next), ток));
если (equal(ток, "^=")) возврат преобр_в_присв(создать_бин_узел(ND_BITXOR, узел, присваивание(остаток, ток->next), ток));
если (equal(ток, "<<=")) возврат преобр_в_присв(создать_бин_узел(ND_SHL, узел, присваивание(остаток, ток->next), ток));
если (equal(ток, ">>=")) возврат преобр_в_присв(создать_бин_узел(ND_SHR, узел, присваивание(остаток, ток->next), ток));
*остаток = ток;
возврат узел;
}
стат Node *условное(Token **остаток, Token *ток) {
Node *усл = лог_или(&ток, ток);
если (!equal(ток, "?")) { *остаток = ток; возврат усл; }
если (equal(ток->next, ":")) {
add_type(усл);
Obj *перем = создатьок_перем("", усл->ty);
Node *лев = создать_бин_узел(ND_ASSIGN, создать_узел_перем(перем, ток), усл, ток);
Node *прав = создать_узел(ND_COND, ток);
прав->cond = создать_узел_перем(перем, ток);
прав->then = создать_узел_перем(перем, ток);
прав->els = условное(остаток, ток->next->next);
возврат создать_бин_узел(ND_COMMA, лев, прав, ток);
}
Node *узел = создать_узел(ND_COND, ток);
узел->cond = усл;
узел->then = выражение(&ток, ток->next);
ток = skip(ток, ":");
узел->els = условное(остаток, ток);
возврат узел;
}
стат Node *лог_или(Token **остаток, Token *ток) {
Node *узел = лог(&ток, ток);
пока (equal(ток, "||")) { Token *старт = ток; узел = создать_бин_узел(ND_LOGOR, узел, лог(&ток, ток->next), старт); }
*остаток = ток;
возврат узел;
}
стат Node *лог(Token **остаток, Token *ток) {
Node *узел = побит_или(&ток, ток);
пока (equal(ток, "&&")) { Token *старт = ток; узел = создать_бин_узел(ND_LOGAND, узел, побит_или(&ток, ток->next), старт); }
*остаток = ток;
возврат узел;
}
стат Node *побит_или(Token **остаток, Token *ток) {
Node *узел = побитскл_или(&ток, ток);
пока (equal(ток, "|")) { Token *старт = ток; узел = создать_бин_узел(ND_BITOR, узел, побитскл_или(&ток, ток->next), старт); }
*остаток = ток;
возврат узел;
}
стат Node *побитскл_или(Token **остаток, Token *ток) {
Node *узел = побит(&ток, ток);
пока (equal(ток, "^")) { Token *старт = ток; узел = создать_бин_узел(ND_BITXOR, узел, побит(&ток, ток->next), старт); }
*остаток = ток;
возврат узел;
}
стат Node *побит(Token **остаток, Token *ток) {
Node *узел = равенство(&ток, ток);
пока (equal(ток, "&")) { Token *старт = ток; узел = создать_бин_узел(ND_BITAND, узел, равенство(&ток, ток->next), старт); }
*остаток = ток;
возврат узел;
}
стат Node *равенство(Token **остаток, Token *ток) {
Node *узел = сравнение(&ток, ток);
для (;;) {
Token *старт = ток;
если (equal(ток, "==")) { узел = создать_бин_узел(ND_EQ, узел, сравнение(&ток, ток->next), старт); продолжи; }
если (equal(ток, "!=")) { узел = создать_бин_узел(ND_NE, узел, сравнение(&ток, ток->next), старт); продолжи; }
*остаток = ток;
возврат узел;
}
}
стат Node *сравнение(Token **остаток, Token *ток) {
Node *узел = сдвиг(&ток, ток);
для (;;) {
Token *старт = ток;
если (equal(ток, "<")) { узел = создать_бин_узел(ND_LT, узел, сдвиг(&ток, ток->next), старт); продолжи; }
если (equal(ток, "<=")) { узел = создать_бин_узел(ND_LE, узел, сдвиг(&ток, ток->next), старт); продолжи; }
если (equal(ток, ">")) { узел = создать_бин_узел(ND_LT, сдвиг(&ток, ток->next), узел, старт); продолжи; }
если (equal(ток, ">=")) { узел = создать_бин_узел(ND_LE, сдвиг(&ток, ток->next), узел, старт); продолжи; }
*остаток = ток;
возврат узел;
}
}
стат Node *сдвиг(Token **остаток, Token *ток) {
Node *узел = сложение(&ток, ток);
для (;;) {
Token *старт = ток;
если (equal(ток, "<<")) { узел = создать_бин_узел(ND_SHL, узел, сложение(&ток, ток->next), старт); продолжи; }
если (equal(ток, ">>")) { узел = создать_бин_узел(ND_SHR, узел, сложение(&ток, ток->next), старт); продолжи; }
*остаток = ток;
возврат узел;
}
}
стат Node *нов_слож(Node *лев, Node *прав, Token *ток) {
add_type(лев);
add_type(прав);
если (is_numeric(лев->ty) && is_numeric(прав->ty)) возврат создать_бин_узел(ND_ADD, лев, прав, ток);
если (лев->ty->base && прав->ty->base) error_tok(ток, "недопустимые операнды");
если (!лев->ty->base && прав->ty->base) { Node *вр = лев; лев = прав; прав = вр; }
если (лев->ty->base->kind == TY_VLA) {
прав = создать_бин_узел(ND_MUL, прав, создать_узел_перем(лев->ty->base->vla_size, ток), ток);
возврат создать_бин_узел(ND_ADD, лев, прав, ток);
}
прав = создать_бин_узел(ND_MUL, прав, создать_длин_число(лев->ty->base->size, ток), ток);
возврат создать_бин_узел(ND_ADD, лев, прав, ток);
}
стат Node *нов_выч(Node *лев, Node *прав, Token *ток) {
add_type(лев);
add_type(прав);
если (is_numeric(лев->ty) && is_numeric(прав->ty)) возврат создать_бин_узел(ND_SUB, лев, прав, ток);
если (лев->ty->base->kind == TY_VLA) {
прав = создать_бин_узел(ND_MUL, прав, создать_узел_перем(лев->ty->base->vla_size, ток), ток);
add_type(прав);
Node *узел = создать_бин_узел(ND_SUB, лев, прав, ток);
узел->ty = лев->ty;
возврат узел;
}
если (лев->ty->base && is_integer(прав->ty)) {
прав = создать_бин_узел(ND_MUL, прав, создать_длин_число(лев->ty->base->size, ток), ток);
add_type(прав);
Node *узел = создать_бин_узел(ND_SUB, лев, прав, ток);
узел->ty = лев->ty;
возврат узел;
}
если (лев->ty->base && прав->ty->base) {
Node *узел = создать_бин_узел(ND_SUB, лев, прав, ток);
узел->ty = ty_long;
возврат создать_бин_узел(ND_DIV, узел, создать_число(лев->ty->base->size, ток), ток);
}
error_tok(ток, "недопустимые операнды");
}
стат Node *сложение(Token **остаток, Token *ток) {
Node *узел = умножение(&ток, ток);
для (;;) {
Token *старт = ток;
если (equal(ток, "+")) { узел = нов_слож(узел, умножение(&ток, ток->next), старт); продолжи; }
если (equal(ток, "-")) { узел = нов_выч(узел, умножение(&ток, ток->next), старт); продолжи; }
*остаток = ток;
возврат узел;
}
}
стат Node *умножение(Token **остаток, Token *ток) {
Node *узел = приведение(&ток, ток);
для (;;) {
Token *старт = ток;
если (equal(ток, "*")) { узел = создать_бин_узел(ND_MUL, узел, приведение(&ток, ток->next), старт); продолжи; }
если (equal(ток, "/")) { узел = создать_бин_узел(ND_DIV, узел, приведение(&ток, ток->next), старт); продолжи; }
если (equal(ток, "%")) { узел = создать_бин_узел(ND_MOD, узел, приведение(&ток, ток->next), старт); продолжи; }
*остаток = ток;
возврат узел;
}
}
стат Node *приведение(Token **остаток, Token *ток) {
если (equal(ток, "(") && это_имя_типа(ток->next)) {
Token *старт = ток;
Type *тип = имя_типа(&ток, ток->next);
ток = skip(ток, ")");
если (equal(ток, "{")) возврат унарный(остаток, старт);
Node *узел = new_cast(приведение(остаток, ток), тип);
узел->tok = старт;
возврат узел;
}
возврат унарный(остаток, ток);
}
стат Node *унарный(Token **остаток, Token *ток) {
если (equal(ток, "+")) возврат приведение(остаток, ток->next);
если (equal(ток, "-")) возврат создать_ун_узел(ND_NEG, приведение(остаток, ток->next), ток);
если (equal(ток, "&")) {
Node *лев = приведение(остаток, ток->next);
add_type(лев);
если (лев->kind == ND_MEMBER && лев->member->is_bitfield)
error_tok(ток, "невозможно взять адрес битового поля");
возврат создать_ун_узел(ND_ADDR, лев, ток);
}
если (equal(ток, "*")) {
Node *узел = приведение(остаток, ток->next);
add_type(узел);
если (узел->ty->kind == TY_FUNC) возврат узел;
возврат создать_ун_узел(ND_DEREF, узел, ток);
}
если (equal(ток, "!")) возврат создать_ун_узел(ND_NOT, приведение(остаток, ток->next), ток);
если (equal(ток, "~")) возврат создать_ун_узел(ND_BITNOT, приведение(остаток, ток->next), ток);
если (equal(ток, "++")) возврат преобр_в_присв(нов_слож(унарный(остаток, ток->next), создать_число(1, ток), ток));
если (equal(ток, "--")) возврат преобр_в_присв(нов_выч(унарный(остаток, ток->next), создать_число(1, ток), ток));
если (equal(ток, "&&")) {
Node *узел = создать_узел(ND_LABEL_VAL, ток);
узел->label = извлечь_ид(ток->next);
узел->goto_next = ожид_goto;
ожид_goto = узел;
*остаток = ток->next->next;
возврат узел;
}
возврат постфикс(остаток, ток);
}
стат пусто разбор_членов_стр(Token **остаток, Token *ток, Type *тип) {
Member голова = {};
Member *тек = &голова;
цел инд = 0;
пока (!equal(ток, "}")) {
АтрПерем атр = {};
Type *баз = спецификатор_типа(&ток, ток, &атр);
бул первый = истина;
если ((баз->kind == TY_STRUCT || баз->kind == TY_UNION) && consume(&ток, ток, ";")) {
Member *член = calloc(1, размер(Member));
член->ty = баз;
член->idx = инд++;
член->align = атр.выравн ? атр.выравн : член->ty->align;
тек = тек->next = член;
продолжи;
}
пока (!consume(&ток, ток, ";")) {
если (!первый) ток = skip(ток, ",");
первый = ложь;
Member *член = calloc(1, размер(Member));
член->ty = декларатор(&ток, ток, баз);
член->name = член->ty->name;
член->idx = инд++;
член->align = атр.выравн ? атр.выравн : член->ty->align;
если (consume(&ток, ток, ":")) { член->is_bitfield = истина; член->bit_width = const_expr(&ток, ток); }
тек = тек->next = член;
}
}
если (тек != &голова && тек->ty->kind == TY_ARRAY && тек->ty->array_len < 0) {
тек->ty = array_of(тек->ty->base, 0);
тип->is_flexible = истина;
}
*остаток = ток->next;
тип->members = голова.next;
}
стат Token *разбор_атриб(Token *ток, Type *тип) {
пока (consume(&ток, ток, "__attribute__")) {
ток = skip(ток, "(");
ток = skip(ток, "(");
бул первый = истина;
пока (!consume(&ток, ток, ")")) {
если (!первый) ток = skip(ток, ",");
первый = ложь;
если (consume(&ток, ток, "packed")) { тип->is_packed = истина; продолжи; }
если (consume(&ток, ток, "aligned")) { ток = skip(ток, "("); тип->align = const_expr(&ток, ток); ток = skip(ток, ")"); продолжи; }
error_tok(ток, "неизвестный атрибут");
}
ток = skip(ток, ")");
}
возврат ток;
}
стат Type *разбор_стр_объед(Token **остаток, Token *ток) {
Type *тип = struct_type();
ток = разбор_атриб(ток, тип);
Token *тег = NULL;
если (ток->kind == TK_IDENT) { тег = ток; ток = ток->next; }
если (тег && !equal(ток, "{")) {
*остаток = ток;
Type *т2 = найтиег(тег);
если (т2) возврат т2;
тип->size = -1;
зарегег(тег, тип);
возврат тип;
}
ток = skip(ток, "{");
разбор_членов_стр(&ток, ток, тип);
*остаток = разбор_атриб(ток, тип);
если (тег) {
Type *т2 = хеш_получить2(&тек_обл->теги, тег->loc, тег->len);
если (т2) { *т2 = *тип; возврат т2; }
зарегег(тег, тип);
}
возврат тип;
}
стат Type *объяв_структ(Token **остаток, Token *ток) {
Type *тип = разбор_стр_объед(остаток, ток);
тип->kind = TY_STRUCT;
если (тип->size < 0) возврат тип;
цел биты = 0;
для (Member *член = тип->members; член; член = член->next) {
если (член->is_bitfield && член->bit_width == 0) {
биты = align_to(биты, член->ty->size * 8);
} иначе если (член->is_bitfield) {
цел разм = член->ty->size;
если (биты / (разм * 8) != (биты + член->bit_width - 1) / (разм * 8))
биты = align_to(биты, разм * 8);
член->offset = округлить_вниз(биты / 8, разм);
член->bit_offset = биты % (разм * 8);
биты += член->bit_width;
} иначе {
если (!тип->is_packed) биты = align_to(биты, член->align * 8);
член->offset = биты / 8;
биты += член->ty->size * 8;
}
если (!тип->is_packed && тип->align < член->align) тип->align = член->align;
}
тип->size = align_to(биты, тип->align * 8) / 8;
возврат тип;
}
стат Type *объяв_объед(Token **остаток, Token *ток) {
Type *тип = разбор_стр_объед(остаток, ток);
тип->kind = TY_UNION;
если (тип->size < 0) возврат тип;
для (Member *член = тип->members; член; член = член->next) {
если (тип->align < член->align) тип->align = член->align;
если (тип->size < член->ty->size) тип->size = член->ty->size;
}
тип->size = align_to(тип->size, тип->align);
возврат тип;
}
стат Member *найти_член(Type *тип, Token *ток) {
для (Member *член = тип->members; член; член = член->next) {
если ((член->ty->kind == TY_STRUCT || член->ty->kind == TY_UNION) && !член->name) {
если (найти_член(член->ty, ток)) возврат член;
продолжи;
}
если (член->name->len == ток->len && !strncmp(член->name->loc, ток->loc, ток->len))
возврат член;
}
возврат NULL;
}
стат Member *найти_член_стр(Type *тип, Token *ток) { возврат найти_член(тип, ток); }
стат Node *создатьоступ_к_члену(Node *узел, Token *ток) {
add_type(узел);
если (узел->ty->kind != TY_STRUCT && узел->ty->kind != TY_UNION)
error_tok(узел->tok, "не является структурой или объединением");
Type *тип = узел->ty;
для (;;) {
Member *член = найти_член(тип, ток);
если (!член) error_tok(ток, "нет такого члена");
узел = создать_ун_узел(ND_MEMBER, узел, ток);
узел->member = член;
если (член->name) прерви;
тип = член->ty;
}
возврат узел;
}
стат Node *создать_инкрем_декрем(Node *узел, Token *ток, цел доб) {
add_type(узел);
возврат new_cast(нов_слож(преобр_в_присв(нов_слож(узел, создать_число(доб, ток), ток)),
создать_число(-доб, ток), ток), узел->ty);
}
стат Node *постфикс(Token **остаток, Token *ток) {
если (equal(ток, "(") && это_имя_типа(ток->next)) {
Token *старт = ток;
Type *тип = имя_типа(&ток, ток->next);
ток = skip(ток, ")");
если (тек_обл->след == NULL) {
Obj *перем = создать_аноним_глоб(тип);
иниц_глоб_перем(остаток, ток, перем);
возврат создать_узел_перем(перем, старт);
}
Obj *перем = создатьок_перем("", тип);
Node *лев = иницок_перем(остаток, ток, перем);
Node *прав = создать_узел_перем(перем, ток);
возврат создать_бин_узел(ND_COMMA, лев, прав, старт);
}
Node *узел = первичный(&ток, ток);
для (;;) {
если (equal(ток, "(")) { узел = вызов_фн(&ток, ток->next, узел); продолжи; }
если (equal(ток, "[")) {
Token *старт = ток;
Node *инд = выражение(&ток, ток->next);
ток = skip(ток, "]");
узел = создать_ун_узел(ND_DEREF, нов_слож(узел, инд, старт), старт);
продолжи;
}
если (equal(ток, ".")) { узел = создатьоступ_к_члену(узел, ток->next); ток = ток->next->next; продолжи; }
если (equal(ток, "->")) { узел = создать_ун_узел(ND_DEREF, узел, ток); узел = создатьоступ_к_члену(узел, ток->next); ток = ток->next->next; продолжи; }
если (equal(ток, "++")) { узел = создать_инкрем_декрем(узел, ток, 1); ток = ток->next; продолжи; }
если (equal(ток, "--")) { узел = создать_инкрем_декрем(узел, ток, -1); ток = ток->next; продолжи; }
*остаток = ток;
возврат узел;
}
}
стат Node *вызов_фн(Token **остаток, Token *ток, Node *фн) {
add_type(фн);
если (фн->ty->kind != TY_FUNC && (фн->ty->kind != TY_PTR || фн->ty->base->kind != TY_FUNC))
error_tok(фн->tok, "не является функцией");
Type *тип = (фн->ty->kind == TY_FUNC) ? фн->ty : фн->ty->base;
Type *тип_парам = тип->params;
Node голова = {};
Node *тек = &голова;
пока (!equal(ток, ")")) {
если (тек != &голова) ток = skip(ток, ",");
Node *арг = присваивание(&ток, ток);
add_type(арг);
если (!тип_парам && !тип->is_variadic) error_tok(ток, "слишком много аргументов");
если (тип_парам) {
если (тип_парам->kind != TY_STRUCT && тип_парам->kind != TY_UNION)
арг = new_cast(арг, тип_парам);
тип_парам = тип_парам->next;
} иначе если (арг->ty->kind == TY_FLOAT) { арг = new_cast(арг, ty_double); }
тек = тек->next = арг;
}
если (тип_парам) error_tok(ток, "слишком мало аргументов");
*остаток = skip(ток, ")");
Node *узел = создать_ун_узел(ND_FUNCALL, фн, ток);
узел->func_ty = тип;
узел->ty = тип->return_ty;
узел->args = голова.next;
если (узел->ty->kind == TY_STRUCT || узел->ty->kind == TY_UNION)
узел->ret_buffer = создатьок_перем("", узел->ty);
возврат узел;
}
стат Node *разбор_обобщ(Token **остаток, Token *ток) {
Token *старт = ток;
ток = skip(ток, "(");
Node *упр = присваивание(&ток, ток);
add_type(упр);
Type *т1 = упр->ty;
если (т1->kind == TY_FUNC) т1 = pointer_to(т1);
иначе если (т1->kind == TY_ARRAY) т1 = pointer_to(т1->base);
Node *рез = NULL;
пока (!consume(остаток, ток, ")")) {
ток = skip(ток, ",");
если ((equal(ток, "default") || equal(ток, "умолч"))) {
ток = skip(ток->next, ":");
Node *узел = присваивание(&ток, ток);
если (!рез) рез = узел;
продолжи;
}
Type *т2 = имя_типа(&ток, ток);
ток = skip(ток, ":");
Node *узел = присваивание(&ток, ток);
если (is_compatible(т1, т2)) рез = узел;
}
если (!рез) error_tok(старт, "тип управляющего выражения не совместим ни с одним типом обобщенной ассоциации");
возврат рез;
}
стат Node *первичный(Token **остаток, Token *ток) {
Token *старт = ток;
если (equal(ток, "(") && equal(ток->next, "{")) {
Node *узел = создать_узел(ND_STMT_EXPR, ток);
узел->body = составной_оператор(&ток, ток->next->next)->body;
*остаток = skip(ток, ")");
возврат узел;
}
если (equal(ток, "(")) { Node *узел = выражение(&ток, ток->next); *остаток = skip(ток, ")"); возврат узел; }
если ((equal(ток, "sizeof") || equal(ток, "размер")) && equal(ток->next, "(") && это_имя_типа(ток->next->next)) {
Type *тип = имя_типа(&ток, ток->next->next);
*остаток = skip(ток, ")");
если (тип->kind == TY_VLA) {
если (тип->vla_size) возврат создать_узел_перем(тип->vla_size, ток);
Node *лев = создать_выч_vla(тип, ток);
Node *прав = создать_узел_перем(тип->vla_size, ток);
возврат создать_бин_узел(ND_COMMA, лев, прав, ток);
}
возврат создать_бузн_длин_число(тип->size, старт);
}
если ((equal(ток, "sizeof") || equal(ток, "размер"))) {
Node *узел = унарный(остаток, ток->next);
add_type(узел);
если (узел->ty->kind == TY_VLA) возврат создать_узел_перем(узел->ty->vla_size, ток);
возврат создать_бузн_длин_число(узел->ty->size, ток);
}
если ((equal(ток, "_Alignof") || equal(ток, "_Выравнивание_типа")) && equal(ток->next, "(") && это_имя_типа(ток->next->next)) {
Type *тип = имя_типа(&ток, ток->next->next);
*остаток = skip(ток, ")");
возврат создать_бузн_длин_число(тип->align, ток);
}
если (equal(ток, "_Alignof") || equal(ток, "_Выравнивание_типа")) {
Node *узел = унарный(остаток, ток->next);
add_type(узел);
возврат создать_бузн_длин_число(узел->ty->align, ток);
}
если (equal(ток, "_Generic") || equal(ток, "_Обобщ")) возврат разбор_обобщ(остаток, ток->next);
если (equal(ток, "__builtin_types_compatible_p")) {
ток = skip(ток->next, "(");
Type *т1 = имя_типа(&ток, ток);
ток = skip(ток, ",");
Type *т2 = имя_типа(&ток, ток);
*остаток = skip(ток, ")");
возврат создать_число(is_compatible(т1, т2), старт);
}
если (equal(ток, "__builtin_reg_class")) {
ток = skip(ток->next, "(");
Type *тип = имя_типа(&ток, ток);
*остаток = skip(ток, ")");
если (is_integer(тип) || тип->kind == TY_PTR) возврат создать_число(0, старт);
если (is_flonum(тип)) возврат создать_число(1, старт);
возврат создать_число(2, старт);
}
если (equal(ток, "__builtin_compare_and_swap")) {
Node *узел = создать_узел(ND_CAS, ток);
ток = skip(ток->next, "(");
узел->cas_addr = присваивание(&ток, ток);
ток = skip(ток, ",");
узел->cas_old = присваивание(&ток, ток);
ток = skip(ток, ",");
узел->cas_new = присваивание(&ток, ток);
*остаток = skip(ток, ")");
возврат узел;
}
если (equal(ток, "__builtin_atomic_exchange")) {
Node *узел = создать_узел(ND_EXCH, ток);
ток = skip(ток->next, "(");
узел->lhs = присваивание(&ток, ток);
ток = skip(ток, ",");
узел->rhs = присваивание(&ток, ток);
*остаток = skip(ток, ")");
возврат узел;
}
если (ток->kind == TK_IDENT) {
ОблПерем *обл = найти_перем(ток);
*остаток = ток->next;
если (обл && обл->перем && обл->перем->is_function) {
если (актункция) массив_строк_добавить(&актункция->refs, обл->перем->name);
иначе обл->перем->is_root = истина;
}
если (обл) {
если (обл->перем) возврат создать_узел_перем(обл->перем, ток);
если (обл->тип_переч) возврат создать_число(обл->знач_переч, ток);
}
если (equal(ток->next, "(")) error_tok(ток, "неявное объявление функции");
error_tok(ток, "неопределенная переменная");
}
если (ток->kind == TK_STR) {
Obj *перем = создать_строк_литерал(ток->str, ток->ty);
*остаток = ток->next;
возврат создать_узел_перем(перем, ток);
}
если (ток->kind == TK_NUM) {
Node *узел;
если (is_flonum(ток->ty)) { узел = создать_узел(ND_NUM, ток); узел->fval = ток->fval; }
иначе { узел = создать_число(ток->val, ток); }
узел->ty = ток->ty;
*остаток = ток->next;
возврат узел;
}
error_tok(ток, "ожидалось выражение");
}
стат Token *разбор_типдеф(Token *ток, Type *баз_тип) {
бул первый = истина;
пока (!consume(&ток, ток, ";")) {
если (!первый) ток = skip(ток, ",");
первый = ложь;
Type *тип = декларатор(&ток, ток, баз_тип);
если (!тип->name) error_tok(тип->name_pos, "имя типдеф опущено");
зарег_перем(извлечь_ид(тип->name))->определение_типа = тип;
}
возврат ток;
}
стат пусто зарег_парам(Type *парам) {
если (парам) {
зарег_парам(парам->next);
если (!парам->name) error_tok(парам->name_pos, "имя параметра опущено");
создатьок_перем(извлечь_ид(парам->name), парам);
}
}
стат пусто связатьетки(пусто) {
для (Node *x = ожид_goto; x; x = x->goto_next) {
для (Node *y = опредетки; y; y = y->goto_next) {
если (!strcmp(x->label, y->label)) { x->unique_label = y->unique_label; прерви; }
}
если (x->unique_label == NULL) error_tok(x->tok->next, "использование необъявленной метки");
}
ожид_goto = опредетки = NULL;
}
стат Obj *найтиункцию(символ *имя) {
Область *обл = тек_обл;
пока (обл->след) обл = обл->след;
ОблПерем *обл2 = хеш_получить(&обл->перем, имя);
если (обл2 && обл2->перем && обл2->перем->is_function) возврат обл2->перем;
возврат NULL;
}
стат пусто пометить_живой(Obj *перем) {
если (!перем->is_function || перем->is_live) возврат;
перем->is_live = истина;
для (цел ш = 0; ш < перем->refs.len; ш++) {
Obj *фн = найтиункцию(перем->refs.data[ш]);
если (фн) пометить_живой(фн);
}
}
стат Token *функция(Token *ток, Type *баз_тип, АтрПерем *атр) {
Type *тип = декларатор(&ток, ток, баз_тип);
если (!тип->name) error_tok(тип->name_pos, "имя функции опущено");
символ *имя_стр = извлечь_ид(тип->name);
Obj *фн = найтиункцию(имя_стр);
если (фн) {
если (!фн->is_function) error_tok(ток, "переобъявлено как символ другого вида");
если (фн->is_definition && equal(ток, "{")) error_tok(ток, "переопределение %s", имя_стр);
если (!фн->is_static && атр->это_статик) error_tok(ток, "статическое объявление следует за нестатическим");
фн->is_definition = фн->is_definition || equal(ток, "{");
} иначе {
фн = создать_глоб_перем(имя_стр, тип);
фн->is_function = истина;
фн->is_definition = equal(ток, "{");
фн->is_static = атр->это_статик || (атр->это_инлайн && !атр->это_внеш);
фн->is_inline = атр->это_инлайн;
}
фн->is_root = !(фн->is_static && фн->is_inline);
если (consume(&ток, ток, ";")) возврат ток;
актункция = фн;
лок_перем = NULL;
войти_в_обл();
зарег_парам(тип->params);
Type *rty = тип->return_ty;
если ((rty->kind == TY_STRUCT || rty->kind == TY_UNION) && rty->size > 16)
создатьок_перем("", pointer_to(rty));
фн->params = лок_перем;
если (тип->is_variadic)
фн->va_area = создатьок_перем("__va_area__", array_of(ty_char, 136));
фн->alloca_bottom = создатьок_перем("__alloca_size__", pointer_to(ty_char));
ток = skip(ток, "{");
зарег_перем("__func__")->перем = создать_строк_литерал(фн->name, array_of(ty_char, strlen(фн->name) + 1));
зарег_перем("__FUNCTION__")->перем = создать_строк_литерал(фн->name, array_of(ty_char, strlen(фн->name) + 1));
зарег_перем("__функ__")->перем = создать_строк_литерал(фн->name, array_of(ty_char, strlen(фн->name) + 1));
зарег_перем("__ФУНКЦИЯ__")->перем = создать_строк_литерал(фн->name, array_of(ty_char, strlen(фн->name) + 1));
фн->body = составной_оператор(&ток, ток);
фн->locals = лок_перем;
выйти_из_обл();
связатьетки();
возврат ток;
}
стат Token *глоб_перем_объяв(Token *ток, Type *баз_тип, АтрПерем *атр) {
бул первый = истина;
пока (!consume(&ток, ток, ";")) {
если (!первый) ток = skip(ток, ",");
первый = ложь;
Type *тип = декларатор(&ток, ток, баз_тип);
если (!тип->name) error_tok(тип->name_pos, "имя переменной опущено");
Obj *перем = создать_глоб_перем(извлечь_ид(тип->name), тип);
перем->is_definition = !атр->это_внеш;
перем->is_static = атр->это_статик;
перем->is_tls = атр->это_tls;
если (атр->выравн) перем->align = атр->выравн;
если (equal(ток, "=")) иниц_глоб_перем(&ток, ток->next, перем);
иначе если (!атр->это_внеш && !атр->это_tls) перем->is_tentative = истина;
}
возврат ток;
}
стат бул этоункция(Token *ток) {
если (equal(ток, ";")) возврат ложь;
Type загл = {};
Type *тип = декларатор(&ток, ток, &загл);
возврат тип->kind == TY_FUNC;
}
стат пусто убрать_лишниеендат(пусто) {
Obj голова;
Obj *тек = &голова;
для (Obj *перем = глоб_перем; перем; перем = перем->next) {
если (!перем->is_tentative) { тек = тек->next = перем; продолжи; }
Obj *п2 = глоб_перем;
для (; п2; п2 = п2->next)
если (перем != п2 && п2->is_definition && !strcmp(перем->name, п2->name)) прерви;
если (!п2) тек = тек->next = перем;
}
тек->next = NULL;
глоб_перем = голова.next;
}
стат пусто зарегстр_фн(пусто) {
Type *тип = func_type(pointer_to(ty_void));
тип->params = copy_type(ty_int);
встр_alloca = создать_глоб_перем("alloca", тип);
встр_alloca->is_definition = ложь;
}
Obj *parse(Token *ток) {
зарегстр_фн();
глоб_перем = NULL;
пока (ток->kind != TK_EOF) {
АтрПерем атр = {};
Type *баз = спецификатор_типа(&ток, ток, &атр);
если (атр.это_типдеф) { ток = разбор_типдеф(ток, баз); продолжи; }
если (этоункция(ток)) { ток = функция(ток, баз, &атр); продолжи; }
ток = глоб_перем_объяв(ток, баз, &атр);
}
для (Obj *перем = глоб_перем; перем; перем = перем->next)
если (перем->is_root) пометить_живой(перем);
убрать_лишниеендат();
возврат глоб_перем;
}