Skip to content

Commit

Permalink
typedef and union basics
Browse files Browse the repository at this point in the history
  • Loading branch information
riicchhaarrd committed Nov 23, 2021
1 parent 4cd787b commit 2d25c30
Show file tree
Hide file tree
Showing 6 changed files with 219 additions and 88 deletions.
115 changes: 85 additions & 30 deletions ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ struct ast_context

int verbose;
jmp_buf jmp;

int numtypes;
};

static void statement(struct ast_context *ctx, struct ast_node **node);
Expand Down Expand Up @@ -176,11 +178,17 @@ static struct ast_node *identifier(struct ast_context *ctx, const char *name)
static void add_type_definition(struct ast_context *ctx, const char *key, struct ast_node *n)
{
hash_map_insert(ctx->type_definitions, key, *n);
++ctx->numtypes;
}

static struct ast_node *find_type_definition(struct ast_context *ctx, const char *key)
{
return hash_map_find(ctx->type_definitions, key);
struct ast_node *n = hash_map_find(ctx->type_definitions, key);
if(!n)
return NULL;
if(n->type == AST_TYPEDEF)
return n->typedef_data.type;
return n;
}

void expression_sequence(struct ast_context *ctx, struct ast_node **node);
Expand All @@ -190,6 +198,9 @@ static int type_qualifiers(struct ast_context *ctx, int *qualifiers)
*qualifiers = TQ_NONE;
if(!ast_accept(ctx, TK_CONST))
*qualifiers |= TQ_CONST;
/* these do not really fit in here, and should be handled differently as it's own type, but for now this will do */
else if(!ast_accept(ctx, TK_T_UNSIGNED))
*qualifiers |= TQ_UNSIGNED;
else
return 1;
return 0;
Expand All @@ -204,7 +215,7 @@ static void type_declaration_pointer(struct ast_context *ctx, struct ast_node **
for (int i = 0; i < np; ++i)
{
struct ast_node* pointer_type_node = push_node(ctx, AST_POINTER_DATA_TYPE);
pointer_type_node->pointer_data_type_data.data_type = *n;
pointer_type_node->data_type_data.data_type = *n;
*n = pointer_type_node;
}
}
Expand All @@ -226,9 +237,9 @@ static int type_declaration(struct ast_context *ctx, struct ast_node **data_type
{
int post_qualifiers = TQ_NONE;
type_qualifiers(ctx, &post_qualifiers);
struct ast_node* decl_node = push_node(ctx, AST_STRUCT_DATA_TYPE);
decl_node->struct_data_type_data.struct_ref = ref;
decl_node->struct_data_type_data.qualifiers = pre_qualifiers | post_qualifiers;
struct ast_node* decl_node = push_node(ctx, ref->type == AST_STRUCT_DECL || ref->type == AST_UNION_DECL ? AST_STRUCT_DATA_TYPE : AST_DATA_TYPE);
decl_node->data_type_data.data_type = ref;
decl_node->data_type_data.qualifiers = pre_qualifiers | post_qualifiers;
*data_type_node = decl_node;
parse_advance(&ctx->parse_context);
type_declaration_pointer(ctx, data_type_node);
Expand All @@ -241,9 +252,9 @@ static int type_declaration(struct ast_context *ctx, struct ast_node **data_type
int post_qualifiers = TQ_NONE;
type_qualifiers(ctx, &post_qualifiers);

struct ast_node* primitive_type_node = push_node( ctx, AST_PRIMITIVE_DATA_TYPE );
primitive_type_node->primitive_data_type_data.primitive_type = primitive_type;
primitive_type_node->primitive_data_type_data.qualifiers = pre_qualifiers | post_qualifiers;
struct ast_node* primitive_type_node = push_node( ctx, AST_PRIMITIVE );
primitive_type_node->primitive_data.primitive_type = primitive_type;
primitive_type_node->primitive_data.qualifiers = pre_qualifiers | post_qualifiers;
*data_type_node = primitive_type_node;

type_declaration_pointer(ctx, data_type_node);
Expand Down Expand Up @@ -299,7 +310,8 @@ static struct ast_node *ident_factor(struct ast_context *ctx)
break;
} while ( !ast_accept( ctx, ',' ) );
return n;
} else if(!ast_accept(ctx, '.') || !ast_accept(ctx, TK_ARROW))
}
while(!ast_accept(ctx, '.') || !ast_accept(ctx, TK_ARROW))
{
int as_ptr = ast_token(ctx)->type == TK_ARROW;
struct ast_node* n = push_node(ctx, AST_STRUCT_MEMBER_EXPR);
Expand All @@ -310,7 +322,7 @@ static struct ast_node *ident_factor(struct ast_context *ctx)
// structure member access
ast_expect(ctx, TK_IDENT, "expected structure member name");
n->member_expr_data.property = identifier(ctx, ast_token(ctx)->string);
return n;
ident = n;
}
return ident;
}
Expand Down Expand Up @@ -664,7 +676,7 @@ static void print_ast(struct ast_node *n, int depth)
case AST_POINTER_DATA_TYPE:
{
printf("pointer data type\n");
print_ast(n->pointer_data_type_data.data_type, depth + 1);
print_ast(n->data_type_data.data_type, depth + 1);
} break;

