start rewriting the parser to return with error messages so errors can be caught

This commit is contained in:
2025-07-09 04:58:49 +01:00
parent e234ea074b
commit c4731597f3
22 changed files with 282 additions and 149 deletions

View File

@@ -7,8 +7,8 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
ParsedValue *parse_assign(char *file, DArray *tokens, ParsedValue *assign_to, ParsedValueReturn parse_assign(char *file, DArray *tokens,
size_t *index) { ParsedValue *assign_to, size_t *index) {
Token *token = darray_get(tokens, *index); Token *token = darray_get(tokens, *index);
switch (assign_to->type) { switch (assign_to->type) {
case AST_IDENTIFIER: case AST_IDENTIFIER:
@@ -24,6 +24,7 @@ ParsedValue *parse_assign(char *file, DArray *tokens, ParsedValue *assign_to,
"only use letters, digits, or _, and can't be keywords.\n", "only use letters, digits, or _, and can't be keywords.\n",
file, token->line, token->column); file, token->line, token->column);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
break; break;
@@ -35,19 +36,25 @@ ParsedValue *parse_assign(char *file, DArray *tokens, ParsedValue *assign_to,
ParsedAssign *assign = checked_malloc(sizeof(ParsedAssign)); ParsedAssign *assign = checked_malloc(sizeof(ParsedAssign));
assign->to = assign_to; assign->to = assign_to;
assign->type = token->type; assign->type = token->type;
ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue));
parsedValue->type = AST_ASSIGN;
parsedValue->data = assign;
(*index)++; (*index)++;
error_if_finished(file, tokens, index); error_if_finished(file, tokens, index);
token = darray_get(tokens, *index); token = darray_get(tokens, *index);
assign->from = parse_token(file, tokens, index, true); ParsedValueReturn from = parse_token(file, tokens, index, true);
if (from.err.exists) {
free_parsed(parsedValue);
free(parsedValue);
return from;
}
assign->from = from.value;
if (!assign->from) { if (!assign->from) {
fprintf(stderr, "%s:%zu:%zu error: syntax error\n", file, token->line, fprintf(stderr, "%s:%zu:%zu error: syntax error\n", file, token->line,
token->column); token->column);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue)); return (ParsedValueReturn){no_err, parsedValue};
parsedValue->type = AST_ASSIGN;
parsedValue->data = assign;
return parsedValue;
} }
void free_parse_assign(void *ptr) { void free_parse_assign(void *ptr) {

View File

@@ -9,8 +9,8 @@ typedef struct {
ParsedValue * from; ParsedValue * from;
} ParsedAssign; } ParsedAssign;
ParsedValue *parse_assign(char*file, DArray *tokens, ParsedValueReturn parse_assign(char *file, DArray *tokens, ParsedValue *assign_to,
ParsedValue *assign_to, size_t *index); size_t *index);
void free_parse_assign(void*ptr); void free_parse_assign(void*ptr);

View File

@@ -4,9 +4,9 @@
#include <string.h> #include <string.h>
#include "../../../memory.h" #include "../../../memory.h"
ParsedValue *parse_identifier(Token *token) { ParsedValueReturn parse_identifier(Token *token) {
ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue)); ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue));
parsedValue->type = AST_IDENTIFIER; parsedValue->type = AST_IDENTIFIER;
parsedValue->data = strcpy(checked_malloc(strlen(token->value) + 1), token->value); parsedValue->data = strcpy(checked_malloc(strlen(token->value) + 1), token->value);
return parsedValue; return (ParsedValueReturn){no_err, parsedValue};
} }

View File

@@ -4,6 +4,6 @@
#include "../../../lexer/token.h" // for Token #include "../../../lexer/token.h" // for Token
// Function declaration for parsing an identifier // Function declaration for parsing an identifier
ParsedValue * parse_identifier(Token * token); ParsedValueReturn parse_identifier(Token *token);
#endif // IDENTIFIER_H #endif // IDENTIFIER_H

View File

