From 9c202a496e75903fe37e5c19cb97c98eba6e35f2 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Fri, 22 Aug 2025 23:28:25 +0900 Subject: chore: move *.c and *.h files to src/ --- parse.c | 1404 --------------------------------------------------------------- 1 file changed, 1404 deletions(-) delete mode 100644 parse.c (limited to 'parse.c') diff --git a/parse.c b/parse.c deleted file mode 100644 index 8f06a83..0000000 --- a/parse.c +++ /dev/null @@ -1,1404 +0,0 @@ -#define LVAR_MAX 32 - -struct LocalVar { - const char* name; - Type* ty; - int stack_offset; -}; -typedef struct LocalVar LocalVar; - -struct Scope { - struct Scope* outer; - const char** lvar_names; - int* lvar_indices; -}; -typedef struct Scope Scope; - -struct GlobalVar { - const char* name; - Type* ty; -}; -typedef struct GlobalVar GlobalVar; - -struct Func { - const char* name; - Type* ty; -}; -typedef struct Func Func; - -struct Parser { - TokenArray* tokens; - int pos; - LocalVar* lvars; - int n_lvars; - Scope* scope; - GlobalVar* gvars; - int n_gvars; - Func* funcs; - int n_funcs; - AstNode* structs; - int n_structs; - AstNode* unions; - int n_unions; - AstNode* enums; - int n_enums; - AstNode* typedefs; - int n_typedefs; - const char** str_literals; - int n_str_literals; -}; -typedef struct Parser Parser; - -Parser* parser_new(TokenArray* tokens) { - Parser* p = calloc(1, sizeof(Parser)); - p->tokens = tokens; - p->gvars = calloc(128, sizeof(GlobalVar)); - p->funcs = calloc(256, sizeof(Func)); - p->structs = calloc(64, sizeof(AstNode)); - p->unions = calloc(64, sizeof(AstNode)); - p->enums = calloc(16, sizeof(AstNode)); - p->typedefs = calloc(64, sizeof(AstNode)); - p->str_literals = calloc(1024, sizeof(char*)); - - p->funcs[p->n_funcs].name = "__ducc_va_start"; - p->funcs[p->n_funcs].ty = calloc(1, sizeof(Type)); - p->funcs[p->n_funcs].ty->kind = TypeKind_void; - ++p->n_funcs; - - return p; -} - -Token* peek_token(Parser* p) { - return &p->tokens->data[p->pos]; -} - -Token* next_token(Parser* p) { - return &p->tokens->data[p->pos++]; -} - -Token* consume_token_if(Parser* p, TokenKind expected) { - if (peek_token(p)->kind == expected) { - return next_token(p); - } else { - return NULL; - } -} - -BOOL eof(Parser* p) { - return peek_token(p)->kind != TokenKind_eof; -} - -Token* expect(Parser* p, TokenKind expected) { - Token* t = next_token(p); - if (t->kind == expected) { - return t; - } - fatal_error("%s:%d: expected '%s', but got '%s'", t->loc.filename, t->loc.line, token_kind_stringify(expected), - token_stringify(t)); -} - -int find_lvar_in_scope(Parser* p, Scope* scope, const char* name) { - for (int i = 0; i < LVAR_MAX; ++i) { - if (scope->lvar_names[i] && strcmp(scope->lvar_names[i], name) == 0) { - return scope->lvar_indices[i]; - } - } - return -1; -} - -int find_lvar_in_current_scope(Parser* p, const char* name) { - return find_lvar_in_scope(p, p->scope, name); -} - -int find_lvar(Parser* p, const char* name) { - Scope* scope = p->scope; - while (scope) { - int idx = find_lvar_in_scope(p, scope, name); - if (idx != -1) - return idx; - scope = scope->outer; - } - return -1; -} - -int calc_stack_offset(Parser* p, Type* ty, BOOL is_param) { - int align; - if (is_param) { - if (8 < type_sizeof(ty) || 8 < type_alignof(ty)) { - fatal_error("too large"); - } - align = 8; - } else { - align = type_alignof(ty); - } - - int offset; - if (p->n_lvars == 0) { - offset = 0; - } else { - offset = p->lvars[p->n_lvars - 1].stack_offset; - } - - offset += type_sizeof(ty); - return to_aligned(offset, align); -} - -int add_lvar(Parser* p, const char* name, Type* ty, BOOL is_param) { - int stack_offset = calc_stack_offset(p, ty, is_param); - p->lvars[p->n_lvars].name = name; - p->lvars[p->n_lvars].ty = ty; - p->lvars[p->n_lvars].stack_offset = stack_offset; - for (int i = 0; i < LVAR_MAX; ++i) { - if (p->scope->lvar_names[i] == NULL) { - p->scope->lvar_names[i] = name; - p->scope->lvar_indices[i] = p->n_lvars; - break; - } - } - ++p->n_lvars; - return stack_offset; -} - -AstNode* generate_temporary_lvar(Parser* p, Type* ty) { - int stack_offset = add_lvar(p, NULL, ty, FALSE); - AstNode* lvar = ast_new(AstNodeKind_lvar); - lvar->name = NULL; - lvar->node_stack_offset = stack_offset; - lvar->ty = ty; - return lvar; -} - -int find_gvar(Parser* p, const char* name) { - for (int i = 0; i < p->n_gvars; ++i) { - if (strcmp(p->gvars[i].name, name) == 0) { - return i; - } - } - return -1; -} - -int find_func(Parser* p, const char* name) { - for (int i = 0; i < p->n_funcs; ++i) { - if (strcmp(p->funcs[i].name, name) == 0) { - return i; - } - } - return -1; -} - -int find_struct(Parser* p, const char* name) { - for (int i = 0; i < p->n_structs; ++i) { - if (strcmp(p->structs[i].name, name) == 0) { - return i; - } - } - return -1; -} - -int find_union(Parser* p, const char* name) { - for (int i = 0; i < p->n_unions; ++i) { - if (strcmp(p->unions[i].name, name) == 0) { - return i; - } - } - return -1; -} - -int find_enum(Parser* p, const char* name) { - for (int i = 0; i < p->n_enums; ++i) { - if (strcmp(p->enums[i].name, name) == 0) { - return i; - } - } - return -1; -} - -int find_enum_member(Parser* p, const char* name) { - for (int i = 0; i < p->n_enums; ++i) { - for (int j = 0; j < p->enums[i].node_members->node_len; ++j) { - if (strcmp(p->enums[i].node_members->node_items[j].name, name) == 0) { - return i * 1000 + j; - } - } - } - return -1; -} - -int find_typedef(Parser* p, const char* name) { - for (int i = 0; i < p->n_typedefs; ++i) { - if (strcmp(p->typedefs[i].name, name) == 0) { - return i; - } - } - return -1; -} - -void enter_scope(Parser* p) { - Scope* outer_scope = p->scope; - p->scope = calloc(1, sizeof(Scope)); - p->scope->outer = outer_scope; - p->scope->lvar_names = calloc(LVAR_MAX, sizeof(char*)); - p->scope->lvar_indices = calloc(LVAR_MAX, sizeof(int)); -} - -void leave_scope(Parser* p) { - p->scope = p->scope->outer; -} - -void enter_func(Parser* p) { - p->lvars = calloc(LVAR_MAX, sizeof(LocalVar)); - p->n_lvars = 0; - enter_scope(p); -} - -void leave_func(Parser* p) { - leave_scope(p); -} - -AstNode* parse_assignment_expr(Parser* p); -AstNode* parse_expr(Parser* p); -AstNode* parse_stmt(Parser* p); - -const char* parse_ident(Parser* p) { - return expect(p, TokenKind_ident)->value.string; -} - -int register_str_literal(Parser* p, const char* s) { - p->str_literals[p->n_str_literals] = s; - ++p->n_str_literals; - return p->n_str_literals; -} - -AstNode* parse_primary_expr(Parser* p) { - Token* t = next_token(p); - if (t->kind == TokenKind_literal_int) { - return ast_new_int(t->value.integer); - } else if (t->kind == TokenKind_literal_str) { - AstNode* e = ast_new(AstNodeKind_str_expr); - e->node_idx = register_str_literal(p, t->value.string); - e->ty = type_new_static_string(strlen(t->value.string)); - return e; - } else if (t->kind == TokenKind_paren_l) { - AstNode* e = parse_expr(p); - expect(p, TokenKind_paren_r); - return e; - } else if (t->kind == TokenKind_ident) { - const char* name = t->value.string; - - if (peek_token(p)->kind == TokenKind_paren_l) { - AstNode* e = ast_new(AstNodeKind_func_call); - int func_idx = find_func(p, name); - if (func_idx == -1) { - fatal_error("undefined function: %s", name); - } - e->name = name; - e->ty = p->funcs[func_idx].ty; - return e; - } - - int lvar_idx = find_lvar(p, name); - if (lvar_idx == -1) { - int gvar_idx = find_gvar(p, name); - if (gvar_idx == -1) { - int enum_member_idx = find_enum_member(p, name); - if (enum_member_idx == -1) { - fatal_error("undefined variable: %s", name); - } - int enum_idx = enum_member_idx / 1000; - int n = enum_member_idx % 1000; - AstNode* e = ast_new_int(p->enums[enum_idx].node_members->node_items[n].node_int_value); - e->ty = type_new(TypeKind_enum); - e->ty->def = p->enums + enum_idx; - return e; - } - AstNode* e = ast_new(AstNodeKind_gvar); - e->name = name; - e->ty = p->gvars[gvar_idx].ty; - return e; - } - - AstNode* e = ast_new(AstNodeKind_lvar); - e->name = name; - e->node_stack_offset = p->lvars[lvar_idx].stack_offset; - e->ty = p->lvars[lvar_idx].ty; - return e; - } else { - fatal_error("%s:%d: expected an expression, but got '%s'", t->loc.filename, t->loc.line, token_stringify(t)); - } -} - -AstNode* parse_arg_list(Parser* p) { - AstNode* list = ast_new_list(6); - while (peek_token(p)->kind != TokenKind_paren_r) { - AstNode* arg = parse_assignment_expr(p); - ast_append(list, arg); - if (!consume_token_if(p, TokenKind_comma)) { - break; - } - } - if (list->node_len > 6) { - fatal_error("too many arguments"); - } - return list; -} - -// e++ -// tmp1 = &e; tmp2 = *tmp1; *tmp1 += 1; tmp2 -// e-- -// tmp1 = &e; tmp2 = *tmp1; *tmp1 -= 1; tmp2 -AstNode* create_new_postfix_inc_or_dec(Parser* p, AstNode* e, TokenKind op) { - AstNode* tmp1_lvar = generate_temporary_lvar(p, type_new_ptr(e->ty)); - AstNode* tmp2_lvar = generate_temporary_lvar(p, e->ty); - - AstNode* expr1 = ast_new_assign_expr(TokenKind_assign, tmp1_lvar, ast_new_ref_expr(e)); - AstNode* expr2 = ast_new_assign_expr(TokenKind_assign, tmp2_lvar, ast_new_deref_expr(tmp1_lvar)); - AstNode* expr3; - if (op == TokenKind_plusplus) { - expr3 = ast_new_assign_add_expr(ast_new_deref_expr(tmp1_lvar), ast_new_int(1)); - } else { - expr3 = ast_new_assign_sub_expr(ast_new_deref_expr(tmp1_lvar), ast_new_int(1)); - } - AstNode* expr4 = tmp2_lvar; - - AstNode* ret = ast_new_list(4); - ast_append(ret, expr1); - ast_append(ret, expr2); - ast_append(ret, expr3); - ast_append(ret, expr4); - ret->ty = expr4->ty; - return ret; -} - -AstNode* parse_postfix_expr(Parser* p) { - AstNode* ret = parse_primary_expr(p); - while (1) { - TokenKind tk = peek_token(p)->kind; - if (consume_token_if(p, TokenKind_paren_l)) { - AstNode* args = parse_arg_list(p); - expect(p, TokenKind_paren_r); - ret->node_args = args; - } else if (consume_token_if(p, TokenKind_bracket_l)) { - AstNode* idx = parse_expr(p); - expect(p, TokenKind_bracket_r); - idx = ast_new_binary_expr(TokenKind_star, idx, ast_new_int(type_sizeof(ret->ty->base))); - ret = ast_new_deref_expr(ast_new_binary_expr(TokenKind_plus, ret, idx)); - } else if (consume_token_if(p, TokenKind_dot)) { - const char* name = parse_ident(p); - ret = ast_new_member_access_expr(ast_new_ref_expr(ret), name); - } else if (consume_token_if(p, TokenKind_arrow)) { - const char* name = parse_ident(p); - ret = ast_new_member_access_expr(ret, name); - } else if (consume_token_if(p, TokenKind_plusplus)) { - ret = create_new_postfix_inc_or_dec(p, ret, TokenKind_plusplus); - } else if (consume_token_if(p, TokenKind_minusminus)) { - ret = create_new_postfix_inc_or_dec(p, ret, TokenKind_minusminus); - } else { - break; - } - } - return ret; -} - -BOOL is_type_token(Parser* p, Token* token) { - if (token->kind == TokenKind_keyword_int || token->kind == TokenKind_keyword_short || - token->kind == TokenKind_keyword_long || token->kind == TokenKind_keyword_char || - token->kind == TokenKind_keyword_void || token->kind == TokenKind_keyword_enum || - token->kind == TokenKind_keyword_struct || token->kind == TokenKind_keyword_union || - token->kind == TokenKind_keyword_const) { - return TRUE; - } - if (token->kind != TokenKind_ident) { - return FALSE; - } - return find_typedef(p, token->value.string) != -1; -} - -Type* parse_type(Parser* p) { - Token* t = next_token(p); - if (t->kind == TokenKind_keyword_const) { - t = next_token(p); - } - if (!is_type_token(p, t)) { - fatal_error("%s:%d: parse_type: expected type, but got '%s'", t->loc.filename, t->loc.line, token_stringify(t)); - } - Type* ty; - if (t->kind == TokenKind_ident) { - int typedef_idx = find_typedef(p, t->value.string); - if (typedef_idx == -1) { - fatal_error("parse_type: unknown typedef, %s", t->value.string); - } - ty = p->typedefs[typedef_idx].ty; - } else { - ty = type_new(TypeKind_unknown); - if (t->kind == TokenKind_keyword_char) { - ty->kind = TypeKind_char; - } else if (t->kind == TokenKind_keyword_short) { - ty->kind = TypeKind_short; - } else if (t->kind == TokenKind_keyword_int) { - ty->kind = TypeKind_int; - } else if (t->kind == TokenKind_keyword_long) { - ty->kind = TypeKind_long; - } else if (t->kind == TokenKind_keyword_void) { - ty->kind = TypeKind_void; - } else if (t->kind == TokenKind_keyword_enum) { - ty->kind = TypeKind_enum; - const char* name = parse_ident(p); - int enum_idx = find_enum(p, name); - if (enum_idx == -1) { - fatal_error("parse_type: unknown enum, %s", name); - } - ty->def = p->enums + enum_idx; - } else if (t->kind == TokenKind_keyword_struct) { - ty->kind = TypeKind_struct; - const char* name = parse_ident(p); - int struct_idx = find_struct(p, name); - if (struct_idx == -1) { - fatal_error("parse_type: unknown struct, %s", name); - } - ty->def = p->structs + struct_idx; - } else if (t->kind == TokenKind_keyword_union) { - ty->kind = TypeKind_union; - const char* name = parse_ident(p); - int union_idx = find_union(p, name); - if (union_idx == -1) { - fatal_error("parse_type: unknown union, %s", name); - } - ty->def = p->unions + union_idx; - } else { - unreachable(); - } - } - while (1) { - if (!consume_token_if(p, TokenKind_star)) { - break; - } - ty = type_new_ptr(ty); - } - return ty; -} - -AstNode* parse_prefix_expr(Parser* p) { - TokenKind op = peek_token(p)->kind; - if (consume_token_if(p, TokenKind_minus)) { - AstNode* operand = parse_prefix_expr(p); - return ast_new_binary_expr(op, ast_new_int(0), operand); - } else if (consume_token_if(p, TokenKind_not)) { - AstNode* operand = parse_prefix_expr(p); - return ast_new_unary_expr(op, operand); - } else if (consume_token_if(p, TokenKind_and)) { - AstNode* operand = parse_prefix_expr(p); - return ast_new_ref_expr(operand); - } else if (consume_token_if(p, TokenKind_star)) { - AstNode* operand = parse_prefix_expr(p); - return ast_new_deref_expr(operand); - } else if (consume_token_if(p, TokenKind_plusplus)) { - AstNode* operand = parse_prefix_expr(p); - return ast_new_assign_add_expr(operand, ast_new_int(1)); - } else if (consume_token_if(p, TokenKind_minusminus)) { - AstNode* operand = parse_prefix_expr(p); - return ast_new_assign_sub_expr(operand, ast_new_int(1)); - } else if (consume_token_if(p, TokenKind_keyword_sizeof)) { - expect(p, TokenKind_paren_l); - Token* next_tok = peek_token(p); - Type* ty = NULL; - if (next_tok->kind == TokenKind_ident) { - int lvar_idx = find_lvar(p, next_tok->value.string); - if (lvar_idx != -1) { - next_token(p); - ty = p->lvars[lvar_idx].ty; - } - int gvar_idx = find_gvar(p, next_tok->value.string); - if (gvar_idx != -1) { - next_token(p); - ty = p->gvars[gvar_idx].ty; - } - } - if (!ty) { - ty = parse_type(p); - } - expect(p, TokenKind_paren_r); - return ast_new_int(type_sizeof(ty)); - } - return parse_postfix_expr(p); -} - -AstNode* parse_multiplicative_expr(Parser* p) { - AstNode* lhs = parse_prefix_expr(p); - while (1) { - TokenKind op = peek_token(p)->kind; - if (op == TokenKind_star || op == TokenKind_slash || op == TokenKind_percent) { - next_token(p); - AstNode* rhs = parse_prefix_expr(p); - lhs = ast_new_binary_expr(op, lhs, rhs); - } else { - break; - } - } - return lhs; -} - -AstNode* parse_additive_expr(Parser* p) { - AstNode* lhs = parse_multiplicative_expr(p); - while (1) { - if (consume_token_if(p, TokenKind_plus)) { - AstNode* rhs = parse_multiplicative_expr(p); - if (lhs->ty->base) { - lhs = ast_new_binary_expr( - TokenKind_plus, lhs, - ast_new_binary_expr(TokenKind_star, rhs, ast_new_int(type_sizeof(lhs->ty->base)))); - } else if (rhs->ty->base) { - lhs = ast_new_binary_expr( - TokenKind_plus, ast_new_binary_expr(TokenKind_star, lhs, ast_new_int(type_sizeof(rhs->ty->base))), - rhs); - } else { - lhs = ast_new_binary_expr(TokenKind_plus, lhs, rhs); - } - } else if (consume_token_if(p, TokenKind_minus)) { - AstNode* rhs = parse_multiplicative_expr(p); - if (lhs->ty->base) { - if (rhs->ty->base) { - // (a - b) / sizeof(a) - lhs = ast_new_binary_expr(TokenKind_slash, ast_new_binary_expr(TokenKind_minus, lhs, rhs), - ast_new_int(type_sizeof(lhs->ty->base))); - } else { - // a - b*sizeof(a) - lhs = ast_new_binary_expr( - TokenKind_minus, lhs, - ast_new_binary_expr(TokenKind_star, rhs, ast_new_int(type_sizeof(lhs->ty->base)))); - } - } else { - lhs = ast_new_binary_expr(TokenKind_minus, lhs, rhs); - } - } else { - break; - } - } - return lhs; -} - -AstNode* parse_shift_expr(Parser* p) { - AstNode* lhs = parse_additive_expr(p); - while (1) { - TokenKind op = peek_token(p)->kind; - if (op == TokenKind_lshift || op == TokenKind_rshift) { - next_token(p); - AstNode* rhs = parse_additive_expr(p); - lhs = ast_new_binary_expr(op, lhs, rhs); - } else { - break; - } - } - return lhs; -} - -AstNode* parse_relational_expr(Parser* p) { - AstNode* lhs = parse_shift_expr(p); - while (1) { - TokenKind op = peek_token(p)->kind; - if (op == TokenKind_lt || op == TokenKind_le) { - next_token(p); - AstNode* rhs = parse_shift_expr(p); - lhs = ast_new_binary_expr(op, lhs, rhs); - } else if (consume_token_if(p, TokenKind_gt)) { - AstNode* rhs = parse_shift_expr(p); - lhs = ast_new_binary_expr(TokenKind_lt, rhs, lhs); - } else if (consume_token_if(p, TokenKind_ge)) { - AstNode* rhs = parse_shift_expr(p); - lhs = ast_new_binary_expr(TokenKind_le, rhs, lhs); - } else { - break; - } - } - return lhs; -} - -AstNode* parse_equality_expr(Parser* p) { - AstNode* lhs = parse_relational_expr(p); - while (1) { - TokenKind op = peek_token(p)->kind; - if (op == TokenKind_eq || op == TokenKind_ne) { - next_token(p); - AstNode* rhs = parse_relational_expr(p); - lhs = ast_new_binary_expr(op, lhs, rhs); - } else { - break; - } - } - return lhs; -} - -AstNode* parse_bitwise_or_expr(Parser* p) { - AstNode* lhs = parse_equality_expr(p); - while (1) { - TokenKind op = peek_token(p)->kind; - if (consume_token_if(p, TokenKind_or)) { - AstNode* rhs = parse_equality_expr(p); - lhs = ast_new_binary_expr(op, lhs, rhs); - lhs->ty = type_new(TypeKind_int); - } else { - break; - } - } - return lhs; -} - -AstNode* parse_logical_and_expr(Parser* p) { - AstNode* lhs = parse_bitwise_or_expr(p); - while (1) { - TokenKind op = peek_token(p)->kind; - if (consume_token_if(p, TokenKind_andand)) { - AstNode* rhs = parse_bitwise_or_expr(p); - AstNode* e = ast_new(AstNodeKind_logical_expr); - e->node_op = op; - e->node_lhs = lhs; - e->node_rhs = rhs; - e->ty = type_new(TypeKind_int); - lhs = e; - } else { - break; - } - } - return lhs; -} - -AstNode* parse_logical_or_expr(Parser* p) { - AstNode* lhs = parse_logical_and_expr(p); - while (1) { - TokenKind op = peek_token(p)->kind; - if (consume_token_if(p, TokenKind_oror)) { - AstNode* rhs = parse_logical_and_expr(p); - AstNode* e = ast_new(AstNodeKind_logical_expr); - e->node_op = op; - e->node_lhs = lhs; - e->node_rhs = rhs; - e->ty = type_new(TypeKind_int); - lhs = e; - } else { - break; - } - } - return lhs; -} - -AstNode* parse_conditional_expr(Parser* p) { - AstNode* e = parse_logical_or_expr(p); - if (consume_token_if(p, TokenKind_question)) { - AstNode* then_expr = parse_expr(p); - expect(p, TokenKind_colon); - AstNode* else_expr = parse_assignment_expr(p); - AstNode* ret = ast_new(AstNodeKind_cond_expr); - ret->node_cond = e; - ret->node_then = then_expr; - ret->node_else = else_expr; - ret->ty = then_expr->ty; - return ret; - } else { - return e; - } -} - -// constant-expression: -// conditional-expression -AstNode* parse_constant_expression(Parser* p) { - return parse_conditional_expr(p); -} - -AstNode* parse_assignment_expr(Parser* p) { - AstNode* lhs = parse_conditional_expr(p); - while (1) { - TokenKind op = peek_token(p)->kind; - // TODO: check if the lhs is unary expression. - if (op == TokenKind_assign || op == TokenKind_assign_mul || op == TokenKind_assign_div || - op == TokenKind_assign_mod) { - next_token(p); - AstNode* rhs = parse_assignment_expr(p); - lhs = ast_new_assign_expr(op, lhs, rhs); - } else if (consume_token_if(p, TokenKind_assign_add)) { - AstNode* rhs = parse_assignment_expr(p); - lhs = ast_new_assign_add_expr(lhs, rhs); - } else if (consume_token_if(p, TokenKind_assign_sub)) { - AstNode* rhs = parse_assignment_expr(p); - lhs = ast_new_assign_sub_expr(lhs, rhs); - } else { - break; - } - } - return lhs; -} - -AstNode* parse_comma_expr(Parser* p) { - AstNode* lhs = parse_assignment_expr(p); - while (1) { - TokenKind op = peek_token(p)->kind; - if (consume_token_if(p, TokenKind_comma)) { - AstNode* rhs = parse_assignment_expr(p); - AstNode* list = ast_new_list(2); - ast_append(list, lhs); - ast_append(list, rhs); - list->ty = rhs->ty; - lhs = list; - } else { - break; - } - } - return lhs; -} - -AstNode* parse_expr(Parser* p) { - return parse_comma_expr(p); -} - -AstNode* parse_return_stmt(Parser* p) { - expect(p, TokenKind_keyword_return); - if (consume_token_if(p, TokenKind_semicolon)) { - return ast_new(AstNodeKind_return_stmt); - } - - AstNode* expr = parse_expr(p); - expect(p, TokenKind_semicolon); - - AstNode* ret = ast_new(AstNodeKind_return_stmt); - ret->node_expr = expr; - return ret; -} - -AstNode* parse_if_stmt(Parser* p) { - expect(p, TokenKind_keyword_if); - expect(p, TokenKind_paren_l); - AstNode* cond = parse_expr(p); - expect(p, TokenKind_paren_r); - AstNode* then_body = parse_stmt(p); - AstNode* else_body = NULL; - if (consume_token_if(p, TokenKind_keyword_else)) { - else_body = parse_stmt(p); - } - - AstNode* stmt = ast_new(AstNodeKind_if_stmt); - stmt->node_cond = cond; - stmt->node_then = then_body; - stmt->node_else = else_body; - return stmt; -} - -// pointer: -// '*' TODO attribute-specifier-sequence_opt TODO type-qualifier-list_opt -// '*' TODO attribute-specifier-sequence_opt TODO type-qualifier-list_opt pointer -Type* parse_pointer_opt(Parser* p, Type* ty) { - while (peek_token(p)->kind == TokenKind_star) { - next_token(p); - ty = type_new_ptr(ty); - } - return ty; -} - -// array-declarator: -// direct-declarator '[' TODO type-qualifier-list_opt TODO assignment-expression_opt ']' -// TODO direct-declarator '[' 'static' type-qualifier-list_opt assignment-expression_opt ']' -// TODO direct-declarator '[' type-qualifier-list 'static' assignment-expression_opt ']' -// TODO direct-declarator '[' type-qualifier-list_opt '*' ']' -Type* parse_array_declarator_suffix(Parser* p, Type* ty) { - next_token(p); // skip '[' - - AstNode* size_expr = parse_expr(p); - if (size_expr->kind != AstNodeKind_int_expr) { - fatal_error("parse_var_decl: invalid array size"); - } - int size = size_expr->node_int_value; - expect(p, TokenKind_bracket_r); - - return type_new_array(ty, size); -} - -// direct-declarator: -// identifier TODO attribute-specifier-sequence_opt -// TODO '(' declarator ')' -// array-declarator TODO attribute-specifier-sequence_opt -// TODO function-declarator TODO attribute-specifier-sequence_opt -AstNode* parse_direct_declarator(Parser* p, Type* ty) { - const char* name = parse_ident(p); - while (1) { - if (peek_token(p)->kind == TokenKind_bracket_l) { - ty = parse_array_declarator_suffix(p, ty); - } else { - break; - } - } - - AstNode* ret = ast_new(AstNodeKind_declarator); - ret->name = name; - ret->ty = ty; - return ret; -} - -// declarator: -// pointer_opt direct-declarator -AstNode* parse_declarator(Parser* p, Type* ty) { - ty = parse_pointer_opt(p, ty); - return parse_direct_declarator(p, ty); -} - -// initializer: -// assignment-expression -// TODO braced-initializer -AstNode* parse_initializer(Parser* p) { - return parse_assignment_expr(p); -} - -// init-declarator: -// declarator -// declarator '=' initializer -AstNode* parse_init_declarator(Parser* p, Type* ty) { - AstNode* decl = parse_declarator(p, ty); - AstNode* init = NULL; - if (consume_token_if(p, TokenKind_assign)) { - init = parse_initializer(p); - } - decl->node_init = init; - return decl; -} - -// init-declarator-list: -// init-declarator -// init-declarator-list ',' init-declarator -AstNode* parse_init_declarator_list(Parser* p, Type* ty) { - AstNode* list = ast_new_list(1); - while (1) { - AstNode* d = parse_init_declarator(p, ty); - ast_append(list, d); - if (!consume_token_if(p, TokenKind_comma)) { - break; - } - } - return list; -} - -AstNode* parse_var_decl(Parser* p) { - Type* base_ty = parse_type(p); - if (type_is_unsized(base_ty)) { - fatal_error("parse_var_decl: invalid type for variable"); - } - - AstNode* decls = parse_init_declarator_list(p, base_ty); - expect(p, TokenKind_semicolon); - - for (int i = 0; i < decls->node_len; ++i) { - AstNode* decl = &decls->node_items[i]; - - if (find_lvar_in_current_scope(p, decl->name) != -1) { - // TODO: use name's location. - fatal_error("%s:%d: '%s' redeclared", peek_token(p)->loc.filename, peek_token(p)->loc.line, decl->name); - } - int stack_offset = add_lvar(p, decl->name, decl->ty, FALSE); - - if (decl->node_init) { - AstNode* lhs = ast_new(AstNodeKind_lvar); - lhs->name = decl->name; - lhs->node_stack_offset = stack_offset; - lhs->ty = decl->ty; - AstNode* assign = ast_new_assign_expr(TokenKind_assign, lhs, decl->node_init); - decl->kind = AstNodeKind_expr_stmt; - decl->node_expr = assign; - } else { - decl->kind = AstNodeKind_nop; - } - } - return decls; -} - -AstNode* parse_for_stmt(Parser* p) { - expect(p, TokenKind_keyword_for); - expect(p, TokenKind_paren_l); - AstNode* init = NULL; - AstNode* cond = NULL; - AstNode* update = NULL; - enter_scope(p); - if (peek_token(p)->kind != TokenKind_semicolon) { - if (is_type_token(p, peek_token(p))) { - init = parse_var_decl(p)->node_items[0].node_expr; - } else { - init = parse_expr(p); - expect(p, TokenKind_semicolon); - } - } else { - expect(p, TokenKind_semicolon); - } - if (peek_token(p)->kind != TokenKind_semicolon) { - cond = parse_expr(p); - } else { - cond = ast_new_int(1); - } - expect(p, TokenKind_semicolon); - if (peek_token(p)->kind != TokenKind_paren_r) { - update = parse_expr(p); - } - expect(p, TokenKind_paren_r); - AstNode* body = parse_stmt(p); - leave_scope(p); - - AstNode* stmt = ast_new(AstNodeKind_for_stmt); - stmt->node_cond = cond; - stmt->node_init = init; - stmt->node_update = update; - stmt->node_body = body; - return stmt; -} - -AstNode* parse_while_stmt(Parser* p) { - expect(p, TokenKind_keyword_while); - expect(p, TokenKind_paren_l); - AstNode* cond = parse_expr(p); - expect(p, TokenKind_paren_r); - AstNode* body = parse_stmt(p); - - AstNode* stmt = ast_new(AstNodeKind_for_stmt); - stmt->node_cond = cond; - stmt->node_body = body; - return stmt; -} - -AstNode* parse_do_while_stmt(Parser* p) { - expect(p, TokenKind_keyword_do); - AstNode* body = parse_stmt(p); - expect(p, TokenKind_keyword_while); - expect(p, TokenKind_paren_l); - AstNode* cond = parse_expr(p); - expect(p, TokenKind_paren_r); - expect(p, TokenKind_semicolon); - - AstNode* stmt = ast_new(AstNodeKind_do_while_stmt); - stmt->node_cond = cond; - stmt->node_body = body; - return stmt; -} - -AstNode* parse_break_stmt(Parser* p) { - expect(p, TokenKind_keyword_break); - expect(p, TokenKind_semicolon); - return ast_new(AstNodeKind_break_stmt); -} - -AstNode* parse_continue_stmt(Parser* p) { - expect(p, TokenKind_keyword_continue); - expect(p, TokenKind_semicolon); - return ast_new(AstNodeKind_continue_stmt); -} - -AstNode* parse_expr_stmt(Parser* p) { - AstNode* e = parse_expr(p); - expect(p, TokenKind_semicolon); - AstNode* stmt = ast_new(AstNodeKind_expr_stmt); - stmt->node_expr = e; - return stmt; -} - -AstNode* parse_block_stmt(Parser* p) { - AstNode* list = ast_new_list(4); - expect(p, TokenKind_brace_l); - enter_scope(p); - while (peek_token(p)->kind != TokenKind_brace_r) { - AstNode* stmt = parse_stmt(p); - ast_append(list, stmt); - } - leave_scope(p); - expect(p, TokenKind_brace_r); - return list; -} - -AstNode* parse_empty_stmt(Parser* p) { - consume_token_if(p, TokenKind_semicolon); - return ast_new(AstNodeKind_nop); -} - -AstNode* parse_stmt(Parser* p) { - Token* t = peek_token(p); - if (t->kind == TokenKind_keyword_return) { - return parse_return_stmt(p); - } else if (t->kind == TokenKind_keyword_if) { - return parse_if_stmt(p); - } else if (t->kind == TokenKind_keyword_for) { - return parse_for_stmt(p); - } else if (t->kind == TokenKind_keyword_while) { - return parse_while_stmt(p); - } else if (t->kind == TokenKind_keyword_do) { - return parse_do_while_stmt(p); - } else if (t->kind == TokenKind_keyword_break) { - return parse_break_stmt(p); - } else if (t->kind == TokenKind_keyword_continue) { - return parse_continue_stmt(p); - } else if (t->kind == TokenKind_brace_l) { - return parse_block_stmt(p); - } else if (t->kind == TokenKind_semicolon) { - return parse_empty_stmt(p); - } else if (is_type_token(p, t)) { - return parse_var_decl(p); - } else { - return parse_expr_stmt(p); - } -} - -void register_params(Parser* p, AstNode* params) { - for (int i = 0; i < params->node_len; ++i) { - AstNode* param = params->node_items + i; - add_lvar(p, param->name, param->ty, TRUE); - } -} - -void register_func(Parser* p, const char* name, Type* ty) { - p->funcs[p->n_funcs].name = name; - p->funcs[p->n_funcs].ty = ty; - ++p->n_funcs; -} - -AstNode* parse_param(Parser* p) { - Type* ty = parse_type(p); - const char* name = NULL; - TokenKind tk = peek_token(p)->kind; - if (tk != TokenKind_comma && tk != TokenKind_paren_r) { - name = parse_ident(p); - } - AstNode* param = ast_new(AstNodeKind_param); - param->ty = ty; - if (name) { - param->name = name; - } - return param; -} - -AstNode* parse_param_list(Parser* p) { - BOOL has_void = FALSE; - AstNode* list = ast_new_list(6); - while (peek_token(p)->kind != TokenKind_paren_r) { - if (consume_token_if(p, TokenKind_ellipsis)) { - break; - } - AstNode* param = parse_param(p); - has_void = has_void || param->ty->kind == TypeKind_void; - ast_append(list, param); - if (!consume_token_if(p, TokenKind_comma)) { - break; - } - } - if (list->node_len > 6) { - fatal_error("too many parameters"); - } - if (has_void) { - if (list->node_len != 1) { - fatal_error("invalid use of void param"); - } - list->node_len = 0; - } - return list; -} - -AstNode* parse_global_var_decl(Parser* p) { - Type* base_ty = parse_type(p); - if (type_is_unsized(base_ty)) { - fatal_error("parse_global_var_decl: invalid type for variable"); - } - - AstNode* decls = parse_init_declarator_list(p, base_ty); - expect(p, TokenKind_semicolon); - - for (int i = 0; i < decls->node_len; ++i) { - AstNode* decl = &decls->node_items[i]; - - if (find_gvar(p, decl->name) != -1) { - fatal_error("parse_global_var_decl: %s redeclared", decl->name); - } - p->gvars[p->n_gvars].name = decl->name; - p->gvars[p->n_gvars].ty = decl->ty; - ++p->n_gvars; - - decl->kind = AstNodeKind_gvar_decl; - decl->node_expr = decl->node_init; - } - return decls; -} - -AstNode* parse_func_decl_or_def(Parser* p) { - // TODO: remove it. - int start_pos = p->pos; - - Type* ty = parse_type(p); - const char* name = parse_ident(p); - - if (peek_token(p)->kind != TokenKind_paren_l) { - // TODO: avoid backtracking - p->pos = start_pos; - return parse_global_var_decl(p); - } - - expect(p, TokenKind_paren_l); - register_func(p, name, ty); - AstNode* params = parse_param_list(p); - expect(p, TokenKind_paren_r); - if (consume_token_if(p, TokenKind_semicolon)) { - return ast_new(AstNodeKind_func_decl); - } - enter_func(p); - register_params(p, params); - AstNode* body = parse_block_stmt(p); - leave_func(p); - AstNode* func = ast_new(AstNodeKind_func_def); - func->ty = ty; - func->name = name; - func->node_params = params; - func->node_body = body; - if (p->n_lvars == 0) { - func->node_stack_size = 0; - } else { - func->node_stack_size = p->lvars[p->n_lvars - 1].stack_offset + type_sizeof(p->lvars[p->n_lvars - 1].ty); - } - return func; -} - -AstNode* parse_struct_member(Parser* p) { - Type* ty = parse_type(p); - const char* name = parse_ident(p); - expect(p, TokenKind_semicolon); - AstNode* member = ast_new(AstNodeKind_struct_member); - member->name = name; - member->ty = ty; - return member; -} - -AstNode* parse_struct_members(Parser* p) { - AstNode* list = ast_new_list(4); - while (peek_token(p)->kind != TokenKind_brace_r) { - AstNode* member = parse_struct_member(p); - ast_append(list, member); - } - return list; -} - -AstNode* parse_struct_decl_or_def(Parser* p) { - expect(p, TokenKind_keyword_struct); - const char* name = parse_ident(p); - - if (peek_token(p)->kind != TokenKind_semicolon && peek_token(p)->kind != TokenKind_brace_l) { - p->pos = p->pos - 2; - return parse_func_decl_or_def(p); - } - - int struct_idx = find_struct(p, name); - if (struct_idx == -1) { - struct_idx = p->n_structs; - p->structs[struct_idx].kind = AstNodeKind_struct_def; - p->structs[struct_idx].name = name; - ++p->n_structs; - } - if (consume_token_if(p, TokenKind_semicolon)) { - return ast_new(AstNodeKind_struct_decl); - } - if (p->structs[struct_idx].node_members) { - fatal_error("parse_struct_decl_or_def: struct %s redefined", name); - } - expect(p, TokenKind_brace_l); - AstNode* members = parse_struct_members(p); - expect(p, TokenKind_brace_r); - expect(p, TokenKind_semicolon); - p->structs[struct_idx].node_members = members; - return p->structs + struct_idx; -} - -AstNode* parse_union_member(Parser* p) { - Type* ty = parse_type(p); - const char* name = parse_ident(p); - expect(p, TokenKind_semicolon); - AstNode* member = ast_new(AstNodeKind_union_member); - member->name = name; - member->ty = ty; - return member; -} - -AstNode* parse_union_members(Parser* p) { - AstNode* list = ast_new_list(4); - while (peek_token(p)->kind != TokenKind_brace_r) { - AstNode* member = parse_union_member(p); - ast_append(list, member); - } - return list; -} - -AstNode* parse_union_decl_or_def(Parser* p) { - expect(p, TokenKind_keyword_union); - const char* name = parse_ident(p); - - if (peek_token(p)->kind != TokenKind_semicolon && peek_token(p)->kind != TokenKind_brace_l) { - p->pos = p->pos - 2; - return parse_func_decl_or_def(p); - } - - int union_idx = find_union(p, name); - if (union_idx == -1) { - union_idx = p->n_unions; - p->unions[union_idx].kind = AstNodeKind_union_def; - p->unions[union_idx].name = name; - ++p->n_unions; - } - if (consume_token_if(p, TokenKind_semicolon)) { - return ast_new(AstNodeKind_union_decl); - } - if (p->unions[union_idx].node_members) { - fatal_error("parse_union_decl_or_def: union %s redefined", name); - } - expect(p, TokenKind_brace_l); - AstNode* members = parse_union_members(p); - expect(p, TokenKind_brace_r); - expect(p, TokenKind_semicolon); - p->unions[union_idx].node_members = members; - return p->unions + union_idx; -} - -AstNode* parse_enum_member(Parser* p) { - const char* name = parse_ident(p); - AstNode* member = ast_new(AstNodeKind_enum_member); - member->name = name; - return member; -} - -AstNode* parse_enum_members(Parser* p) { - int next_value = 0; - AstNode* list = ast_new_list(16); - while (peek_token(p)->kind != TokenKind_brace_r) { - AstNode* member = parse_enum_member(p); - member->node_int_value = next_value; - ++next_value; - ast_append(list, member); - if (!consume_token_if(p, TokenKind_comma)) { - break; - } - } - return list; -} - -AstNode* parse_enum_def(Parser* p) { - expect(p, TokenKind_keyword_enum); - const char* name = parse_ident(p); - - if (peek_token(p)->kind != TokenKind_brace_l) { - p->pos = p->pos - 2; - return parse_func_decl_or_def(p); - } - - int enum_idx = find_enum(p, name); - if (enum_idx == -1) { - enum_idx = p->n_enums; - p->enums[enum_idx].kind = AstNodeKind_enum_def; - p->enums[enum_idx].name = name; - ++p->n_enums; - } else { - fatal_error("parse_enum_def: enum %s redefined", name); - } - expect(p, TokenKind_brace_l); - AstNode* members = parse_enum_members(p); - expect(p, TokenKind_brace_r); - expect(p, TokenKind_semicolon); - p->enums[enum_idx].node_members = members; - return p->enums + enum_idx; -} - -AstNode* parse_typedef_decl(Parser* p) { - expect(p, TokenKind_keyword_typedef); - Type* ty = parse_type(p); - const char* name = parse_ident(p); - expect(p, TokenKind_semicolon); - AstNode* decl = ast_new(AstNodeKind_typedef_decl); - decl->name = name; - decl->ty = ty; - p->typedefs[p->n_typedefs].name = name; - p->typedefs[p->n_typedefs].ty = ty; - ++p->n_typedefs; - return decl; -} - -AstNode* parse_extern_var_decl(Parser* p) { - expect(p, TokenKind_keyword_extern); - Type* ty = parse_type(p); - if (type_is_unsized(ty)) { - fatal_error("parse_extern_var_decl: invalid type for variable"); - } - const char* name = parse_ident(p); - expect(p, TokenKind_semicolon); - - if (find_lvar(p, name) != -1 || find_gvar(p, name) != -1) { - fatal_error("parse_extern_var_decl: %s redeclared", name); - } - p->gvars[p->n_gvars].name = name; - p->gvars[p->n_gvars].ty = ty; - ++p->n_gvars; - - return ast_new(AstNodeKind_gvar_decl); -} - -AstNode* parse_toplevel(Parser* p) { - TokenKind tk = peek_token(p)->kind; - if (tk == TokenKind_keyword_struct) { - return parse_struct_decl_or_def(p); - } else if (tk == TokenKind_keyword_union) { - return parse_union_decl_or_def(p); - } else if (tk == TokenKind_keyword_enum) { - return parse_enum_def(p); - } else if (tk == TokenKind_keyword_typedef) { - return parse_typedef_decl(p); - } else if (tk == TokenKind_keyword_extern) { - return parse_extern_var_decl(p); - } else { - return parse_func_decl_or_def(p); - } -} - -Program* parse(TokenArray* tokens) { - Parser* p = parser_new(tokens); - AstNode* funcs = ast_new_list(32); - AstNode* vars = ast_new_list(16); - while (eof(p)) { - AstNode* n = parse_toplevel(p); - if (n->kind == AstNodeKind_func_def) { - ast_append(funcs, n); - } else if (n->kind == AstNodeKind_gvar_decl && n->ty) { - ast_append(vars, n); - } else if (n->kind == AstNodeKind_list) { - for (int i = 0; i < n->node_len; ++i) { - ast_append(vars, &n->node_items[i]); - } - } - } - Program* prog = calloc(1, sizeof(Program)); - prog->funcs = funcs; - prog->vars = vars; - prog->str_literals = p->str_literals; - return prog; -} - -int eval(AstNode* e) { - if (e->kind == AstNodeKind_int_expr) { - return e->node_int_value; - } else if (e->kind == AstNodeKind_unary_expr) { - int v = eval(e->node_operand); - if (e->node_op == TokenKind_not) { - return !v; - } else { - unimplemented(); - } - } else if (e->kind == AstNodeKind_binary_expr || e->kind == AstNodeKind_logical_expr) { - int v1 = eval(e->node_lhs); - int v2 = eval(e->node_rhs); - if (e->node_op == TokenKind_andand) { - return v1 && v2; - } else if (e->node_op == TokenKind_oror) { - return v1 || v2; - } else { - unimplemented(); - } - } else { - unimplemented(); - } -} - -BOOL pp_eval_constant_expression(TokenArray* pp_tokens) { - TokenArray* tokens = tokenize(pp_tokens); - Parser* p = parser_new(tokens); - AstNode* e = parse_constant_expression(p); - return eval(e) != 0; -} -- cgit v1.2.3-70-g09d2