summaryrefslogtreecommitdiff
path: root/src/parser/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser/parser.c')
-rw-r--r--src/parser/parser.c135
1 files changed, 113 insertions, 22 deletions
diff --git a/src/parser/parser.c b/src/parser/parser.c
index a74da06..6b6d015 100644
--- a/src/parser/parser.c
+++ b/src/parser/parser.c
@@ -35,7 +35,8 @@
#include "parser/ast.h"
#include "parser/types.h"
-#define SYMS_HASHMAP_ROWS 16
+#define SYMS_HASHMAP_ROWS 16
+#define PARAMS_HASHMAP_ROWS 4
static void
tok_error(struct token *tok, const char *fmt, ...)
@@ -48,17 +49,122 @@ tok_error(struct token *tok, const char *fmt, ...)
va_end(args);
}
+static void
+tok_warn(struct token *tok, const char *fmt, ...)
+{
+ va_list args;
+
+ fprintf(stderr, "\033[1;97m%d:%d: \033[1;95mwarning: \033[0m", tok->line, tok->col);
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+}
+
+static struct type *
+parse_type_ref(struct parser *ctx, int *ptr_levels_out)
+{
+ struct type *type;
+ int ptr_levels;
+
+ /*
+ * TODO: Parse custom types.
+ */
+ if (!(ctx->tok.flags & TF_BUILTIN_TYPE)) {
+ tok_error(&ctx->tok, "expected built-in type name\n");
+ return NULL;
+ }
+
+ type = types_find_builtin(ctx->tok.kind);
+ if (type == NULL) {
+ return NULL;
+ }
+
+ parser_advance(ctx);
+ ptr_levels = 0;
+ while (ctx->tok.kind == TOK_ASTERISK) {
+ ptr_levels++;
+ parser_advance(ctx);
+ }
+
+ *ptr_levels_out = ptr_levels;
+ return type;
+}
+
static bool
-parse_func_decl(struct parser *ctx, struct ast_node *func)
+parse_params(struct parser *ctx, struct ast_node *func)
{
- func->kind = NOK_FUNCTION;
+ struct type *type;
+ int ptr_levels;
+ struct ast_node *node;
+
+ func->params.rows = malloc(PARAMS_HASHMAP_ROWS * sizeof(struct list));
+ if (func->params.rows == NULL) {
+ return false;
+ }
+
+ func->params.row_count = PARAMS_HASHMAP_ROWS;
+ hashmap_init(func->params);
/*
- * TODO: Parse parameters.
+ * TODO: Free memory if parsing parameters fails.
*/
+ while (ctx->tok.kind != TOK_RPAREN) {
+ type = parse_type_ref(ctx, &ptr_levels);
+ if (type == NULL) {
+ return false;
+ }
+
+ if (ctx->tok.kind != TOK_IDENTIFIER) {
+ tok_error(&ctx->tok, "expected parameter name after type\n");
+ return false;
+ }
+
+ node = malloc(sizeof(struct ast_node));
+ if (node == NULL) {
+ log_error("failed to allocate memory for AST node\n");
+ return false;
+ }
+
+ node->kind = NOK_PARAMETER;
+ node->name = ctx->tok.pos;
+ node->name_len = ctx->tok.len;
+ node->type = type;
+ node->ptr_levels = ptr_levels;
+ node->hashmap_entry.hash = ctx->tok.hash;
+ hashmap_add(func->params, &node->hashmap_entry);
+
+ parser_advance(ctx);
+ if (ctx->tok.kind == TOK_COMMA) {
+ parser_advance(ctx);
+ if (ctx->tok.kind == TOK_RPAREN) {
+ tok_warn(&ctx->tok, "extra \",\" at end of parameter list\n");
+ }
+
+ continue;
+ }
+ }
+
+ return true;
+}
+
+static bool
+parse_func_decl(struct parser *ctx, struct ast_node *func)
+{
+ func->kind = NOK_FUNCTION;
+
+ /* Skip "void" marking no parameters */
parser_advance(ctx);
- if (ctx->tok.kind != TOK_RPAREN) {
- tok_error(&ctx->tok, "expected \")\" after \"(\"\n");
+ if (ctx->tok.kind == TOK_VOID) {
+ parser_advance(ctx);
+ if (ctx->tok.kind != TOK_RPAREN) {
+ tok_error(&ctx->tok, "expected \")\" after \"void\"\n");
+ free(func);
+ return false;
+ }
+ }
+
+ /* Parse parameters if present */
+ if (ctx->tok.kind != TOK_RPAREN && !parse_params(ctx, func)) {
free(func);
return false;
}
@@ -112,26 +218,11 @@ parse_decl(struct parser *ctx)
int ptr_levels;
struct ast_node *node;
- /*
- * TODO: Parse custom types.
- */
- if (!(ctx->tok.flags & TF_BUILTIN_TYPE)) {
- tok_error(&ctx->tok, "expected type\n");
- return false;
- }
-
- type = types_find_builtin(ctx->tok.kind);
+ type = parse_type_ref(ctx, &ptr_levels);
if (type == NULL) {
return false;
}
- parser_advance(ctx);
- ptr_levels = 0;
- while (ctx->tok.kind == TOK_ASTERISK) {
- ptr_levels++;
- parser_advance(ctx);
- }
-
if (ctx->tok.kind != TOK_IDENTIFIER) {
tok_error(&ctx->tok, "expected identifier after type\n");
return false;