diff --git a/src/lexer/lex.l b/src/lexer/lex.l index ddb33ae..edd1586 100644 --- a/src/lexer/lex.l +++ b/src/lexer/lex.l @@ -108,7 +108,7 @@ int yywrap(void * unused_param) { . { GET_STATE - fprintf(stderr, "%s:%u:%u error: unexpected character '%s'\n", state->path, yylineno, COLUMN_NO+1, yytext); + fprintf(stderr, "%s:%zu:%zu error: unexpected character '%s'\n", state->path, state->current_line+1, COLUMN_NO+1, yytext); exit(1); } %% \ No newline at end of file diff --git a/src/lexer/lexer.c b/src/lexer/lexer.c index fe59df6..e1603c6 100644 --- a/src/lexer/lexer.c +++ b/src/lexer/lexer.c @@ -13,11 +13,12 @@ void lexer(LexerState state) { int token; while ((token = yylex(scanner)) != 0) { Token *token_struct = - create_token(token, yyget_lineno(scanner), state.current_column + 1, + create_token(token, state.current_line+1, state.current_column + 1, yyget_text(scanner)); darray_push(state.tokens, token_struct); free(token_struct); if (token == TOKEN_NEW_LINE) { + state.current_line += 1; state.current_column = 0; } else { state.current_column += yyget_leng(scanner); diff --git a/src/lexer/lexer.h b/src/lexer/lexer.h index 8af7c77..0d7b51a 100644 --- a/src/lexer/lexer.h +++ b/src/lexer/lexer.h @@ -8,7 +8,8 @@ typedef struct { const char *path; FILE *file; - int current_column; + size_t current_line; + size_t current_column; DArray *tokens; // add more fields as needed } LexerState; diff --git a/src/lexer/token.h b/src/lexer/token.h index 7892554..10c2288 100644 --- a/src/lexer/token.h +++ b/src/lexer/token.h @@ -1,6 +1,7 @@ #ifndef TOKEN_H #define TOKEN_H +#include typedef enum { TOKEN_STRING = 256, TOKEN_NUMBER, @@ -76,8 +77,8 @@ typedef enum { typedef struct { TokenType type; - int line; - int column; + size_t line; + size_t column; char *value; } Token; diff --git a/src/main.c b/src/main.c index 5156a7a..bb8c1dc 100644 --- a/src/main.c +++ b/src/main.c @@ -17,7 +17,7 @@ int main(int argc, char *argv[]) { darray_init(&tokens, sizeof(Token)); - LexerState state = {path, fopen(path, "r"), 0, &tokens}; + LexerState state = {path, fopen(path, "r"), 0, 0, &tokens}; lexer(state); fclose(state.file); diff --git a/src/parser/assignable/access/access.c b/src/parser/assignable/access/access.c index cd2e54d..31e3818 100644 --- a/src/parser/assignable/access/access.c +++ b/src/parser/assignable/access/access.c @@ -12,7 +12,7 @@ ParsedValue *parse_access(char*file,DArray *tokens, size_t * index, ParsedValue ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue)); ParsedAccess *parsedAccess = checked_malloc(sizeof(ParsedAccess)); parsedAccess->to_access = to_access; - parsedAccess->access = strcpy(checked_malloc(sizeof(token->value)), token->value); + parsedAccess->access = strcpy(checked_malloc(strlen(token->value) + 1), token->value); parsedValue->type = AST_ACCESS; parsedValue->data = parsedAccess; return parsedValue; diff --git a/src/parser/assignable/assign/assign.c b/src/parser/assignable/assign/assign.c index e3879f8..8ffb520 100644 --- a/src/parser/assignable/assign/assign.c +++ b/src/parser/assignable/assign/assign.c @@ -1,28 +1,42 @@ #include "assign.h" #include "../../../lexer/token.h" +#include "../../../memory.h" #include "../../parser.h" +#include "../call/call.h" #include #include #include -#include "../../../memory.h" -ParsedValue *parse_assign(char *file, DArray *tokens, - ParsedValue *assign_to, size_t *index) { +ParsedValue *parse_assign(char *file, DArray *tokens, ParsedValue *assign_to, + size_t *index) { Token *token = darray_get(tokens, *index); switch (assign_to->type) { - case AST_IDENTIFIER: - case AST_ASSIGN: - break; - default: - fprintf(stderr, "%s:%u:%u error: can't assign to %s\n", file, token->line, - token->column, ValueTypeNames[assign_to->type]); - exit(EXIT_FAILURE); + case AST_IDENTIFIER: + case AST_ASSIGN: + break; + case AST_CALL:; + ParsedCall *call = assign_to->data; + for (size_t i = 0; i < call->args->size; i++) { + if (((ParsedValue *)darray_get(call->args, i))->type != AST_IDENTIFIER) { + fprintf( + stderr, + "%s:%zu:%zu error: parameter names need to start with a letter or _, " + "only use letters, digits, or _, and can't be keywords.\n", + file, token->line, token->column); + exit(EXIT_FAILURE); + } + } + break; + default: + fprintf(stderr, "%s:%zu:%zu error: can't assign to %s\n", file, token->line, + token->column, ValueTypeNames[assign_to->type]); + exit(EXIT_FAILURE); } ParsedAssign *assign = checked_malloc(sizeof(ParsedAssign)); assign->to = assign_to; assign->type = token->type; (*index)++; - error_if_finished(file,tokens,index); + error_if_finished(file, tokens, index); token = darray_get(tokens, *index); assign->from = parse_token(file, tokens, index, true); ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue)); diff --git a/src/parser/assignable/call/call.c b/src/parser/assignable/call/call.c index 49ea61f..2de6570 100644 --- a/src/parser/assignable/call/call.c +++ b/src/parser/assignable/call/call.c @@ -8,42 +8,41 @@ ParsedValue *parse_call(char *file, DArray *tokens, size_t *index, ParsedValue *to_call) { + ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue)); + ParsedCall *call = checked_malloc(sizeof(ParsedCall)); + call->to_call = to_call; + parsedValue->data = call; + parsedValue->type = AST_CALL; + call->args = checked_malloc(sizeof(DArray)); + darray_init(call->args, sizeof(ParsedValue)); (*index)++; error_if_finished(file, tokens, index); - ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue)); - ParsedCall *parsedCall = checked_malloc(sizeof(ParsedCall)); - DArray *args = checked_malloc(sizeof(DArray)); - darray_init(args, sizeof(ParsedValue)); - parsedCall->to_call = to_call; - parsedCall->args = args; - parsedValue->type = AST_ACCESS; - parsedValue->data = parsedCall; Token *token = darray_get(tokens, *index); - DArray *arg = checked_malloc(sizeof(DArray)); - darray_init(arg, sizeof(ParsedValue)); - while (true) { - bool to_break = false; - switch (token->type) { - case TOKEN_RPAREN: - to_break = true; - break; - default: - break; - } - if (to_break) - break; - ParsedValue *parsedValue = parse_token(file, tokens, index, true); - darray_push(arg, parsedValue); - free(parsedValue); - switch (token->type) { - case TOKEN_COMMA: - darray_push(args, arg); - free(arg); - arg = checked_malloc(sizeof(DArray)); - darray_init(arg, sizeof(ParsedValue)); - break; - default: - break; + if (token->type == TOKEN_RPAREN) { + (*index)++; + if ((*index) >= tokens->size) + return parsedValue; + token = darray_get(tokens, *index); + } else { + while ((*index) < tokens->size) { + ParsedValue *parsedArg = parse_token(file, tokens, index, true); + darray_push(call->args, parsedArg); + free(parsedArg); + error_if_finished(file, tokens, index); + token = darray_get(tokens, *index); + if (token->type == TOKEN_RPAREN) { + (*index)++; + if ((*index) >= tokens->size) + break; + token = darray_get(tokens, *index); + break; + } else if (token->type != TOKEN_COMMA) { + fprintf(stderr, "%s:%zu:%zu error: expected comma\n", file, token->line, + token->column); + exit(EXIT_FAILURE); + } + (*index)++; + error_if_finished(file, tokens, index); } } return parsedValue; @@ -53,9 +52,7 @@ void free_parse_call(void *ptr) { ParsedValue *parsedValue = ptr; ParsedCall *parsedCall = parsedValue->data; + darray_free(parsedCall->args, free_parsed); free_parsed(parsedCall->to_call); - - - free(parsedCall); } \ No newline at end of file diff --git a/src/parser/assignable/identifier/identifier.c b/src/parser/assignable/identifier/identifier.c index 28e7864..88c4aec 100644 --- a/src/parser/assignable/identifier/identifier.c +++ b/src/parser/assignable/identifier/identifier.c @@ -7,6 +7,6 @@ ParsedValue *parse_identifier(Token *token) { ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue)); parsedValue->type = AST_IDENTIFIER; - parsedValue->data = strcpy(checked_malloc(sizeof(token->value)), token->value); + parsedValue->data = strcpy(checked_malloc(strlen(token->value) + 1), token->value); return parsedValue; } \ No newline at end of file diff --git a/src/parser/declaration/declaration.c b/src/parser/declaration/declaration.c index 366234f..4296817 100644 --- a/src/parser/declaration/declaration.c +++ b/src/parser/declaration/declaration.c @@ -1,76 +1,125 @@ #include "declaration.h" #include "../../lexer/token.h" #include "../../memory.h" -#include "../parser.h" #include "../literals/literals.h" +#include "../parser.h" #include #include #include -ParsedValue *parse_declaration(char *file, DArray *tokens, - size_t *index) { +ParsedValue *parse_declaration(char *file, DArray *tokens, size_t *index) { (*index)++; error_if_finished(file, tokens, index); Token *token = darray_get(tokens, *index); - ParsedValue * parsedValue = malloc(sizeof(ParsedValue)); - ParsedDeclaration * declaration = malloc(sizeof(ParsedDeclaration)); - declaration->is_function = false; - declaration->from = parse_null(); - parsedValue->data = declaration; + ParsedValue *parsedValue = malloc(sizeof(ParsedValue)); parsedValue->type = AST_DECLARATION; + DArray *declarations = malloc(sizeof(DArray)); + darray_init(declarations, sizeof(ParsedSingleDeclaration)); + parsedValue->data = declarations; + while (true) { + ParsedSingleDeclaration _declaration = {}; + darray_push(declarations, &_declaration); + ParsedSingleDeclaration *declaration = + darray_get(declarations, declarations->size - 1); + declaration->is_function = false; + declaration->from = parse_null(); - if (token->type != TOKEN_IDENTIFIER) { - fprintf(stderr, "%s:%u:%u error: declaration requires an identifier\n", - file, token->line, token->column); - exit(EXIT_FAILURE); - } - declaration->name = strcpy(checked_malloc(sizeof(token->value)), token->value); + if (token->type != TOKEN_IDENTIFIER) { + fprintf(stderr, "%s:%zu:%zu error: declaration requires an identifier\n", + file, token->line, token->column); + exit(EXIT_FAILURE); + } + declaration->name = + strcpy(checked_malloc(strlen(token->value) + 1), token->value); - (*index)++; - if ((*index) >= tokens->size) { - return parsedValue; - } - token = darray_get(tokens, *index); - if (token->type == TOKEN_LPAREN) { - declaration->is_function = true; - declaration->parameters = checked_malloc(sizeof(DArray)); - darray_init(declaration->parameters, sizeof(char*)); (*index)++; - error_if_finished(file, tokens, index); - while(true) { - token = darray_get(tokens, *index); - if (token->type != TOKEN_IDENTIFIER) { - fprintf(stderr, "%s:%u:%u error: parameter names need to start with a letter or _, only use letters, digits, or _, and can't be keywords.\n", - file, token->line, token->column); - exit(EXIT_FAILURE); - } - darray_push(declaration->parameters, strcpy(checked_malloc(sizeof(token->value)), token->value)); + if ((*index) >= tokens->size) + return parsedValue; + token = darray_get(tokens, *index); + if (token->type == TOKEN_LPAREN) { + declaration->is_function = true; + declaration->parameters = checked_malloc(sizeof(DArray)); + darray_init(declaration->parameters, sizeof(char *)); (*index)++; error_if_finished(file, tokens, index); token = darray_get(tokens, *index); if (token->type == TOKEN_RPAREN) { (*index)++; - error_if_finished(file, tokens, index); + if ((*index) >= tokens->size) + return parsedValue; token = darray_get(tokens, *index); - break; - } else if (token->type != TOKEN_COMMA) { - fprintf(stderr, "%s:%u:%u error: expected comma\n", - file, token->line, token->column); - exit(EXIT_FAILURE); + } else { + while ((*index) < tokens->size) { + token = darray_get(tokens, *index); + if (token->type != TOKEN_IDENTIFIER) { + fprintf(stderr, + "%s:%zu:%zu error: parameter names need to start with a " + "letter or _, only use letters, digits, or _, and can't be " + "keywords.\n", + file, token->line, token->column); + exit(EXIT_FAILURE); + } + char *parameter_name = + strcpy(checked_malloc(strlen(token->value) + 1), token->value); + darray_push(declaration->parameters, ¶meter_name); + (*index)++; + error_if_finished(file, tokens, index); + token = darray_get(tokens, *index); + if (token->type == TOKEN_RPAREN) { + (*index)++; + if ((*index) >= tokens->size) + return parsedValue; + token = darray_get(tokens, *index); + break; + } else if (token->type != TOKEN_COMMA) { + fprintf(stderr, "%s:%zu:%zu error: expected comma\n", file, + token->line, token->column); + exit(EXIT_FAILURE); + } + (*index)++; + error_if_finished(file, tokens, index); + } } + } + if (token->type == TOKEN_ASSIGN) { (*index)++; error_if_finished(file, tokens, index); + + free(declaration->from); + + declaration->from = parse_token(file, tokens, index, true); + if ((*index) >= tokens->size) + break; + token = darray_get(tokens, *index); } + if (token->type != TOKEN_COMMA) + break; + (*index)++; + error_if_finished(file, tokens, index); + token = darray_get(tokens, *index); } - if (token->type != TOKEN_ASSIGN) return parsedValue; - - (*index)++; - error_if_finished(file, tokens, index); - - free(declaration->from); - - declaration->from = parse_token(file, tokens, index, true); - return parsedValue; +} + +void free_string(void *ptr) { + // `ptr` is a pointer to a char* + char *str = *(char **)ptr; + free(str); +} + +void free_single_declaration(void *ptr) { + ParsedSingleDeclaration *declaration = ptr; + free(declaration->name); + if (declaration->is_function) + darray_free(declaration->parameters, free_string); + free_parsed(declaration->from); + free(declaration->from); +} + +void free_declaration(void *ptr) { + ParsedValue *parsedValue = ptr; + DArray *declaration = parsedValue->data; + darray_free(declaration, free_single_declaration); + free(declaration); } \ No newline at end of file diff --git a/src/parser/declaration/declaration.h b/src/parser/declaration/declaration.h index 571da4d..358add9 100644 --- a/src/parser/declaration/declaration.h +++ b/src/parser/declaration/declaration.h @@ -8,10 +8,12 @@ typedef struct { bool is_function; DArray * parameters; // string[] ParsedValue * from; -} ParsedDeclaration; +} ParsedSingleDeclaration; // Function declaration for parsing an identifier ParsedValue *parse_declaration(char *file, DArray *tokens, size_t *index); +void free_declaration(void *ptr); + #endif // DECLARATION_H \ No newline at end of file diff --git a/src/parser/if/if.c b/src/parser/if/if.c index 9bdca56..9bbf038 100644 --- a/src/parser/if/if.c +++ b/src/parser/if/if.c @@ -42,7 +42,7 @@ ParsedValue *parse_if(char *file, DArray *tokens, token = darray_get(tokens, *index); if (token->type != TOKEN_LPAREN) { fprintf(stderr, - "%s:%u:%u error: expected '(' after if\n", + "%s:%zu:%zu error: expected '(' after if\n", file, token->line, token->column); exit(EXIT_FAILURE); } @@ -67,7 +67,7 @@ ParsedValue *parse_if(char *file, DArray *tokens, if (token->type != TOKEN_RPAREN) { fprintf(stderr, - "%s:%u:%u error: missing closing ')' in condition\n", + "%s:%zu:%zu error: missing closing ')' in condition\n", file, token->line, token->column); exit(EXIT_FAILURE); } @@ -82,7 +82,7 @@ ParsedValue *parse_if(char *file, DArray *tokens, if (!parsed_content) { fprintf(stderr, - "%s:%u:%u error: expected body after condition\n", + "%s:%zu:%zu error: expected body after condition\n", file, token->line, token->column); exit(EXIT_FAILURE); } diff --git a/src/parser/parser.c b/src/parser/parser.c index cc53d4d..1d21f44 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -8,6 +8,7 @@ #include "number/number.h" #include "string/string.h" #include "literals/literals.h" +#include "assignable/call/call.h" #include #include #include @@ -21,7 +22,7 @@ const char *ValueTypeNames[] = {"string", "assign", "identifier", 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, + fprintf(stderr, "%s:%zu:%zu error: syntax error\n", file, token->line, token->column); exit(EXIT_FAILURE); } @@ -67,7 +68,7 @@ ParsedValue *parse_token(char *file, DArray *tokens, size_t *index, output = parse_token(file, tokens, index, inline_flag); break; case TOKEN_INDENT: - fprintf(stderr, "%s:%u:%u error: invalid indentation\n", file, token->line, + fprintf(stderr, "%s:%zu:%zu error: invalid indentation\n", file, token->line, token->column); exit(EXIT_FAILURE); case TOKEN_IDENTIFIER: @@ -82,7 +83,7 @@ ParsedValue *parse_token(char *file, DArray *tokens, size_t *index, output = parse_declaration(file, tokens, index); break; default: - fprintf(stderr, "%s:%u:%u error: syntax error\n", file, token->line, + fprintf(stderr, "%s:%zu:%zu error: syntax error\n", file, token->line, token->column); exit(EXIT_FAILURE); } @@ -102,6 +103,9 @@ ParsedValue *parse_token(char *file, DArray *tokens, size_t *index, case TOKEN_ASSIGN_STAR:; output = parse_assign(file, tokens, output, index); break; + case TOKEN_LPAREN: + output = parse_call(file, tokens, index, output); + break; default: passed = true; } @@ -131,6 +135,12 @@ void free_parsed(void *ptr) { case AST_ASSIGN: free_parse_assign(parsed); break; + case AST_DECLARATION: + free_declaration(parsed); + break; + case AST_CALL: + free_parse_call(parsed); + break; case AST_NUMBER: case AST_NULL: case AST_BOOLEAN: diff --git a/test.ar b/test.ar index 1813ee1..1ec6e30 100644 --- a/test.ar +++ b/test.ar @@ -1,2 +1,2 @@ -let a -a = 10 \ No newline at end of file +let a, b = 1, c, d = 42, temp_result, compute_area(radius) = 3.1415, identity(x) = x, f(x), g(y, z), result, z = 0, extremely_long_variable_name_to_test_limits, cache_value = compute_area(5), placeholder_fn_with_no_body(arg1, arg2, arg3), total = identity(100), deeply_nested_args_function(arg1, arg2, arg3, arg4, arg5), sum = a, another, another_function(), just_null_here, +x = 10 \ No newline at end of file