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