@@ -1,6 +1,6 @@
#include "declaration.h" #include "declaration.h"
#include "../../hashmap/hashmap.h"
#include "../../hash_data/hash_data.h" #include "../../hash_data/hash_data.h"
#include "../../hashmap/hashmap.h"
#include "../../lexer/token.h" #include "../../lexer/token.h"
#include "../../memory.h" #include "../../memory.h"
#include "../function/function.h" #include "../function/function.h"
@@ -10,7 +10,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
ParsedValue *parse_declaration(char *file, DArray *tokens, size_t *index) { ParsedValueReturn parse_declaration(char *file, DArray *tokens, size_t *index) {
(*index)++; (*index)++;
error_if_finished(file, tokens, index); error_if_finished(file, tokens, index);
Token *token = darray_get(tokens, *index); Token *token = darray_get(tokens, *index);
@@ -30,16 +30,19 @@ ParsedValue *parse_declaration(char *file, DArray *tokens, size_t *index) {
declaration->from = parse_null(); declaration->from = parse_null();
if (token->type != TOKEN_IDENTIFIER) { if (token->type != TOKEN_IDENTIFIER) {
fprintf(stderr, "%s:%zu:%zu error: declaration requires an identifier\n", free_parsed(parsedValue);
file, token->line, token->column); free(parsedValue);
exit(EXIT_FAILURE); return (ParsedValueReturn){
create_err(token->line, token->column, token->length, file,
"Syntax Error", "declaration requires an identifier"),
NULL};
} }
declaration->name = declaration->name =
strcpy(checked_malloc(strlen(token->value) + 1), token->value); strcpy(checked_malloc(strlen(token->value) + 1), token->value);
(*index)++; (*index)++;
if ((*index) >= tokens->size) if ((*index) >= tokens->size)
return parsedValue; return (ParsedValueReturn){no_err, parsedValue};
token = darray_get(tokens, *index); token = darray_get(tokens, *index);
if (token->type == TOKEN_LPAREN) { if (token->type == TOKEN_LPAREN) {
isFunction = true; isFunction = true;
@@ -51,7 +54,7 @@ ParsedValue *parse_declaration(char *file, DArray *tokens, size_t *index) {
if (token->type == TOKEN_RPAREN) { if (token->type == TOKEN_RPAREN) {
(*index)++; (*index)++;
if ((*index) >= tokens->size) if ((*index) >= tokens->size)
return parsedValue; return (ParsedValueReturn){no_err, parsedValue};
token = darray_get(tokens, *index); token = darray_get(tokens, *index);
} else { } else {
while ((*index) < tokens->size) { while ((*index) < tokens->size) {
@@ -59,23 +62,32 @@ ParsedValue *parse_declaration(char *file, DArray *tokens, size_t *index) {
error_if_finished(file, tokens, index); error_if_finished(file, tokens, index);
token = darray_get(tokens, *index); token = darray_get(tokens, *index);
if (token->type != TOKEN_IDENTIFIER) { if (token->type != TOKEN_IDENTIFIER) {
fprintf(stderr, free_parsed(parsedValue);
"%s:%zu:%zu error: parameter names need to start with a " free(parsedValue);
"letter or _, only use letters, digits, or _, and can't be " return (ParsedValueReturn){
"keywords.\n", create_err(
file, token->line, token->column); token->line, token->column, token->length, file,
exit(EXIT_FAILURE); "Syntax Error",
"parameter names need to start with a letter or _, only "
"use letters, digits, or _, and can't be keywords."),
NULL};
} }
uint64_t hash = siphash64_bytes(token->value, token->length, siphash_key); uint64_t hash =
siphash64_bytes(token->value, token->length, siphash_key);
if (hashmap_lookup(parameters_hashmap, hash) != NULL) { if (hashmap_lookup(parameters_hashmap, hash) != NULL) {
fprintf(stderr, free_parsed(parsedValue);
"%s:%zu:%zu error: duplicate argument '%.*s' in function definition\n", free(parsedValue);
file, token->line, token->column, (int)token->length, token->value); return (ParsedValueReturn){
exit(EXIT_FAILURE); create_err(token->line, token->column, token->length, file,
"Syntax Error",
"duplicate argument in function "
"definition"),
NULL};
} }
char *parameter_name = checked_malloc(token->length + 1); char *parameter_name = checked_malloc(token->length + 1);
strcpy(parameter_name, token->value); strcpy(parameter_name, token->value);
hashmap_insert(parameters_hashmap, hash, parameter_name, (void*)1, 0); hashmap_insert(parameters_hashmap, hash, parameter_name, (void *)1,
0);
darray_push(&parameters, &parameter_name); darray_push(&parameters, &parameter_name);
(*index)++; (*index)++;
error_if_finished(file, tokens, index); error_if_finished(file, tokens, index);
@@ -85,18 +97,22 @@ ParsedValue *parse_declaration(char *file, DArray *tokens, size_t *index) {
if (token->type == TOKEN_RPAREN) { if (token->type == TOKEN_RPAREN) {
(*index)++; (*index)++;
if ((*index) >= tokens->size) if ((*index) >= tokens->size)
return parsedValue; return (ParsedValueReturn){no_err, parsedValue};
token = darray_get(tokens, *index); token = darray_get(tokens, *index);
break; break;
} else if (token->type != TOKEN_COMMA) { } else if (token->type != TOKEN_COMMA) {
fprintf(stderr, "%s:%zu:%zu error: expected comma\n", file, free_parsed(parsedValue);
token->line, token->column); free(parsedValue);
exit(EXIT_FAILURE); return (ParsedValueReturn){
create_err(token->line, token->column, token->length, file,
"Syntax Error", "expected comma"),
NULL};
} }
(*index)++; (*index)++;
error_if_finished(file, tokens, index); error_if_finished(file, tokens, index);
} }
} }
hashmap_free(parameters_hashmap, NULL);
} }
if (token->type == TOKEN_ASSIGN) { if (token->type == TOKEN_ASSIGN) {
(*index)++; (*index)++;
@@ -104,11 +120,20 @@ ParsedValue *parse_declaration(char *file, DArray *tokens, size_t *index) {
free(declaration->from); free(declaration->from);
declaration->from = parse_token(file, tokens, index, true); ParsedValueReturn from = parse_token(file, tokens, index, true);
if (from.err.exists) {
free_parsed(parsedValue);
free(parsedValue);
return from;
}
declaration->from = from.value;
if (!declaration->from) { if (!declaration->from) {
fprintf(stderr, "%s:%zu:%zu error: syntax error\n", file, token->line, free_parsed(parsedValue);
token->column); free(parsedValue);
exit(EXIT_FAILURE); return (ParsedValueReturn){create_err(token->line, token->column,
token->length, file,
"Syntax Error", "expected body"),
NULL};
} }
} }
if (isFunction) { if (isFunction) {
@@ -133,7 +158,7 @@ ParsedValue *parse_declaration(char *file, DArray *tokens, size_t *index) {
error_if_finished(file, tokens, index); error_if_finished(file, tokens, index);
token = darray_get(tokens, *index); token = darray_get(tokens, *index);
} }
return parsedValue; return (ParsedValueReturn){no_err, parsedValue};
} }
void free_string(void *ptr) { void free_string(void *ptr) {
@@ -144,9 +169,12 @@ void free_string(void *ptr) {
void free_single_declaration(void *ptr) { void free_single_declaration(void *ptr) {
ParsedSingleDeclaration *declaration = ptr; ParsedSingleDeclaration *declaration = ptr;
if (declaration->name)
free(declaration->name); free(declaration->name);
if (declaration->from) {
free_parsed(declaration->from); free_parsed(declaration->from);
free(declaration->from); free(declaration->from);
}
} }
void free_declaration(void *ptr) { void free_declaration(void *ptr) {

View File

@@ -9,8 +9,7 @@ typedef struct {
} ParsedSingleDeclaration; } ParsedSingleDeclaration;
// Function declaration for parsing an identifier // Function declaration for parsing an identifier
ParsedValue *parse_declaration(char *file, DArray *tokens, ParsedValueReturn parse_declaration(char *file, DArray *tokens, size_t *index);
size_t *index);
void free_declaration(void *ptr); void free_declaration(void *ptr);

View File

@@ -7,7 +7,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
ParsedValue *parse_dictionary(char *file, DArray *tokens, size_t *index) { ParsedValueReturn parse_dictionary(char *file, DArray *tokens, size_t *index) {
ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue)); ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue));
parsedValue->type = AST_DICTIONARY; parsedValue->type = AST_DICTIONARY;
DArray *dictionary = checked_malloc(sizeof(DArray)); DArray *dictionary = checked_malloc(sizeof(DArray));
@@ -23,17 +23,29 @@ ParsedValue *parse_dictionary(char *file, DArray *tokens, size_t *index) {
error_if_finished(file, tokens, index); error_if_finished(file, tokens, index);
size_t keyIndex = *index; size_t keyIndex = *index;
Token *keyToken = darray_get(tokens, *index); Token *keyToken = darray_get(tokens, *index);
ParsedValue *key; ParsedValueReturn key;
if (keyToken->type == TOKEN_IDENTIFIER) { if (keyToken->type == TOKEN_IDENTIFIER) {
(*index)++; (*index)++;
key = parse_string(keyToken, false); key = parse_string(keyToken, false);
} else { } else {
key = parse_token(file, tokens, index, true); key = parse_token(file, tokens, index, true);
} }
if (key.err.exists) {
free_parsed(parsedValue);
free(parsedValue);
return key;
} else if (!key.value) {
free_parsed(parsedValue);
free(parsedValue);
return (ParsedValueReturn){create_err(token->line, token->column,
token->length, file,
"Syntax Error", "expected key"),
NULL};
}
skip_newlines_and_indents(tokens, index); skip_newlines_and_indents(tokens, index);
error_if_finished(file, tokens, index); error_if_finished(file, tokens, index);
token = darray_get(tokens, *index); token = darray_get(tokens, *index);
ParsedValue *value; ParsedValueReturn value;
bool tobreak = false; bool tobreak = false;
switch (token->type) { switch (token->type) {
case TOKEN_COLON: case TOKEN_COLON:
@@ -41,6 +53,22 @@ ParsedValue *parse_dictionary(char *file, DArray *tokens, size_t *index) {
skip_newlines_and_indents(tokens, index); skip_newlines_and_indents(tokens, index);
error_if_finished(file, tokens, index); error_if_finished(file, tokens, index);
value = parse_token(file, tokens, index, true); value = parse_token(file, tokens, index, true);
if (value.err.exists) {
free_parsed(parsedValue);
free(parsedValue);
free_parsed(key.value);
free(key.value);
return value;
} else if (!value.value) {
free_parsed(parsedValue);
free(parsedValue);
free_parsed(key.value);
free(key.value);
return (ParsedValueReturn){
create_err(token->line, token->column, token->length, file,
"Syntax Error", "expected value"),
NULL};
}
skip_newlines_and_indents(tokens, index); skip_newlines_and_indents(tokens, index);
error_if_finished(file, tokens, index); error_if_finished(file, tokens, index);
token = darray_get(tokens, *index); token = darray_get(tokens, *index);
@@ -63,7 +91,7 @@ ParsedValue *parse_dictionary(char *file, DArray *tokens, size_t *index) {
token->column); token->column);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
ParsedDictionaryEntry entry = {key, value}; ParsedDictionaryEntry entry = {key.value, value.value};
darray_push(dictionary, &entry); darray_push(dictionary, &entry);
if (tobreak) { if (tobreak) {
break; break;
@@ -73,7 +101,7 @@ ParsedValue *parse_dictionary(char *file, DArray *tokens, size_t *index) {
} }
} }
(*index)++; (*index)++;
return parsedValue; return (ParsedValueReturn){no_err, parsedValue};
} }
void free_dictionary_entry(void *ptr) { void free_dictionary_entry(void *ptr) {

View File

@@ -8,8 +8,7 @@ typedef struct {
ParsedValue * value; ParsedValue * value;
} ParsedDictionaryEntry; } ParsedDictionaryEntry;
ParsedValue *parse_dictionary(char *file, DArray *tokens, ParsedValueReturn parse_dictionary(char *file, DArray *tokens, size_t *index);
size_t *index);
void free_parsed_dictionary(void *ptr); void free_parsed_dictionary(void *ptr);

View File

@@ -24,7 +24,7 @@ void free_string_dowrap(void *ptr) {
free(str); free(str);
} }
ParsedValue *parse_dowrap(char *file, DArray *tokens, size_t *index) { ParsedValueReturn parse_dowrap(char *file, DArray *tokens, size_t *index) {
ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue)); ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue));
parsedValue->type = AST_DOWRAP; parsedValue->type = AST_DOWRAP;
DArray *dowrap_parsed = checked_malloc(sizeof(DArray)); DArray *dowrap_parsed = checked_malloc(sizeof(DArray));
@@ -32,9 +32,13 @@ ParsedValue *parse_dowrap(char *file, DArray *tokens, size_t *index) {
parsedValue->data = dowrap_parsed; parsedValue->data = dowrap_parsed;
(*index)++; (*index)++;
if ((*index) >= tokens->size) if ((*index) >= tokens->size)
return parsedValue; return (ParsedValueReturn){no_err, parsedValue};
Token *token = darray_get(tokens, *index); Token *token = darray_get(tokens, *index);
if (token->type != TOKEN_NEW_LINE) { if (token->type != TOKEN_NEW_LINE) {
return (ParsedValueReturn){create_err(token->line, token->column,
token->length, file, "Syntax Error",
"expected body"),
NULL};
fprintf(stderr, "%s:%zu:%zu error: syntax error\n", file, token->line, fprintf(stderr, "%s:%zu:%zu error: syntax error\n", file, token->line,
token->column); token->column);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@@ -74,7 +78,7 @@ ParsedValue *parse_dowrap(char *file, DArray *tokens, size_t *index) {
break; break;
} }
if (temp_indent_depth > indent_depth) { if (temp_indent_depth > indent_depth) {
size_t indent_amount = temp_indent_depth-indent_depth; size_t indent_amount = temp_indent_depth - indent_depth;
Token indent_token; Token indent_token;
indent_token.line = token->line; indent_token.line = token->line;
indent_token.column = token->column; indent_token.column = token->column;
@@ -85,21 +89,27 @@ ParsedValue *parse_dowrap(char *file, DArray *tokens, size_t *index) {
} }
temp_indent_depth_toggle = false; temp_indent_depth_toggle = false;
temp_indent_depth = 0; temp_indent_depth = 0;
temp_index_count=0; temp_index_count = 0;
darray_push(&dowrap_tokens, token); darray_push(&dowrap_tokens, token);
} }
} }
(*index)-=temp_index_count; (*index) -= temp_index_count;
for (size_t i = 0; i<temp_index_count;i++) { for (size_t i = 0; i < temp_index_count; i++) {
darray_pop(&dowrap_tokens, NULL); darray_pop(&dowrap_tokens, NULL);
} }
parser(file, dowrap_parsed, &dowrap_tokens, false); ArErr err = parser(file, dowrap_parsed, &dowrap_tokens, false);
darray_free(&dowrap_tokens, NULL); darray_free(&dowrap_tokens, NULL);
darray_free(&to_free, free_string_dowrap); darray_free(&to_free, free_string_dowrap);
return parsedValue; if (err.exists) {
free_parsed(parsedValue);
free(parsedValue);
return (ParsedValueReturn){err, NULL};
}
return (ParsedValueReturn){no_err, parsedValue};
} }
void free_dowrap(void *ptr) { void free_dowrap(void *ptr) {

View File

@@ -4,8 +4,7 @@
#include "../../lexer/token.h" // for Token #include "../../lexer/token.h" // for Token
// Function declaration for parsing an identifier // Function declaration for parsing an identifier
ParsedValue *parse_dowrap(char *file, DArray *tokens, ParsedValueReturn parse_dowrap(char *file, DArray *tokens, size_t *index);
size_t *index);
void free_dowrap(void *ptr); void free_dowrap(void *ptr);

View File

@@ -1,6 +1,5 @@
#include "function.h" #include "function.h"
#include "../../memory.h" #include "../../memory.h"
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>

View File

@@ -6,7 +6,17 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
ParsedValue *parse_if(char *file, DArray *tokens, size_t *index) { void free_conditional(void *ptr) {
ParsedConditional *conditional = ptr;
if (conditional->condition) {
free_parsed(conditional->condition);
free(conditional->condition);
}
free_parsed(conditional->content);
free(conditional->content);
}
ParsedValueReturn parse_if(char *file, DArray *tokens, size_t *index) {
(*index)++; (*index)++;
error_if_finished(file, tokens, index); error_if_finished(file, tokens, index);
@@ -35,28 +45,50 @@ ParsedValue *parse_if(char *file, DArray *tokens, size_t *index) {
} }
} }
ParsedValue *condition = NULL; ParsedValueReturn condition = {no_err, NULL};
if (token->type != TOKEN_ELSE) { if (token->type != TOKEN_ELSE) {
// Parse ( condition ) // Parse ( condition )
token = darray_get(tokens, *index); token = darray_get(tokens, *index);
if (token->type != TOKEN_LPAREN) { if (token->type != TOKEN_LPAREN) {
fprintf(stderr, "%s:%zu:%zu error: expected '(' after if\n", file, darray_free(parsed_if, free_conditional);
token->line, token->column); free(parsed_if);
exit(EXIT_FAILURE); return (ParsedValueReturn){
create_err(token->line, token->column, token->length, file,
"Syntax Error", "expected '(' after if"),
NULL};
} }
(*index)++; (*index)++;
error_if_finished(file, tokens, index); error_if_finished(file, tokens, index);
skip_newlines_and_indents(tokens, index); skip_newlines_and_indents(tokens, index);
condition = parse_token(file, tokens, index, true); condition = parse_token(file, tokens, index, true);
if (condition.err.exists) {
darray_free(parsed_if, free_conditional);
free(parsed_if);
return condition;
} else if (!condition.value) {
darray_free(parsed_if, free_conditional);
free(parsed_if);
return (ParsedValueReturn){
create_err(token->line, token->column, token->length, file,
"Syntax Error", "expected condition"),
NULL};
}
skip_newlines_and_indents(tokens, index); skip_newlines_and_indents(tokens, index);
token = darray_get(tokens, *index); token = darray_get(tokens, *index);
if (token->type != TOKEN_RPAREN) { if (token->type != TOKEN_RPAREN) {
fprintf(stderr, "%s:%zu:%zu error: missing closing ')' in condition\n", if (condition.value) {
file, token->line, token->column); free_parsed(condition.value);
exit(EXIT_FAILURE); free(condition.value);
}
darray_free(parsed_if, free_conditional);
free(parsed_if);
return (ParsedValueReturn){
create_err(token->line, token->column, token->length, file,
"Syntax Error", "missing closing ')' in condition"),
NULL};
} }
(*index)++; (*index)++;
@@ -64,15 +96,32 @@ ParsedValue *parse_if(char *file, DArray *tokens, size_t *index) {
} }
// Parse the body // Parse the body
ParsedValue *parsed_content = parse_token(file, tokens, index, false); ParsedValueReturn parsed_content = parse_token(file, tokens, index, false);
if (!parsed_content) { if (parsed_content.err.exists) {
fprintf(stderr, "%s:%zu:%zu error: expected body after condition\n", file, if (condition.value) {
token->line, token->column); free_parsed(condition.value);
exit(EXIT_FAILURE); free(condition.value);
}
darray_free(parsed_if, free_conditional);
free(parsed_if);
return parsed_content;
} }
ParsedConditional conditional = {condition, parsed_content}; if (!parsed_content.value) {
if (condition.value) {
free_parsed(condition.value);
free(condition.value);
}
darray_free(parsed_if, free_conditional);
free(parsed_if);
return (ParsedValueReturn){create_err(token->line, token->column,
token->length, file, "Syntax Error",
"expected body"),
NULL};
}
ParsedConditional conditional = {condition.value, parsed_content.value};
darray_push(parsed_if, &conditional); darray_push(parsed_if, &conditional);
expect_conditional = expect_conditional =
@@ -98,17 +147,7 @@ ParsedValue *parse_if(char *file, DArray *tokens, size_t *index) {
// printf(" - content value type: %d\n", cond->content->type); // printf(" - content value type: %d\n", cond->content->type);
// } // }
return parsedValue; return (ParsedValueReturn){no_err, parsedValue};
}
void free_conditional(void *ptr) {
ParsedConditional *conditional = ptr;
if (conditional->condition) {
free_parsed(conditional->condition);
free(conditional->condition);
}
free_parsed(conditional->content);
free(conditional->content);
} }
void free_parsed_if(void *ptr) { void free_parsed_if(void *ptr) {

View File

@@ -8,8 +8,7 @@ typedef struct {
ParsedValue *content; ParsedValue *content;
} ParsedConditional; } ParsedConditional;
ParsedValue *parse_if(char *file, DArray *tokens, ParsedValueReturn parse_if(char *file, DArray *tokens, size_t *index);
size_t *index);
void free_parsed_if(void *ptr); void free_parsed_if(void *ptr);

View File

@@ -6,7 +6,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
ParsedValue *parse_list(char *file, DArray *tokens, size_t *index) { ParsedValueReturn parse_list(char *file, DArray *tokens, size_t *index) {
ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue)); ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue));
parsedValue->type = AST_LIST; parsedValue->type = AST_LIST;
DArray *list = checked_malloc(sizeof(DArray)); DArray *list = checked_malloc(sizeof(DArray));
@@ -19,9 +19,14 @@ ParsedValue *parse_list(char *file, DArray *tokens, size_t *index) {
if (token->type != TOKEN_RBRACKET) { if (token->type != TOKEN_RBRACKET) {
while (true) { while (true) {
skip_newlines_and_indents(tokens, index); skip_newlines_and_indents(tokens, index);
ParsedValue *parsedValue = parse_token(file, tokens, index, true); ParsedValueReturn parsedItem = parse_token(file, tokens, index, true);
darray_push(list, parsedValue); if (parsedItem.err.exists) {
free_parsed(parsedValue);
free(parsedValue); free(parsedValue);
return parsedItem;
}
darray_push(list, parsedItem.value);
free(parsedItem.value);
error_if_finished(file, tokens, index); error_if_finished(file, tokens, index);
skip_newlines_and_indents(tokens, index); skip_newlines_and_indents(tokens, index);
error_if_finished(file, tokens, index); error_if_finished(file, tokens, index);
@@ -38,7 +43,7 @@ ParsedValue *parse_list(char *file, DArray *tokens, size_t *index) {
} }
} }
(*index)++; (*index)++;
return parsedValue; return (ParsedValueReturn){no_err, parsedValue};
} }
void free_parsed_list(void *ptr) { void free_parsed_list(void *ptr) {

View File

@@ -3,8 +3,7 @@
#include "../../lexer/token.h" // for Token #include "../../lexer/token.h" // for Token
#include "../parser.h" #include "../parser.h"
ParsedValue *parse_list(char *file, DArray *tokens, ParsedValueReturn parse_list(char *file, DArray *tokens, size_t *index);
size_t *index);
void free_parsed_list(void *ptr); void free_parsed_list(void *ptr);

View File

@@ -150,9 +150,9 @@
// return 0; // return 0;
// } // }
ParsedValue *parse_number(Token *token) { ParsedValueReturn parse_number(Token *token) {
ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue)); ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue));
parsedValue->type = AST_NUMBER; parsedValue->type = AST_NUMBER;
parsedValue->data = strdup(token->value); parsedValue->data = strdup(token->value);
return parsedValue; return (ParsedValueReturn){no_err, parsedValue};
} }

View File

@@ -4,6 +4,6 @@
#include "../../lexer/token.h" // for Token #include "../../lexer/token.h" // for Token
// Function declaration for parsing an identifier // Function declaration for parsing an identifier
ParsedValue * parse_number(Token * token); ParsedValueReturn parse_number(Token *token);
#endif // NUMBER_H #endif // NUMBER_H

View File

@@ -54,11 +54,11 @@ size_t skip_newlines_and_indents(DArray *tokens, size_t *index) {
return count; return count;
} }
ParsedValue *parse_token_full(char *file, DArray *tokens, size_t *index, ParsedValueReturn parse_token_full(char *file, DArray *tokens, size_t *index,
bool inline_flag, bool process_operations) { bool inline_flag, bool process_operations) {
Token *token = darray_get(tokens, *index); Token *token = darray_get(tokens, *index);
ParsedValue *output = NULL; ParsedValueReturn output;
if (!inline_flag) { if (!inline_flag) {
switch (token->type) { switch (token->type) {
@@ -71,15 +71,15 @@ ParsedValue *parse_token_full(char *file, DArray *tokens, size_t *index,
switch (token->type) { switch (token->type) {
case TOKEN_TRUE: case TOKEN_TRUE:
(*index)++; (*index)++;
output = parse_true(); output = (ParsedValueReturn){no_err, parse_true()};
break; break;
case TOKEN_FALSE: case TOKEN_FALSE:
(*index)++; (*index)++;
output = parse_false(); output = (ParsedValueReturn){no_err, parse_false()};
break; break;
case TOKEN_NULL: case TOKEN_NULL:
(*index)++; (*index)++;
output = parse_null(); output = (ParsedValueReturn){no_err, parse_null()};
break; break;
case TOKEN_STRING: case TOKEN_STRING:
(*index)++; (*index)++;
@@ -87,18 +87,19 @@ ParsedValue *parse_token_full(char *file, DArray *tokens, size_t *index,
break; break;
case TOKEN_NEW_LINE: case TOKEN_NEW_LINE:
(*index)++; (*index)++;
return NULL; return (ParsedValueReturn){no_err, NULL};
case TOKEN_INDENT: case TOKEN_INDENT:
if (strlen(token->value) > 0 && (*index + 1) < tokens->size) { if (strlen(token->value) > 0 && (*index + 1) < tokens->size) {
token = darray_get(tokens, (*index) + 1); token = darray_get(tokens, (*index) + 1);
if (token->type != TOKEN_NEW_LINE) { if (token->type != TOKEN_NEW_LINE) {
fprintf(stderr, "%s:%zu:%zu error: invalid indentation\n", file, return (ParsedValueReturn){
token->line, token->column); create_err(token->line, token->column, token->length, file,
exit(EXIT_FAILURE); "Syntax Error", "unexpected indent"),
NULL};
} }
} }
(*index)++; (*index)++;
return NULL; return (ParsedValueReturn){no_err, NULL};
case TOKEN_IDENTIFIER: case TOKEN_IDENTIFIER:
(*index)++; (*index)++;
output = parse_identifier(token); output = parse_identifier(token);
@@ -128,6 +129,9 @@ ParsedValue *parse_token_full(char *file, DArray *tokens, size_t *index,
// LHS required // LHS required
bool passed = false; bool passed = false;
while (!passed && (*index) < tokens->size) { while (!passed && (*index) < tokens->size) {
if (output.err.exists) {
return output;
}
token = darray_get(tokens, *index); token = darray_get(tokens, *index);
switch (token->type) { switch (token->type) {
case TOKEN_ASSIGN: case TOKEN_ASSIGN:
@@ -138,18 +142,18 @@ ParsedValue *parse_token_full(char *file, DArray *tokens, size_t *index,
case TOKEN_ASSIGN_PLUS: case TOKEN_ASSIGN_PLUS:
case TOKEN_ASSIGN_SLASH: case TOKEN_ASSIGN_SLASH:
case TOKEN_ASSIGN_STAR: case TOKEN_ASSIGN_STAR:
output = parse_assign(file, tokens, output, index); output = parse_assign(file, tokens, output.value, index);
break; break;
case TOKEN_LPAREN: case TOKEN_LPAREN:
output = parse_call(file, tokens, index, output); output = parse_call(file, tokens, index, output.value);
break; break;
case TOKEN_DOT: case TOKEN_DOT:
case TOKEN_LBRACKET: case TOKEN_LBRACKET:
output = parse_access(file, tokens, index, output); output = parse_access(file, tokens, index, output.value);
break; break;
SWITCH_OPERATIONS SWITCH_OPERATIONS
if (process_operations) { if (process_operations) {
output = parse_operations(file, tokens, index, output); output = parse_operations(file, tokens, index, output.value);
break; break;
} }
/* fall through */ /* fall through */
@@ -161,18 +165,21 @@ ParsedValue *parse_token_full(char *file, DArray *tokens, size_t *index,
return output; return output;
} }
ParsedValue *parse_token(char *file, DArray *tokens, size_t *index, ParsedValueReturn parse_token(char *file, DArray *tokens, size_t *index,
bool inline_flag) { bool inline_flag) {
return parse_token_full(file, tokens, index, inline_flag, true); return parse_token_full(file, tokens, index, inline_flag, true);
} }
void parser(char *file, DArray *parsed, DArray *tokens, bool inline_flag) { ArErr parser(char *file, DArray *parsed, DArray *tokens, bool inline_flag) {
size_t index = 0; size_t index = 0;
bool expecting_new_line = false; bool expecting_new_line = false;
while (index < tokens->size) { while (index < tokens->size) {
size_t old_index = index; size_t old_index = index;
ParsedValue *parsed_code = parse_token(file, tokens, &index, inline_flag); ParsedValueReturn parsed_code =
if (parsed_code) { parse_token(file, tokens, &index, inline_flag);
if (parsed_code.err.exists)
return parsed_code.err;
else if (parsed_code.value) {
if (expecting_new_line) { if (expecting_new_line) {
Token *token = darray_get(tokens, old_index); Token *token = darray_get(tokens, old_index);
fprintf(stderr, "%s:%zu:%zu error: expected a new line\n", file, fprintf(stderr, "%s:%zu:%zu error: expected a new line\n", file,
@@ -180,8 +187,8 @@ void parser(char *file, DArray *parsed, DArray *tokens, bool inline_flag) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
expecting_new_line = true; expecting_new_line = true;
darray_push(parsed, parsed_code); darray_push(parsed, parsed_code.value);
free(parsed_code); free(parsed_code.value);
} else { } else {
expecting_new_line = false; expecting_new_line = false;
} }

View File

@@ -2,26 +2,28 @@
#define PARSER_H #define PARSER_H
#include "../dynamic_array/darray.h" #include "../dynamic_array/darray.h"
#include "../err.h"
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#define SWITCH_OPERATIONS case TOKEN_AND:\ #define SWITCH_OPERATIONS \
case TOKEN_OR:\ case TOKEN_AND: \
case TOKEN_NOT_IN:\ case TOKEN_OR: \
case TOKEN_IN:\ case TOKEN_NOT_IN: \
case TOKEN_LE:\ case TOKEN_IN: \
case TOKEN_GE:\ case TOKEN_LE: \
case TOKEN_LT:\ case TOKEN_GE: \
case TOKEN_GT:\ case TOKEN_LT: \
case TOKEN_NE:\ case TOKEN_GT: \
case TOKEN_EQ:\ case TOKEN_NE: \
case TOKEN_PLUS:\ case TOKEN_EQ: \
case TOKEN_MINUS:\ case TOKEN_PLUS: \
case TOKEN_MODULO:\ case TOKEN_MINUS: \
case TOKEN_STAR:\ case TOKEN_MODULO: \
case TOKEN_FLOORDIV:\ case TOKEN_STAR: \
case TOKEN_SLASH:\ case TOKEN_FLOORDIV: \
case TOKEN_CARET: case TOKEN_SLASH: \
case TOKEN_CARET:
typedef struct LinkedList LinkedList; typedef struct LinkedList LinkedList;
@@ -43,24 +45,29 @@ typedef enum {
AST_FUNCTION AST_FUNCTION
} ValueType; } ValueType;
extern const char* ValueTypeNames[]; extern const char *ValueTypeNames[];
typedef struct { typedef struct {
ValueType type; ValueType type;
void *data; void *data;
} ParsedValue; } ParsedValue;
void parser(char *file, DArray *parsed, DArray *tokens, bool inline_flag); typedef struct {
ArErr err;
ParsedValue *value;
} ParsedValueReturn;
ParsedValue *parse_token_full(char *file, DArray *tokens, size_t *index, ArErr parser(char *file, DArray *parsed, DArray *tokens, bool inline_flag);
ParsedValueReturn parse_token_full(char *file, DArray *tokens, size_t *index,
bool inline_flag, bool process_operations); bool inline_flag, bool process_operations);
ParsedValue *parse_token(char *file, DArray *tokens, size_t *index, ParsedValueReturn parse_token(char *file, DArray *tokens, size_t *index,
bool inline_flag); bool inline_flag);
void free_parsed(void *ptr); void free_parsed(void *ptr);
void error_if_finished(char *file,DArray *tokens, size_t *index); void error_if_finished(char *file, DArray *tokens, size_t *index);
size_t skip_newlines_and_indents(DArray *tokens, size_t *index); size_t skip_newlines_and_indents(DArray *tokens, size_t *index);

View File

@@ -245,7 +245,7 @@ char *unquote(char *str, size_t *decoded_len) {
return unescaped; return unescaped;
} }
ParsedValue *parse_string(Token* token, bool to_unquote) { ParsedValueReturn parse_string(Token* token, bool to_unquote) {
ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue)); ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue));
parsedValue->type = AST_STRING; parsedValue->type = AST_STRING;
ParsedString *parsedString = checked_malloc(sizeof(ParsedString)); ParsedString *parsedString = checked_malloc(sizeof(ParsedString));
@@ -253,11 +253,19 @@ ParsedValue *parse_string(Token* token, bool to_unquote) {
if (to_unquote) { if (to_unquote) {
parsedString->length = 0; parsedString->length = 0;
parsedString->string = unquote(token->value, &parsedString->length); parsedString->string = unquote(token->value, &parsedString->length);
if (!parsedString->string) {
free(parsedValue);
free(parsedString);
return (ParsedValueReturn){create_err(token->line, token->column,
token->length, NULL, "String Error",
"failed to unquote string %s", token->value),
NULL};
}
} else { } else {
parsedString->string = strdup(token->value); parsedString->string = strdup(token->value);
parsedString->length = token->length; parsedString->length = token->length;
} }
return parsedValue; return (ParsedValueReturn){no_err,parsedValue};
} }
void free_parsed_string(void *ptr) { void free_parsed_string(void *ptr) {

View File

@@ -15,7 +15,7 @@ char *swap_quotes(char *input, char quote);
char *unquote(char *str, size_t *decoded_len); char *unquote(char *str, size_t *decoded_len);
ParsedValue *parse_string(Token* token, bool to_unquote); ParsedValueReturn parse_string(Token* token, bool to_unquote);
void free_parsed_string(void *ptr); void free_parsed_string(void *ptr);

View File

@@ -1 +1 @@
10~10 ~