diff options
author | metamuffin <metamuffin@disroot.org> | 2024-10-09 16:05:33 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2024-10-09 16:05:33 +0200 |
commit | bcf69099f11a09882309b4590b55c0a3a7d5caba (patch) | |
tree | 257e1fc8817abe75ce9f4b98c68ef271d26669e1 | |
parent | 0140eab52ab1d584c6526c242f173e6a55130589 (diff) | |
download | attocc-bcf69099f11a09882309b4590b55c0a3a7d5caba.tar attocc-bcf69099f11a09882309b4590b55c0a3a7d5caba.tar.bz2 attocc-bcf69099f11a09882309b4590b55c0a3a7d5caba.tar.zst |
more parse
-rw-r--r-- | attocc.c | 179 |
1 files changed, 147 insertions, 32 deletions
@@ -337,7 +337,7 @@ struct token *tokenize(char *source) { continue; } else if (p[0] == '/' && p[1] == '*') { p += 2; - for (char c, d = '\0'; (d = c, c = *p++) && !(c == '/' && d == '*');) + for (char c = '\0', d; (d = c, c = *p++) && !(c == '/' && d == '*');) ; continue; } else if (p[0] == '#') { @@ -583,14 +583,27 @@ struct node { NO_STRUCT, NO_UNION, NO_ENUM, + NO_TYPE_PRIMITIVE, + NO_TYPE_POINTER, NO_FUNCTION, NO_COMPOUND, + NO_TR_UNIT, } kind; union node_data { + struct node *type_pointer; + enum node_primitive_type { + PRIMTY_U64, + PRIMTY_I32, + PRIMTY_U8, + } primitive_type; + struct node_data_tr_unit { + unsigned long num_elements; + struct node **elements; + } tr_unit; struct node_data_function { struct node *return_type; char *name; - int num_arguments; + unsigned long num_arguments; struct function_argument { char *name; struct node *type; @@ -598,7 +611,7 @@ struct node { struct node *body; } function; struct node_data_compound { - int num_statements; + unsigned long num_statements; struct node **statements; } compount; struct node_data_binop { @@ -617,29 +630,110 @@ struct node { } data; }; -struct node *parse_enum_decl(int *p, struct token *tokens); +struct node *parse_enum_decl(int *p, struct token *tokens, char **error); +struct node *parse_function(int *p, struct token *tokens, char **error); +struct node *parse_type(int *p, struct token *tokens, char **error); +struct node *parse_toplevel(int *p, struct token *tokens, char **error); -struct node *parse_type(int *p, struct token *tokens) { +struct node *parse(int *p, struct token *tokens, char **error) { + int num_elements = 0; + struct node **elements = NULL; + while (1) { + struct node *el = parse_toplevel(p, tokens, error); + if (!el) { + if (tokens[*p].kind == TOK_END) + break; + else + return NULL; + } + num_elements += 1; + elements = realloc_failsafe(elements, num_elements * sizeof(struct node *)); + elements[num_elements - 1] = el; + } + struct node *node = realloc_failsafe(NULL, sizeof(struct node)); + node->kind = NO_TR_UNIT; + node->data.tr_unit.elements = elements; + node->data.tr_unit.num_elements = num_elements; + return node; +} + +struct node *parse_toplevel(int *p, struct token *tokens, char **error) { struct node *out; - out = parse_enum_decl(p, tokens); + out = parse_type(p, tokens, error); + if (out) + return out; + out = parse_function(p, tokens, error); if (out) return out; return NULL; } -struct node *parse_function(int *p, struct token *tokens) { - struct node *return_type = parse_type(p, tokens); +struct node *parse_type(int *p, struct token *tokens, char **error) { + struct node *out; + out = parse_enum_decl(p, tokens, error); + if (out) + return out; + + if (tokens[*p].kind == TOK_IDENTIFIER) { + struct node *node = realloc_failsafe(NULL, sizeof(struct node)); + node->kind = NO_TYPE_PRIMITIVE; + node->data.primitive_type = PRIMTY_I32; + } + + return NULL; +} + +struct node *parse_function(int *p, struct token *tokens, char **error) { + struct node *return_type = parse_type(p, tokens, error); if (!return_type) return NULL; + if (tokens[*p].kind != TOK_IDENTIFIER) + return NULL; + char *name = strdup_failsafe(tokens[*p].data.identifier); + *p += 1; + + if (tokens[*p].kind != TOK_SEPERATOR || + tokens[*p].data.seperator != SEP_LPAREN) + return NULL; + *p += 1; + + int num_arguments = 0; + struct function_argument *arguments = NULL; + + while (1) { + if (tokens[*p].kind == TOK_END) + return NULL; + if (tokens[*p].kind == TOK_SEPERATOR && + tokens[*p].data.seperator == SEP_RPAREN) + break; + + struct node *type = parse_type(p, tokens, error); + if (tokens[*p].kind != TOK_IDENTIFIER) + return NULL; + char *name = strdup_failsafe(tokens->data.identifier); + *p += 1; + + if (tokens[*p].kind == TOK_SEPERATOR && + tokens[*p].data.seperator == SEP_COMMA) + *p += 1; + + num_arguments += 1; + arguments = realloc_failsafe( + arguments, num_arguments * sizeof(struct function_argument)); + arguments[num_arguments - 1].name = name; + arguments[num_arguments - 1].type = type; + } + struct node *node = realloc_failsafe(NULL, sizeof(struct node)); node->kind = NO_FUNCTION; node->data.function.return_type = return_type; + node->data.function.name = name; return node; } -struct node *parse_enum_decl(int *p, struct token *tokens) { +struct node *parse_enum_decl(int *p, struct token *tokens, char **error) { if (tokens[*p].kind != TOK_KEYWORD || tokens[*p].data.keyword != KW_ENUM) return 0; *p += 1; @@ -721,33 +815,44 @@ struct node *parse_enum_decl(int *p, struct token *tokens) { return node; } -struct node *parse(int *p, struct token *tokens) { - return parse_type(p, tokens); +#ifdef DEBUG +void indent(int k) { + for (int i = 0; i < k; i++) { + printf(" "); + } } -#ifdef DEBUG -void debug_node(struct node *node) { +void debug_node(struct node *node, int k) { switch (node->kind) { case NO_ENUM: + indent(k); printf("NO_ENUM\n"); - printf(" name=%s\n", node->data.enum_.name); - printf(" is_decl=%i\n", node->data.enum_.is_decl); + indent(k + 1); + printf("name=%s\n", node->data.enum_.name); + indent(k + 1); + printf("is_decl=%i\n", node->data.enum_.is_decl); if (node->data.enum_.is_decl) { - printf(" num_members=%li\n", node->data.enum_.num_members); - printf(" members\n"); - for (int i = 0; i < node->data.enum_.num_members; i++) { - printf(" %s=%i\n", node->data.enum_.members[i].name, + indent(k + 1); + printf("num_members=%li\n", node->data.enum_.num_members); + indent(k + 1); + printf("members\n"); + for (unsigned long i = 0; i < node->data.enum_.num_members; i++) { + indent(k + 2); + printf("%s=%i\n", node->data.enum_.members[i].name, node->data.enum_.members[i].value); } } break; case NO_BINOP: + indent(k); printf("NO_BINOP\n"); - printf(" lhs: "); - debug_node(node->data.binop.lhs); + indent(k + 1); + printf("lhs: "); + debug_node(node->data.binop.lhs, k + 2); printf("\n"); - printf(" rhs: "); - debug_node(node->data.binop.rhs); + indent(k + 1); + printf("rhs: "); + debug_node(node->data.binop.rhs, k + 2); printf("\n"); break; case NO_MEMBER_ACCESS: @@ -765,6 +870,11 @@ void debug_node(struct node *node) { case NO_UNOP: printf("NO_UNOP\n"); break; + case NO_TR_UNIT: + indent(k); + printf("NO_TR_UNIT\n"); + for (unsigned long i = 0; i < node->data.tr_unit.num_elements; i++) + debug_node(node->data.tr_unit.elements[i], k + 1); default: break; } @@ -812,21 +922,21 @@ int main(int argc, char **argv) { char *input = argv[1]; char *output = argv[2]; - printf("open input\n"); int input_fd = open(input, O_RDONLY | O_CLOEXEC); if (input_fd < 0) { perror("cannot open input"); return 1; } - - printf("open output\n"); int output_fd = open(output, O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, 0640); if (output_fd < 0) { perror("cannot open input"); return 1; } - printf("read input\n"); +#ifdef DEBUG + printf("\n=== READ INPUT ===\n"); +#endif + int source_len = 0; char *source = NULL; int size; @@ -845,25 +955,30 @@ int main(int argc, char **argv) { } source[source_len] = '\0'; - printf("tokenize\n"); +#ifdef DEBUG + printf("%i bytes loaded\n", source_len); + printf("\n=== TOKENIZE ===\n"); +#endif + struct token *tokens = tokenize(source); if (!tokens) return 1; #ifdef DEBUG debug_tokens(tokens); + printf("\n=== PARSE ===\n"); #endif - printf("parse\n"); int p = 0; - struct node *node = parse(&p, tokens); + char *error = "no message"; + struct node *node = parse(&p, tokens, &error); if (!node) { - printf("parse failed\n"); + printf("parse failed: %s\n", error); return 1; } #ifdef DEBUG - debug_node(node); + debug_node(node, 0); #endif free_tokens(tokens); |