Expr *new_expr_alignof_type(SrcPos pos, Typespec *type) { Expr *e = new_expr(EXPR_ALIGNOF_TYPE, pos); e->alignof_type = type; return(e); }
Expr *new_expr_sizeof_type(SrcPos pos, Typespec *type) { var e = new_expr(EXPR_SIZEOF_TYPE, pos); e->sizeof_type = type; return(e); }
Expr *new_expr_typeof_type(SrcPos pos, Typespec *type) { Expr *e = new_expr(EXPR_TYPEOF_TYPE, pos); e->typeof_type = type; return(e); }
Decl *parse_decl_enum(SrcPos pos) { char *name = null; if (is_token(TOKEN_NAME)) { name = parse_name(); } Typespec *type = null; if (match_token(TOKEN_ASSIGN)) { type = parse_type(); } expect_token(TOKEN_LBRACE); EnumItem *items = null; var buf = Buffer <EnumItem> .Create(16); while (!is_token(TOKEN_RBRACE)) { buf.Add(parse_decl_enum_item()); if (!match_token(TOKEN_COMMA)) { break; } } expect_token(TOKEN_RBRACE); return(new_decl_enum(pos, name, type, buf._begin, buf.count)); }
Decl *new_decl_typedef(SrcPos pos, char *name, Typespec *type) { var d = new_decl(DECL_TYPEDEF, pos, name); d->typedef_decl.type = type; return(d); }
Decl *parse_decl_var(SrcPos pos) { var name = parse_name(); if (match_token(TOKEN_ASSIGN)) { Expr *expr = parse_expr(); expect_token(TOKEN_SEMICOLON); return(new_decl_var(pos, name, null, expr)); } else if (match_token(TOKEN_COLON)) { Typespec *type = parse_type(); Expr * expr = null; if (match_token(TOKEN_ASSIGN)) { expr = parse_expr(); } expect_token(TOKEN_SEMICOLON); return(new_decl_var(pos, name, type, expr)); } else { fatal_error_here("Expected : or = after var, got {0}", token_info()); return(null); } }
Typespec *new_typespec_const(SrcPos pos, Typespec * @base) { Typespec *t = new_typespec(TYPESPEC_CONST, pos); t->@base = @base; return(t); }
Typespec *new_typespec_ptr(SrcPos pos, Typespec * @base) { var t = new_typespec(TYPESPEC_PTR, pos); t->@base = @base; t->@base = @base; return(t); }
Expr *new_expr_offsetof(SrcPos pos, Typespec *type, char *name) { Expr *e = new_expr(EXPR_OFFSETOF, pos); e->offsetof_field.type = type; e->offsetof_field.name = name; return(e); }
Decl *new_decl_const(SrcPos pos, char *name, Typespec *type, Expr *expr) { var d = new_decl(DECL_CONST, pos, name); d->const_decl.type = type; d->const_decl.expr = expr; return(d); }
Decl *new_decl_var(SrcPos pos, char *name, Typespec *type, Expr *expr) { var d = new_decl(DECL_VAR, pos, name); d->var.type = type; d->var.expr = expr; return(d); }
Typespec *new_typespec_tuple(SrcPos pos, Typespec **fields, int num_fields) { Typespec *t = new_typespec(TYPESPEC_TUPLE, pos); t->tuple.fields = fields; t->tuple.num_fields = num_fields; return(t); }
Typespec *new_typespec_array(SrcPos pos, Typespec * @base, Expr *num_elems) { var t = new_typespec(TYPESPEC_ARRAY, pos); t->@base = @base; t->num_elems = num_elems; return(t); }
Expr *new_expr_cast(SrcPos pos, Typespec *type, Expr *expr) { var e = new_expr(EXPR_CAST, pos); e->cast.type = type; e->cast.expr = expr; return(e); }
Decl *new_decl_enum(SrcPos pos, char *name, Typespec *type, EnumItem *items, int num_items) { var d = new_decl(DECL_ENUM, pos, name); d->enum_decl.items = items; d->enum_decl.type = type; d->enum_decl.num_items = num_items; return(d); }
Expr *new_expr_compound(SrcPos pos, Typespec *type, CompoundField *fields, int num_fields) { var e = new_expr(EXPR_COMPOUND, pos); e->compound.type = type; e->compound.fields = fields; e->compound.num_fields = num_fields; return(e); }
void print_typespec(Typespec *type) { var t = type; switch (t->kind) { case TYPESPEC_NAME: printf("{0}", *(t->names)); break; case TYPESPEC_FUNC: printf("(func ("); for (var it = t->func.args; it != t->func.args + t->func.num_args; it++) { printf(" "); print_typespec(*it); } printf(" ) "); if (t->func.ret != null) { print_typespec(t->func.ret); } else { printf("void"); } printf(")"); break; case TYPESPEC_ARRAY: printf("(array "); print_typespec(t->@base); printf(" "); if (t->num_elems != null) { print_expr(t->num_elems); } else { printf("nil"); } printf(")"); break; case TYPESPEC_PTR: printf("(ptr "); print_typespec(t->@base); printf(")"); break; default: assert(false); break; } }
Typespec *new_typespec_func(SrcPos pos, Typespec **args, int num_args, Typespec *ret, bool has_varargs) { var t = new_typespec(TYPESPEC_FUNC, pos); t->func.args = args; t->func.num_args = num_args; t->func.ret = ret; t->func.has_varargs = has_varargs; return(t); }
Decl *parse_decl_typedef(SrcPos pos) { var name = parse_name(); expect_token(TOKEN_ASSIGN); Typespec *type = parse_type(); expect_token(TOKEN_SEMICOLON); return(new_decl_typedef(pos, name, type)); }
Stmt *new_stmt_init(SrcPos pos, char *name, Typespec *type, Expr *expr, bool is_undef) { var s = new_stmt(STMT_INIT, pos); s->init.name = name; s->init.type = type; s->init.expr = expr; s->init.is_undef = is_undef; return(s); }
Typespec *parse_type_func_param() { Typespec *type = parse_type(); if (match_token(TOKEN_COLON)) { if (type->kind != TypespecKind.TYPESPEC_NAME) { error_here("Colons in parameters of func types must be preceded by names."); } type = parse_type(); } return(type); }
Decl *parse_decl_const(SrcPos pos) { Typespec *type = null; var name = parse_name(); if (match_token(TOKEN_COLON)) { type = parse_type(); } expect_token(TOKEN_ASSIGN); Expr *expr = parse_expr(); expect_token(TOKEN_SEMICOLON); return(new_decl_const(pos, name, type, expr)); }
Typespec *parse_type_tuple() { SrcPos pos = token.pos; PtrBuffer *fields = PtrBuffer.Create(); while (!is_token(TOKEN_RBRACE)) { Typespec *field = parse_type(); fields->Add(field); if (!match_token(TOKEN_COMMA)) { break; } } expect_token(TOKEN_RBRACE); return(new_typespec_tuple(pos, (Typespec **)fields->_begin, fields->count)); }
Expr *parse_expr_compound(Typespec *type) { var pos = token.pos; expect_token(TOKEN_LBRACE); var buf = Buffer <CompoundField> .Create(); while (!is_token(TOKEN_RBRACE)) { buf.Add(parse_expr_compound_field()); if (!match_token(TOKEN_COMMA)) { break; } } expect_token(TOKEN_RBRACE); return(new_expr_compound(pos, type, buf, buf.count)); }
Typespec *parse_type_func() { var buf = PtrBuffer.Create(); var pos = token.pos; bool has_varargs = false; expect_token(TOKEN_LPAREN); if (!is_token(TOKEN_RPAREN)) { buf->Add(parse_type_func_param()); while (match_token(TOKEN_COMMA)) { if (match_token(TOKEN_ELLIPSIS)) { if (has_varargs) { error_here("Multiple ellipsis instances in function type"); } has_varargs = true; } else { if (has_varargs) { error_here("Ellipsis must be last parameter in function type"); } buf->Add(parse_type_func_param()); } } } expect_token(TOKEN_RPAREN); Typespec *ret = null; if (match_token(TOKEN_COLON)) { ret = parse_type(); } return(new_typespec_func(pos, (Typespec **)buf->_begin, buf->count, ret, has_varargs)); }
AggregateItem parse_decl_aggregate_item() { var pos = token.pos; if (match_keyword(struct_keyword)) { return(new AggregateItem { pos = pos, kind = AGGREGATE_ITEM_SUBAGGREGATE, subaggregate = parse_aggregate(AGGREGATE_STRUCT), }); } else if (match_keyword(union_keyword)) { return(new AggregateItem { pos = pos, kind = AGGREGATE_ITEM_SUBAGGREGATE, subaggregate = parse_aggregate(AGGREGATE_UNION), }); } else { var names = PtrBuffer.Create(); names->Add(parse_name()); while (match_token(TOKEN_COMMA)) { names->Add(parse_name()); } expect_token(TOKEN_COLON); Typespec *type = parse_type(); expect_token(TOKEN_SEMICOLON); return(new AggregateItem { pos = pos, kind = AGGREGATE_ITEM_FIELD, names = (char **)names->_begin, num_names = names->count, type = type, }); } }
Stmt *parse_init_stmt(Expr *left) { var pos = token.pos; Stmt *stmt = null; if (match_token(TOKEN_COLON_ASSIGN)) { if (left->kind != EXPR_NAME) { fatal_error_here(":= must be preceded by a name"); return(null); } return(new_stmt_init(left->pos, left->name, null, parse_expr(), false)); } else if (match_token(TOKEN_COLON)) { if (left->kind != EXPR_NAME) { fatal_error_here(": must be preceded by a name"); return(null); } char * name = left->name; Typespec *type = parse_type(); Expr * expr = null; bool is_undef = false; if (match_token(TOKEN_ASSIGN)) { is_undef = match_keyword(undef_keyword); if (!is_undef) { expr = parse_expr(); } } return(new_stmt_init(left->pos, name, type, expr, is_undef)); } return(null); }
Expr *parse_expr_operand() { var pos = token.pos; if (is_token(TOKEN_INT)) { var val = token.int_val; var suffix = token.suffix; var mod = token.mod; next_token(); return(new_expr_int(pos, val, mod, suffix)); } if (is_token(TOKEN_FLOAT)) { char * start = token.start; char * end = token.end; double val = token.float_val; TokenSuffix suffix = token.suffix; next_token(); return(new_expr_float(pos, start, end, val, suffix)); } if (is_token(TOKEN_STR)) { var mod = token.mod; var val = token.str_val; next_token(); return(new_expr_str(pos, val, mod)); } if (is_token(TOKEN_NAME)) { var name = token.name; next_token(); if (is_token(TOKEN_LBRACE)) { return(parse_expr_compound(new_typespec_name(pos, &name, 1))); } return(new_expr_name(pos, name)); } if (match_keyword(new_keyword)) { return(parse_expr_new(pos)); } if (match_keyword(sizeof_keyword)) { expect_token(TOKEN_LPAREN); if (match_token(TOKEN_COLON)) { var type = parse_type(); expect_token(TOKEN_RPAREN); return(new_expr_sizeof_type(pos, type)); } var expr = parse_expr(); expect_token(TOKEN_RPAREN); return(new_expr_sizeof_expr(pos, expr)); } if (match_keyword(alignof_keyword)) { expect_token(TOKEN_LPAREN); if (match_token(TOKEN_COLON)) { Typespec *type = parse_type(); expect_token(TOKEN_RPAREN); return(new_expr_alignof_type(pos, type)); } else { Expr *expr = parse_expr(); expect_token(TOKEN_RPAREN); return(new_expr_alignof_expr(pos, expr)); } } if (match_keyword(typeof_keyword)) { expect_token(TOKEN_LPAREN); if (match_token(TOKEN_COLON)) { Typespec *type = parse_type(); expect_token(TOKEN_RPAREN); return(new_expr_typeof_type(pos, type)); } else { Expr *expr = parse_expr(); expect_token(TOKEN_RPAREN); return(new_expr_typeof_expr(pos, expr)); } } if (match_keyword(offsetof_keyword)) { expect_token(TOKEN_LPAREN); Typespec *type = parse_type(); expect_token(TOKEN_COMMA); char *name = parse_name(); expect_token(TOKEN_RPAREN); return(new_expr_offsetof(pos, type, name)); } if (is_token(TOKEN_LBRACE)) { return(parse_expr_compound(null)); } if (match_token(TOKEN_LPAREN)) { if (match_token(TOKEN_COLON)) { var type = parse_type(); expect_token(TOKEN_RPAREN); if (is_token(TOKEN_LBRACE)) { return(parse_expr_compound(type)); } return(new_expr_cast(pos, type, parse_expr_unary())); } var expr = parse_expr(); expect_token(TOKEN_RPAREN); return(new_expr_paren(pos, expr)); } fatal_error_here("Unexpected token {0} in expression", token_info()); return(null); }
Decl *parse_decl_func(SrcPos pos) { var name = parse_name(); bool has_varargs = false; Typespec *varargs_type = null; expect_token(TOKEN_LPAREN); var buf = Buffer <FuncParam> .Create(); if (!is_token(TOKEN_RPAREN)) { buf.Add(parse_decl_func_param()); while (match_token(TOKEN_COMMA)) { if (match_token(TOKEN_ELLIPSIS)) { if (has_varargs) { error_here("Multiple ellipsis in function declaration"); } if (!is_token(TOKEN_RPAREN)) { varargs_type = parse_type(); } has_varargs = true; } else { if (has_varargs) { error_here("Ellipsis must be last parameter in function declaration"); } buf.Add(parse_decl_func_param()); } } } expect_token(TOKEN_RPAREN); Typespec *ret_type = null; if (match_token(TOKEN_COLON)) { ret_type = parse_type(); } StmtList block = default; bool is_incomplete; if (match_token(TOKEN_SEMICOLON)) { is_incomplete = true; } else { block = parse_stmt_block(); is_incomplete = false; } var decl = new_decl_func(pos, name, buf, buf.count, ret_type, has_varargs, varargs_type, block); decl->is_incomplete = is_incomplete; return(decl); }
Decl *new_decl_func(SrcPos pos, char *name, FuncParam * @params, int num_params, Typespec *ret_type, bool has_varargs, Typespec *varargs_type, StmtList block) { var d = new_decl(DECL_FUNC, pos, name); d->func.@params = @params; d->func.num_params = num_params; d->func.ret_type = ret_type; d->func.has_varargs = has_varargs; d->func.varargs_type = varargs_type; d->func.block = block; return(d); }