case AST_FUNCTION_CALL_EXPR:
Expand Down Expand Up @@ -725,13 +737,13 @@ static void print_ast(struct ast_node *n, int depth)

case AST_ARRAY_DATA_TYPE:
{
printf("array data type [%d]\n", n->array_data_type_data.array_size);
print_ast(n->array_data_type_data.data_type, depth + 1);
printf("array data type [%d]\n", n->data_type_data.array_size);
print_ast(n->data_type_data.data_type, depth + 1);
} break;

case AST_PRIMITIVE_DATA_TYPE:
case AST_PRIMITIVE:
{
printf("type %s\n", data_type_strings[n->primitive_data_type_data.primitive_type]);
printf("type %s\n", data_type_strings[n->primitive_data.primitive_type]);
} break;

case AST_RETURN_STMT:
Expand Down Expand Up @@ -776,6 +788,22 @@ static void print_ast(struct ast_node *n, int depth)
printf("sizeof\n");
print_ast(n->sizeof_data.subject, depth + 1);
} break;

case AST_STRUCT_DATA_TYPE:
{
int is_union = n->data_type_data.data_type->type == AST_UNION_DECL;
printf("%s %s\n", is_union ? "union" : "struct", n->data_type_data.data_type->struct_decl_data.name);
} break;

case AST_STRUCT_MEMBER_EXPR:
{
struct ast_node *ob = n->member_expr_data.object;
struct ast_node *prop = n->member_expr_data.property;
int arrow = n->member_expr_data.as_pointer;
printf("struct member expression %s\n", arrow ? "->" : ".");
print_ast(ob, depth + 1);
print_ast(prop, depth + 1);
} break;

