rusi/parse.c

2096 lines
111 KiB
C
Raw Permalink Normal View History

// Этот файл содержит рекурсивный спуск-парсер для языка 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) пометить_живой(перем);
убрать_лишниеендат();
возврат глоб_перем;
}