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