default:
printf("unhandled type %s | %s:%d\n", AST_NODE_TYPE_to_string(n->type), __FILE__, __LINE__);
Expand Down Expand Up @@ -817,12 +845,12 @@ static void variable_declaration( struct ast_context* ctx, struct ast_node** out
int dc = ast_token(ctx)->integer;
ast_assert( ctx, dc > 0, "array size can't be zero" );
ast_expect(ctx, ']', "expected ] after array type declaration");
array_type_node->array_data_type_data.array_size = dc;
array_type_node->array_data_type_data.data_type = type_decl;
array_type_node->data_type_data.array_size = dc;
array_type_node->data_type_data.data_type = type_decl;
if ( ast_accept( ctx, '[' ) )
break;
struct ast_node* new_node = push_node( ctx, AST_ARRAY_DATA_TYPE );
array_type_node->array_data_type_data.data_type = new_node;
array_type_node->data_type_data.data_type = new_node;
array_type_node = new_node;
}
}
Expand Down Expand Up @@ -1053,30 +1081,56 @@ static struct ast_node *program(struct ast_context *ctx)
while(1)
{
if(!ast_accept(ctx, TK_EOF)) break;

if(!ast_accept(ctx, TK_STRUCT))
if(!ast_accept(ctx, TK_TYPEDEF))
{
ast_expect(ctx, TK_IDENT, "no name for struct type");

struct ast_node struct_node = {.parent = NULL, .type = AST_STRUCT_DECL, .rvalue = 0};
snprintf(struct_node.struct_decl_data.name, sizeof(struct_node.struct_decl_data.name), "%s",
struct ast_node typedef_node = {.parent = NULL, .type = AST_TYPEDEF, .rvalue = 0};
struct ast_node* type_decl = NULL;

int td = type_declaration( ctx , &type_decl );
ast_assert(ctx, !td, "error in type declaration for typedef");
if ( !type_decl )
ast_error( ctx, "expected type for typedef, got '%s'", token_type_to_string( parse_token(&ctx->parse_context)->type ) );
typedef_node.typedef_data.type = type_decl;
ast_expect(ctx, TK_IDENT, "expected name for typedef");
snprintf(typedef_node.typedef_data.name, sizeof(typedef_node.typedef_data.name), "%s",
ast_token(ctx)->string);
struct_node.struct_decl_data.numfields = 0;
ast_expect(ctx, ';', "no ending semicolon for typedef");
add_type_definition(ctx, typedef_node.typedef_data.name, &typedef_node);
continue;
}

if(!ast_accept(ctx, TK_STRUCT) || !ast_accept(ctx, TK_UNION))
{
int is_union_type = ast_token(ctx)->type == TK_UNION;
const char *type_string = is_union_type ? "union" : "struct";

ast_expect(ctx, '{', "no starting brace for struct type");
struct ast_node struct_node = {.parent = NULL, .type = is_union_type ? AST_UNION_DECL : AST_STRUCT_DECL, .rvalue = 0};
struct_node.struct_decl_data.numfields = 0;
if(ast_accept(ctx, '{'))
{
ast_expect(ctx, TK_IDENT, "no name for %s type", type_string);
snprintf(struct_node.struct_decl_data.name, sizeof(struct_node.struct_decl_data.name), "%s",
ast_token(ctx)->string);

ast_expect(ctx, '{', "no starting brace for %s type", type_string);
} else {
//if no name is specified set a random name
snprintf(struct_node.struct_decl_data.name, sizeof(struct_node.struct_decl_data.name), "#%s_%d", type_string, ctx->numtypes);
}

while (1)
{
struct ast_node* field_node;
variable_declaration(ctx, &field_node, 0);
if (!field_node)
break;
ast_expect(ctx, ';', "expected ; in struct field");
ast_expect(ctx, ';', "expected ; in %s field", type_string);
struct_node.struct_decl_data.fields[struct_node.struct_decl_data.numfields++] = field_node;
}

ast_expect(ctx, '}', "no ending brace for struct type");
ast_expect(ctx, ';', "no ending semicolon for struct type");
ast_expect(ctx, '}', "no ending brace for %s type", type_string);
ast_expect(ctx, ';', "no ending semicolon for %s type", type_string);

//linked_list_prepend(program_node->program_data.body, struct_node);
add_type_definition(ctx, struct_node.struct_decl_data.name, &struct_node);
Expand Down Expand Up @@ -1149,7 +1203,8 @@ int generate_ast(struct token *tokens, int num_tokens, struct linked_list **ll/*
.verbose = verbose,
.function = NULL,
.last_node = NULL,
.type_definitions = hash_map_create(struct ast_node)
.type_definitions = hash_map_create(struct ast_node),
.numtypes = 0
};

context.parse_context.current_token = NULL;
Expand Down
48 changes: 23 additions & 25 deletions ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@

struct ast_node;

#define IDENT_CHARLEN (64)

enum AST_LITERAL_TYPE
{
LITERAL_INTEGER,
Expand All @@ -50,7 +52,7 @@ struct ast_literal

union
{
char string[32]; //C's max identifier length is 31 iirc
char string[IDENT_CHARLEN]; //C's max identifier length is 31 iirc
float flt;
double dbl;
int integer;
Expand All @@ -60,7 +62,7 @@ struct ast_literal

struct ast_identifier
{
char name[64];
char name[IDENT_CHARLEN];
};

static void print_literal(struct ast_literal* lit)
Expand Down Expand Up @@ -171,42 +173,33 @@ enum TYPE_QUALIFIER
{
TQ_NONE = 0,
TQ_CONST = 1,
TQ_VOLATILE = 2
TQ_VOLATILE = 2,
TQ_UNSIGNED = 4
};

/* int,char,float,double etc...*/
struct ast_primitive_data_type
struct ast_primitive
{
int qualifiers;
int primitive_type;
int qualifiers;
};

struct ast_struct_data_type
//TODO: FIXME rename
//maybe name is too generic?
struct ast_data_type
{
struct ast_node *struct_ref;
struct ast_node *data_type;
int qualifiers;
int array_size;
};

struct ast_struct_decl
{
char name[64];
char name[IDENT_CHARLEN];
struct ast_node* fields[32]; // TODO: increase N
int numfields;
};

struct ast_array_data_type
{
struct ast_node *data_type; //can be either primitive, array or a struct e.g AoS
int array_size;
//struct ast_array_data_type *next;
};

struct ast_pointer_data_type
{
int qualifiers;
struct ast_node *data_type;
};

struct ast_variable_decl
{
struct ast_node *id;
Expand Down Expand Up @@ -250,6 +243,12 @@ struct ast_cast
struct ast_node *expr;
};

struct ast_typedef
{
char name[IDENT_CHARLEN];
struct ast_node *type;
};

struct ast_node
{
struct ast_node *parent;
Expand All @@ -275,17 +274,16 @@ struct ast_node
struct ast_return_stmt return_stmt_data;
struct ast_member_expr member_expr_data;
struct ast_variable_decl variable_decl_data;
struct ast_primitive_data_type primitive_data_type_data;
struct ast_array_data_type array_data_type_data;
struct ast_pointer_data_type pointer_data_type_data;
struct ast_primitive primitive_data;
struct ast_emit emit_data;
struct ast_sizeof sizeof_data;
struct ast_ternary_expr ternary_expr_data;
struct ast_break_stmt break_stmt_data;
struct ast_seq_expr seq_expr_data;
struct ast_cast cast_data;
struct ast_struct_data_type struct_data_type_data;
struct ast_data_type data_type_data;
struct ast_struct_decl struct_decl_data;
struct ast_typedef typedef_data;
};
};

Expand Down
5 changes: 4 additions & 1 deletion ast_node_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,20 @@ ENUM_BEGIN(AST_NODE_TYPE)
ENUM(AST_MEMBER_EXPR),
ENUM(AST_STRUCT_MEMBER_EXPR),
ENUM(AST_VARIABLE_DECL),
ENUM(AST_PRIMITIVE_DATA_TYPE),
ENUM(AST_PRIMITIVE),
ENUM(AST_ARRAY_DATA_TYPE),
ENUM(AST_POINTER_DATA_TYPE),
ENUM(AST_STRUCT_DATA_TYPE),
ENUM(AST_STRUCT_DECL),
ENUM(AST_UNION_DECL),
ENUM(AST_SIZEOF),
ENUM(AST_EMIT),
ENUM(AST_BREAK_STMT),
ENUM(AST_SEQ_EXPR),
ENUM(AST_CAST),
ENUM(AST_EMPTY),
ENUM(AST_TYPEDEF),
ENUM(AST_DATA_TYPE),
ENUM(AST_EXIT),
ENUM_VALUE(AST_INVALID, -1)
ENUM_END(AST_NODE_TYPE)
14 changes: 9 additions & 5 deletions lex.c
Original file line number Diff line number Diff line change
Expand Up @@ -473,14 +473,18 @@ static int token(struct lexer *lex, struct token *tk)
tk->type = TK_EMIT;
else if ( !strcmp( s, "struct" ) )
tk->type = TK_STRUCT;
else if ( !strcmp( s, "union" ) )
tk->type = TK_UNION;
else if ( !strcmp( s, "typedef" ) )
tk->type = TK_TYPEDEF;
}
snprintf(tk->string, sizeof(tk->string), "%s", s);
heap_string_free(&s);
snprintf(tk->string, sizeof(tk->string), "%s", s);
heap_string_free(&s);
} else
{
tk->type = TK_INVALID;
printf("got %c, unhandled error\n", ch);
return 1; //error
tk->type = TK_INVALID;
printf("got %c, unhandled error\n", ch);
return 1; //error
}
break;
}
Expand Down
Loading

0 comments on commit 2d25c30

Please sign in to comment.