#include #include #include #include #include #include static void __expect(struct ctx *ctx, struct token *token, enum token_type type, const char *file, int line, const char *func, const char *type_enum) { if (token->type != type) { printf("[DBG] %s:%d: %s\n", file, line, func); token_print(ctx, token); err("Expected token of type %s!\n", type_enum); } } #define expect(token, type) __expect(ctx, token, type, __FILE__, __LINE__, __func__, #type) static struct token *next(struct token *token, size_t i) { return token + i; } static struct token *parse_declaration(struct ctx *ctx, struct token *token); static struct token *parse_expression(struct ctx *ctx, struct token *token) { struct node_expression *node = malloc(sizeof(*node)); // TODO: Push expressions into tree (using subtrees) struct token *iterator = token; while ((iterator = next(iterator, 1))) { if (iterator->type == LPAREN) { iterator = parse_expression(ctx, iterator); continue; } if (iterator->type == TYPE) { iterator = parse_declaration(ctx, iterator); continue; } if (iterator->type == RPAREN) break; if (iterator->type == EOL || iterator->type == END) expect(iterator, RPAREN); expect(iterator, IDENT); } return iterator; } static struct token *parse_declaration(struct ctx *ctx, struct token *token) { expect(next(token, 1), TYPEDELIM); expect(next(token, 2), PARAM); // Search for equal sign struct token *iterator = token; while ((iterator = next(iterator, 1))) { if (iterator->type == EQUAL) break; if (iterator->type == EOL || iterator->type == END) expect(iterator, EQUAL); } struct node_declaration *node = malloc(sizeof(*node)); node->callee.type = token->string; node->callee.name = next(token, 2)->string; // Magic size_t diff = iterator - token - 3; assert(diff % 3 == 0); node->parameters = malloc((diff / 3 + 1) * sizeof(*node->parameters)); for (size_t i = 0; i < diff / 3; i++) { struct token *param = token + (i + 1) * 3; expect(param, TYPE); expect(next(param, 2), PARAM); node->parameters[i].type = param->string; node->parameters[i].name = next(param, 2)->string; } tree_add(ctx, DECLARATION, node); return next(iterator, 1); } static struct token *parse(struct ctx *ctx, struct token *token) { switch (token->type) { case LPAREN: return parse_expression(ctx, token); case TYPE: return parse_declaration(ctx, token); case RPAREN: return next(token, 1); case END: return NULL; case UNKNOWN: case TYPEDELIM: case PARAM: case IDENT: case OPERATOR: case EQUAL: case NEWLINE: case SOMETHING: case EOL: default: expect(token, SOMETHING); } return NULL; } struct node *tree_create(void) { struct node *tree = malloc(sizeof(*tree)); tree->prev = NULL; tree->next = NULL; return tree; } void tree_add(struct ctx *ctx, enum node_type type, void *data) { assert(ctx->tree.head); struct node *node = malloc(sizeof(*node)); node->type = type; node->data = data; if (!ctx->tree.current) { ctx->tree.head->next = node; node->prev = ctx->tree.head; } else { ctx->tree.current->next = node; node->prev = ctx->tree.current; } ctx->tree.current = node; } void tree_destroy(struct node *tree) { // TODO: Destroy nodes free(tree); } void treeify(struct ctx *ctx) { struct token *token = &ctx->tokens[1]; while (token) { if (token->type == NEWLINE || token->type == EOL) { token = next(token, 1); continue; } if (token->type == END || token->type == UNKNOWN) break; token = parse(ctx, token); } }