From 18993a5d7e7e2b9255328b7c4d2a169638121491 Mon Sep 17 00:00:00 2001 From: William Bell Date: Tue, 3 Jun 2025 13:24:12 +0100 Subject: [PATCH] add if statements --- src/hashmap/hashmap.c | 7 +-- src/lexer/token.c | 3 +- src/list/list.c | 7 +-- src/memory.c | 9 ++++ src/memory.h | 2 + src/parser/assign/assign.c | 6 ++- src/parser/identifier/identifier.c | 6 +-- src/parser/if/if.c | 68 ++++++++++++++++++++++++++++++ src/parser/if/if.h | 18 ++++++++ src/parser/number/number.c | 6 +-- src/parser/parser.c | 26 +++++++++--- src/parser/parser.h | 3 ++ src/parser/string/string.c | 5 ++- src/string/string.c | 3 +- src/translator/translator.c | 3 +- test.ar | 2 +- 16 files changed, 148 insertions(+), 26 deletions(-) create mode 100644 src/parser/if/if.c create mode 100644 src/parser/if/if.h diff --git a/src/hashmap/hashmap.c b/src/hashmap/hashmap.c index 54d7e15..787172d 100644 --- a/src/hashmap/hashmap.c +++ b/src/hashmap/hashmap.c @@ -1,12 +1,13 @@ #include "hashmap.h" #include +#include "../memory.h" struct table *createTable(int size) { - struct table *t = (struct table *)malloc(sizeof(struct table)); + struct table *t = (struct table *)checked_malloc(sizeof(struct table)); t->size = size; - t->list = (struct node **)malloc(sizeof(struct node *) * size); + t->list = (struct node **)checked_malloc(sizeof(struct node *) * size); int i; for (i = 0; i < size; i++) t->list[i] = NULL; @@ -48,7 +49,7 @@ void insert(struct table *t, int key, void* val) { int pos = hashCode(t, key); struct node *list = t->list[pos]; - struct node *newNode = (struct node *)malloc(sizeof(struct node)); + struct node *newNode = (struct node *)checked_malloc(sizeof(struct node)); struct node *temp = list; while (temp) { diff --git a/src/lexer/token.c b/src/lexer/token.c index 861bdf9..68742c1 100644 --- a/src/lexer/token.c +++ b/src/lexer/token.c @@ -1,9 +1,10 @@ #include "token.h" #include "../string/string.h" #include +#include "../memory.h" Token *create_token(TokenType type, int line, int column, char *value) { - Token *token = malloc(sizeof(Token)); + Token *token = checked_malloc(sizeof(Token)); token->type = type; token->line = line; token->column = column; diff --git a/src/list/list.c b/src/list/list.c index 081e675..c84d0d4 100644 --- a/src/list/list.c +++ b/src/list/list.c @@ -2,9 +2,10 @@ #include #include #include +#include "../memory.h" LinkedList *create_list(size_t data_size) { - LinkedList *list = malloc(sizeof(LinkedList)); + LinkedList *list = checked_malloc(sizeof(LinkedList)); list->head = NULL; list->data_size = data_size; list->length = 0; @@ -12,8 +13,8 @@ LinkedList *create_list(size_t data_size) { } void append(LinkedList *list, void *element) { - Node *new_node = malloc(sizeof(Node)); - new_node->data = malloc(list->data_size); + Node *new_node = checked_malloc(sizeof(Node)); + new_node->data = checked_malloc(list->data_size); memcpy(new_node->data, element, list->data_size); new_node->next = NULL; diff --git a/src/memory.c b/src/memory.c index 733ac12..3744178 100644 --- a/src/memory.c +++ b/src/memory.c @@ -4,7 +4,16 @@ #include #include // for malloc/free (temp arena fallback) #include +#include +void *checked_malloc(size_t size) { + void *ptr = malloc(size); + if (!ptr) { + fprintf(stderr, "fatal error: failed to allocate %zu bytes\n", size); + exit(EXIT_FAILURE); + } + return ptr; +} void *gmp_gc_realloc(void *ptr, size_t old_size, size_t new_size) { (void)old_size; // Ignore old_size, Boehm doesn't need it diff --git a/src/memory.h b/src/memory.h index bdcce36..b3650a2 100644 --- a/src/memory.h +++ b/src/memory.h @@ -11,4 +11,6 @@ char *ar_strdup(const char *str); // Memory init/shutdown void ar_memory_init(); +void *checked_malloc(size_t size); + #endif // ARGON_MEMORY_H \ No newline at end of file diff --git a/src/parser/assign/assign.c b/src/parser/assign/assign.c index 079cccb..a3eaa79 100644 --- a/src/parser/assign/assign.c +++ b/src/parser/assign/assign.c @@ -4,6 +4,7 @@ #include #include #include +#include "../../memory.h" ParsedValue *parse_assign(char *file, DArray *parsed, DArray *tokens, ParsedValue *assign_to, size_t *index) { @@ -17,13 +18,14 @@ ParsedValue *parse_assign(char *file, DArray *parsed, DArray *tokens, token->column, ValueTypeNames[assign_to->type]); exit(EXIT_FAILURE); } - ParsedAssign *assign = malloc(sizeof(ParsedAssign)); + ParsedAssign *assign = checked_malloc(sizeof(ParsedAssign)); assign->to = assign_to; assign->type = token->type; (*index)++; + error_if_finished(file,tokens,index); token = darray_get(tokens, *index); assign->from = parse_token(file, parsed, tokens, index, true); - ParsedValue *parsedValue = malloc(sizeof(ParsedValue)); + ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue)); parsedValue->type = AST_ASSIGN; parsedValue->data = assign; return parsedValue; diff --git a/src/parser/identifier/identifier.c b/src/parser/identifier/identifier.c index a9f5c57..075e7d4 100644 --- a/src/parser/identifier/identifier.c +++ b/src/parser/identifier/identifier.c @@ -1,12 +1,12 @@ #include "identifier.h" #include "../../lexer/token.h" #include "../parser.h" -#include #include +#include "../../memory.h" ParsedValue *parse_identifier(Token *token) { - ParsedValue *parsedValue = malloc(sizeof(ParsedValue)); + ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue)); parsedValue->type = AST_IDENTIFIER; - parsedValue->data = strcpy(malloc(sizeof(token->value)), token->value); + parsedValue->data = strcpy(checked_malloc(sizeof(token->value)), token->value); return parsedValue; } \ No newline at end of file diff --git a/src/parser/if/if.c b/src/parser/if/if.c new file mode 100644 index 0000000..30f50e2 --- /dev/null +++ b/src/parser/if/if.c @@ -0,0 +1,68 @@ +#include "if.h" +#include "../../lexer/token.h" +#include "../parser.h" +#include +#include +#include +#include "../../memory.h" + +ParsedValue *parse_if(char *file, DArray *parsed, DArray *tokens, + size_t *index) { + (*index)++; + error_if_finished(file, tokens, index); + Token *token = darray_get(tokens, *index); + if (token->type != TOKEN_LPAREN) { + fprintf(stderr, + "%s:%u:%u error: if statement requires paren for the condition\n", + file, token->line, token->column); + exit(EXIT_FAILURE); + } + (*index)++; + error_if_finished(file, tokens, index); + DArray *parsed_if = checked_malloc(sizeof(DArray)); + darray_init(parsed_if, sizeof(ParsedConditional)); + DArray *condition = checked_malloc(sizeof(DArray)); + darray_init(condition, sizeof(ParsedValue)); + while ((*index) < tokens->size) { + ParsedValue *parsed_code = parse_token(file, parsed, tokens, index, true); + if (parsed_code) { + darray_push(condition, parsed_code); + free(parsed_code); + } + token = darray_get(tokens, *index); + if (token->type == TOKEN_RPAREN) + break; + } + if (token->type != TOKEN_RPAREN) { + fprintf(stderr, + "%s:%u:%u error: missing closing parenthesis in if condition\n", + file, token->line, token->column); + exit(EXIT_FAILURE); + } + (*index)++; + error_if_finished(file, tokens, index); + ParsedValue *parsed_content = parse_token(file, parsed, tokens, index, true); + if (!parsed_content) { + fprintf(stderr, "%s:%u:%u error: expected body after if condition\n", file, + token->line, token->column); + exit(EXIT_FAILURE); + } + ParsedConditional output_conditional = {condition, parsed_content}; + darray_push(parsed_if, &output_conditional); + ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue)); + parsedValue->type = AST_IF; + parsedValue->data = parsed_if; + return parsedValue; +} + +void free_conditional(void *ptr) { + ParsedConditional *conditional = ptr; + darray_free(conditional->condition, free_parsed); + free_parsed(conditional->content); +} + +void free_parsed_if(void *ptr) { + ParsedValue *parsedValue = ptr; + DArray *parsed_if = parsedValue->data; + darray_free(parsed_if, free_conditional); +} \ No newline at end of file diff --git a/src/parser/if/if.h b/src/parser/if/if.h new file mode 100644 index 0000000..391b314 --- /dev/null +++ b/src/parser/if/if.h @@ -0,0 +1,18 @@ +// parser.h + +#ifndef iF_H +#define iF_H +#include "../parser.h" +#include "../../lexer/token.h" // for Token + +typedef struct { + DArray * condition; + ParsedValue * content; +} ParsedConditional; + +ParsedValue *parse_if(char *file, DArray *parsed, DArray *tokens, size_t *index); + +void free_parsed_if(void *ptr); + + +#endif // iF_H \ No newline at end of file diff --git a/src/parser/number/number.c b/src/parser/number/number.c index 37218b4..baff3c6 100644 --- a/src/parser/number/number.c +++ b/src/parser/number/number.c @@ -1,12 +1,12 @@ #include "number.h" #include "../../lexer/token.h" #include "../parser.h" -#include +#include "../../memory.h" #include ParsedValue *parse_number(Token *token) { - ParsedValue *parsedValue = malloc(sizeof(ParsedValue)); - mpz_t *number = malloc(sizeof(mpz_t)); + ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue)); + mpz_t *number = checked_malloc(sizeof(mpz_t)); mpz_init_set_str(*number, token->value, 10); parsedValue->type = AST_NUMBER; parsedValue->data = number; diff --git a/src/parser/parser.c b/src/parser/parser.c index 8c5bd3f..bd0ef43 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -2,8 +2,9 @@ #include "../dynamic_array/darray.h" #include "../lexer/token.h" #include "assign/assign.h" -#include "number/number.h" #include "identifier/identifier.h" +#include "if/if.h" +#include "number/number.h" #include "string/string.h" #include #include @@ -11,13 +12,24 @@ #include #include -const char *ValueTypeNames[] = {"string", "assign", "identifier", "number"}; +const char *ValueTypeNames[] = {"string", "assign", "identifier", "number", "if statement"}; + +void error_if_finished(char *file, DArray *tokens, size_t *index) { + if ((*index) >= tokens->size) { + Token *token = darray_get(tokens, tokens->size - 1); + fprintf(stderr, "%s:%u:%u error: syntax error\n", file, token->line, + token->column); + exit(EXIT_FAILURE); + } +} ParsedValue *parse_token(char *file, DArray *parsed, DArray *tokens, size_t *index, bool inline_flag) { Token *token = darray_get(tokens, *index); if (!inline_flag) { switch (token->type) { + case TOKEN_IF: + return parse_if(file, parsed, tokens, index); default: break; }; @@ -70,9 +82,9 @@ ParsedValue *parse_token(char *file, DArray *parsed, DArray *tokens, token->column); exit(EXIT_FAILURE); } - ParsedValue *assigning_to = darray_get(parsed, parsed->size-1); + ParsedValue *assigning_to = darray_get(parsed, parsed->size - 1); fprintf(stderr, "%s:%u:%u error: cannot assign to %s\n", file, token->line, - token->column, ValueTypeNames[assigning_to->type]); + token->column, ValueTypeNames[assigning_to->type]); exit(EXIT_FAILURE); case TOKEN_NUMBER: (*index)++; @@ -85,8 +97,7 @@ ParsedValue *parse_token(char *file, DArray *parsed, DArray *tokens, void parser(char *file, DArray *parsed, DArray *tokens, bool inline_flag) { size_t index = 0; - size_t length = tokens->size; - while (index < length) { + while (index < tokens->size) { ParsedValue *parsed_code = parse_token(file, parsed, tokens, &index, inline_flag); if (parsed_code) { @@ -108,5 +119,8 @@ void free_parsed(void *ptr) { break; case AST_NUMBER: break; + case AST_IF: + free_parsed_if(parsed); + break; } } \ No newline at end of file diff --git a/src/parser/parser.h b/src/parser/parser.h index 68d9c0e..178ba9e 100644 --- a/src/parser/parser.h +++ b/src/parser/parser.h @@ -12,6 +12,7 @@ typedef enum { AST_ASSIGN, AST_IDENTIFIER, AST_NUMBER, + AST_IF, } ValueType; extern const char* ValueTypeNames[]; @@ -28,4 +29,6 @@ ParsedValue *parse_token(char *file, DArray *parsed, DArray *tokens, void free_parsed(void *ptr); +void error_if_finished(char *file,DArray *tokens, size_t *index); + #endif // PARSER_H \ No newline at end of file diff --git a/src/parser/string/string.c b/src/parser/string/string.c index 6049dd6..594e137 100644 --- a/src/parser/string/string.c +++ b/src/parser/string/string.c @@ -6,10 +6,11 @@ #include #include #include +#include "../../memory.h" char *swap_quotes(char *input, char quote) { size_t len = strlen(input); - char *result = malloc(len + 1); + char *result = checked_malloc(len + 1); if (!result) return NULL; @@ -73,7 +74,7 @@ char *unquote(char *str) { } ParsedValue *parse_string(Token token) { - ParsedValue *parsedValue = malloc(sizeof(ParsedValue)); + ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue)); parsedValue->type = AST_STRING; parsedValue->data = unquote(token.value); return parsedValue; diff --git a/src/string/string.c b/src/string/string.c index 9019b81..af61cfd 100644 --- a/src/string/string.c +++ b/src/string/string.c @@ -3,6 +3,7 @@ #include #include #include +#include "../memory.h" const char *WHITE_SPACE = " \t\n\r\f\v"; @@ -12,7 +13,7 @@ char *cloneString(char *str) { } size_t len = strlen(str); - char *clone = malloc((len + 1) * sizeof(char)); + char *clone = checked_malloc((len + 1) * sizeof(char)); if (clone == NULL) { return NULL; diff --git a/src/translator/translator.c b/src/translator/translator.c index 00d89e8..9697b8a 100644 --- a/src/translator/translator.c +++ b/src/translator/translator.c @@ -2,9 +2,10 @@ #include "../dynamic_array/darray.h" #include #include +#include "../memory.h" Translated *init_translator() { - Translated *translated = malloc(sizeof(Translated)); + Translated *translated = checked_malloc(sizeof(Translated)); if (!translated) return NULL; diff --git a/test.ar b/test.ar index 52ab0e7..cade759 100644 --- a/test.ar +++ b/test.ar @@ -1 +1 @@ -x=10 \ No newline at end of file +if (x=10) "hello world" \ No newline at end of file