From 86c0eabfdeea47b2142cb08f1a693971f0697b5d Mon Sep 17 00:00:00 2001 From: William Bell Date: Tue, 10 Jun 2025 04:41:06 +0100 Subject: [PATCH] add operations --- .vscode/launch.json | 26 ++++++ Makefile | 8 +- src/lexer/token.h | 26 +++--- src/parser/assignable/assign/assign.c | 4 +- src/parser/assignable/call/call.c | 7 +- src/parser/assignable/call/call.h | 2 +- src/parser/assignable/identifier/identifier.h | 2 - src/parser/declaration/declaration.c | 7 +- src/parser/declaration/declaration.h | 2 +- src/parser/dowrap/dowrap.c | 2 - src/parser/if/if.c | 28 +++---- src/parser/if/if.h | 4 +- src/parser/number/number.h | 2 - src/parser/operations/operations.c | 81 +++++++++++++++++++ src/parser/operations/operations.h | 15 ++++ src/parser/parser.c | 25 ++++-- src/parser/parser.h | 27 ++++++- test.ar | 7 +- 18 files changed, 207 insertions(+), 68 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 src/parser/operations/operations.c create mode 100644 src/parser/operations/operations.h diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..8066bfc --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,26 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "C/C++ Debug (gdb Launch)", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/bin/argon", + "args": ["test.ar"], + "stopAtEntry": true, + "cwd": "${workspaceFolder}", + "environment": [], + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + } + ] +} \ No newline at end of file diff --git a/Makefile b/Makefile index 5eb5c12..16782aa 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ LEXER_C = src/lexer/lex.yy.c LEXER_H = src/lexer/lex.yy.h CFILES = $(shell find src -name '*.c') -CFLAGS = -lm -lcjson -lgc -lgmp -Wall -Wextra -Wno-unused-function -s +CFLAGS = -lm -lcjson -lgc -lgmp -Wall -Wextra -Wno-unused-function BINARY = bin/argon all: $(BINARY) @@ -13,12 +13,16 @@ $(LEXER_C) $(LEXER_H): $(LEXER_SRC) $(BINARY): $(CFILES) $(LEXER_C) $(LEXER_H) mkdir -p bin - gcc -O3 -o $(BINARY) $(CFILES) $(CFLAGS) + gcc -O3 -o $(BINARY) $(CFILES) $(CFLAGS) -s debug: $(CFILES) $(LEXER_C) $(LEXER_H) mkdir -p bin gcc -g -O0 -o $(BINARY) $(CFILES) $(CFLAGS) +full-debug: $(CFILES) $(LEXER_C) $(LEXER_H) + mkdir -p bin + gcc -g -O0 -fsanitize=address -fno-omit-frame-pointer -o $(BINARY) $(CFILES) $(CFLAGS) + optimised: $(CFILES) $(LEXER_C) $(LEXER_H) mkdir -p bin gcc -O3 -fprofile-generate -o $(BINARY) $(CFILES) $(CFLAGS) diff --git a/src/lexer/token.h b/src/lexer/token.h index 10c2288..f79887b 100644 --- a/src/lexer/token.h +++ b/src/lexer/token.h @@ -21,22 +21,22 @@ typedef enum { TOKEN_ASSIGN_CARET, // Operators - TOKEN_AND, // && - TOKEN_OR, // || - TOKEN_NOT_IN, // not in - TOKEN_LE, // <= - TOKEN_GE, // >= + TOKEN_CARET, // ^ (Exponentiation) + TOKEN_STAR, // * (Multiplication) + TOKEN_SLASH, // / (Division) + TOKEN_FLOORDIV, // // (Floor Division) + TOKEN_MODULO, // % (Modulo) + TOKEN_PLUS, // + (Addition) + TOKEN_MINUS, // - (Subtraction) TOKEN_LT, // < TOKEN_GT, // > - TOKEN_NE, // != + TOKEN_LE, // <= + TOKEN_GE, // >= TOKEN_EQ, // == - TOKEN_PLUS, // + - TOKEN_MINUS, // - - TOKEN_MODULO, // % - TOKEN_STAR, // * - TOKEN_FLOORDIV, // // - TOKEN_SLASH, // / - TOKEN_CARET, // ^ + TOKEN_NE, // != + TOKEN_NOT_IN, // not in (Usually treated like a comparison) + TOKEN_AND, // && + TOKEN_OR, // || // Keywords TOKEN_IF, diff --git a/src/parser/assignable/assign/assign.c b/src/parser/assignable/assign/assign.c index 5e51e84..fdf2c2b 100644 --- a/src/parser/assignable/assign/assign.c +++ b/src/parser/assignable/assign/assign.c @@ -16,8 +16,8 @@ ParsedValue *parse_assign(char *file, DArray *tokens, ParsedValue *assign_to, 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) { + 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 _, " diff --git a/src/parser/assignable/call/call.c b/src/parser/assignable/call/call.c index 3cb43ae..02819cb 100644 --- a/src/parser/assignable/call/call.c +++ b/src/parser/assignable/call/call.c @@ -13,8 +13,7 @@ ParsedValue *parse_call(char *file, DArray *tokens, size_t *index, call->to_call = to_call; parsedValue->data = call; parsedValue->type = AST_CALL; - call->args = checked_malloc(sizeof(DArray)); - darray_init(call->args, sizeof(ParsedValue)); + darray_init(&call->args, sizeof(ParsedValue)); (*index)++; error_if_finished(file, tokens, index); Token *token = darray_get(tokens, *index); @@ -23,7 +22,7 @@ ParsedValue *parse_call(char *file, DArray *tokens, size_t *index, skip_newlines_and_indents(tokens, index); error_if_finished(file, tokens, index); ParsedValue *parsedArg = parse_token(file, tokens, index, true); - darray_push(call->args, parsedArg); + darray_push(&call->args, parsedArg); free(parsedArg); error_if_finished(file, tokens, index); skip_newlines_and_indents(tokens, index); @@ -48,7 +47,7 @@ void free_parse_call(void *ptr) { ParsedValue *parsedValue = ptr; ParsedCall *parsedCall = parsedValue->data; - darray_free(parsedCall->args, free_parsed); + 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/call/call.h b/src/parser/assignable/call/call.h index 1b430ae..3675c9a 100644 --- a/src/parser/assignable/call/call.h +++ b/src/parser/assignable/call/call.h @@ -5,7 +5,7 @@ typedef struct { ParsedValue * to_call; - DArray * args; + DArray args; } ParsedCall; // Function declaration for parsing an identifier diff --git a/src/parser/assignable/identifier/identifier.h b/src/parser/assignable/identifier/identifier.h index ea03d2f..6cbaf49 100644 --- a/src/parser/assignable/identifier/identifier.h +++ b/src/parser/assignable/identifier/identifier.h @@ -1,5 +1,3 @@ -// parser.h - #ifndef IDENTIFIER_H #define IDENTIFIER_H #include "../../parser.h" diff --git a/src/parser/declaration/declaration.c b/src/parser/declaration/declaration.c index 14122cf..b80ebcf 100644 --- a/src/parser/declaration/declaration.c +++ b/src/parser/declaration/declaration.c @@ -39,8 +39,7 @@ ParsedValue *parse_declaration(char *file, DArray *tokens, size_t *index) { 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 *)); + darray_init(&declaration->parameters, sizeof(char *)); (*index)++; error_if_finished(file, tokens, index); token = darray_get(tokens, *index); @@ -62,7 +61,7 @@ ParsedValue *parse_declaration(char *file, DArray *tokens, size_t *index) { } char *parameter_name = strcpy(checked_malloc(strlen(token->value) + 1), token->value); - darray_push(declaration->parameters, ¶meter_name); + darray_push(&declaration->parameters, ¶meter_name); (*index)++; error_if_finished(file, tokens, index); skip_newlines_and_indents(tokens, index); @@ -127,7 +126,7 @@ void free_single_declaration(void *ptr) { ParsedSingleDeclaration *declaration = ptr; free(declaration->name); if (declaration->is_function) - darray_free(declaration->parameters, free_string); + darray_free(&declaration->parameters, free_string); free_parsed(declaration->from); free(declaration->from); } diff --git a/src/parser/declaration/declaration.h b/src/parser/declaration/declaration.h index 358add9..7a7c9e1 100644 --- a/src/parser/declaration/declaration.h +++ b/src/parser/declaration/declaration.h @@ -6,7 +6,7 @@ typedef struct { char * name; bool is_function; - DArray * parameters; // string[] + DArray parameters; // string[] ParsedValue * from; } ParsedSingleDeclaration; diff --git a/src/parser/dowrap/dowrap.c b/src/parser/dowrap/dowrap.c index a64fb4d..6de7101 100644 --- a/src/parser/dowrap/dowrap.c +++ b/src/parser/dowrap/dowrap.c @@ -48,8 +48,6 @@ ParsedValue *parse_dowrap(char *file, DArray *tokens, size_t *index) { DArray to_free; darray_init(&to_free, sizeof(char *)); - size_t starting_index = *index; - size_t temp_index_count = 0; while (!pass && ++(*index) < tokens->size) { diff --git a/src/parser/if/if.c b/src/parser/if/if.c index b241ff8..76aa075 100644 --- a/src/parser/if/if.c +++ b/src/parser/if/if.c @@ -35,7 +35,7 @@ ParsedValue *parse_if(char *file, DArray *tokens, size_t *index) { } } - DArray *condition = NULL; + ParsedValue *condition = NULL; if (token->type != TOKEN_ELSE) { // Parse ( condition ) @@ -48,22 +48,11 @@ ParsedValue *parse_if(char *file, DArray *tokens, size_t *index) { (*index)++; error_if_finished(file, tokens, index); + skip_newlines_and_indents(tokens, index); + condition = parse_token(file, tokens, index, true); + skip_newlines_and_indents(tokens, index); - condition = checked_malloc(sizeof(DArray)); - darray_init(condition, sizeof(ParsedValue)); - - while (*index < tokens->size) { - ParsedValue *parsed_code = parse_token(file, 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; - } - + token = darray_get(tokens, *index); if (token->type != TOKEN_RPAREN) { fprintf(stderr, "%s:%zu:%zu error: missing closing ')' in condition\n", file, token->line, token->column); @@ -114,8 +103,10 @@ ParsedValue *parse_if(char *file, DArray *tokens, size_t *index) { void free_conditional(void *ptr) { ParsedConditional *conditional = ptr; - if (conditional->condition) - darray_free(conditional->condition, free_parsed); + if (conditional->condition) { + free_parsed(conditional->condition); + free(conditional->condition); + } free_parsed(conditional->content); free(conditional->content); } @@ -124,4 +115,5 @@ void free_parsed_if(void *ptr) { ParsedValue *parsedValue = ptr; DArray *parsed_if = parsedValue->data; darray_free(parsed_if, free_conditional); + free(parsedValue->data); } \ No newline at end of file diff --git a/src/parser/if/if.h b/src/parser/if/if.h index c8ebedc..38ef858 100644 --- a/src/parser/if/if.h +++ b/src/parser/if/if.h @@ -1,12 +1,10 @@ -// parser.h - #ifndef iF_H #define iF_H #include "../../lexer/token.h" // for Token #include "../parser.h" typedef struct { - DArray *condition; // NULL for 'else' + ParsedValue * condition; // NULL for 'else' ParsedValue *content; } ParsedConditional; diff --git a/src/parser/number/number.h b/src/parser/number/number.h index 768314a..230291c 100644 --- a/src/parser/number/number.h +++ b/src/parser/number/number.h @@ -1,5 +1,3 @@ -// parser.h - #ifndef NUMBER_H #define NUMBER_H #include "../parser.h" diff --git a/src/parser/operations/operations.c b/src/parser/operations/operations.c new file mode 100644 index 0000000..652f454 --- /dev/null +++ b/src/parser/operations/operations.c @@ -0,0 +1,81 @@ +#include "operations.h" +#include "../parser.h" +#include "../../memory.h" +#include +#include +#include + +ParsedValue *convert_to_operation(DArray * to_operate_on, DArray * operations) { + if (to_operate_on->size == 1) { + return darray_get(to_operate_on, 0); + } + TokenType operation = 0; + DArray positions; + for (size_t i = 0; isize;i++) { + TokenType * current_operation = darray_get(operations, i); + if (operation < *current_operation) { + if (operation!=0) { + darray_free(&positions, NULL); + } + operation = *current_operation; + darray_init(&positions, sizeof(size_t)); + } + darray_push(&positions, &i); + } + size_t last_position = operations->size-1; + darray_push(&positions, &last_position); + ParsedValue * parsedValue = checked_malloc(sizeof(ParsedValue)); + parsedValue->type = AST_OPERATION; + ParsedOperation * operationStruct = checked_malloc(sizeof(ParsedOperation)); + parsedValue->data = operationStruct; + operationStruct->operation = operation; + darray_init(&operationStruct->to_operate_on, sizeof(ParsedValue)); + last_position = 0; + for (size_t i = 0; ito_operate_on, convert_to_operation(&to_operate_on_slice, &operations_slice)); + last_position = *position; + } + darray_free(&positions, NULL); + return parsedValue; +} + +ParsedValue *parse_operations(char *file, DArray *tokens, size_t *index, + ParsedValue *first_parsed_value) { + DArray to_operate_on; + darray_init(&to_operate_on, sizeof(ParsedValue)); + darray_push(&to_operate_on, first_parsed_value); + + DArray operations; + darray_init(&operations, sizeof(TokenType)); + + while (tokens->size > *index) { + bool to_break = false; + Token *token = darray_get(tokens, *index); + switch (token->type) { + SWITCH_OPERATIONS + break; + default: + to_break = true; + } + if (to_break) + break; + darray_push(&operations, &token->type); + (*index)++; + error_if_finished(file, tokens, index); + darray_push(&to_operate_on, parse_token_full(file, tokens, index, true, false)); + } + ParsedValue *output = convert_to_operation(&to_operate_on, &operations); + darray_free(&to_operate_on, free_parsed); + darray_free(&operations, free_parsed); + return output; +} + +void free_operation(void *ptr) { + ParsedValue *parsedValue = ptr; + ParsedOperation *parsed_operation = parsedValue->data; + darray_free(&parsed_operation->to_operate_on, free_parsed); + free(parsed_operation); +} \ No newline at end of file diff --git a/src/parser/operations/operations.h b/src/parser/operations/operations.h new file mode 100644 index 0000000..1a3b16b --- /dev/null +++ b/src/parser/operations/operations.h @@ -0,0 +1,15 @@ +#ifndef OPERATIONS_H +#define OPERATIONS_H +#include "../parser.h" +#include "../../lexer/token.h" // for Token + +typedef struct { + TokenType operation; + DArray to_operate_on; // ParsedValue[] +} ParsedOperation; + +ParsedValue *parse_operations(char*file,DArray *tokens, size_t * index, ParsedValue * first_parsed_value); + +void free_operation(void *ptr); + +#endif // OPERATIONS_H \ No newline at end of file diff --git a/src/parser/parser.c b/src/parser/parser.c index 8c676c4..43c7689 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -6,6 +6,7 @@ #include "assignable/call/call.h" #include "assignable/identifier/identifier.h" #include "declaration/declaration.h" +#include "operations/operations.h" #include "dowrap/dowrap.h" #include "if/if.h" #include "literals/literals.h" @@ -19,7 +20,7 @@ const char *ValueTypeNames[] = { "string", "assign", "identifier", "number", "if statement", "access", - "call", "declaration", "null", "boolean", "do wrap"}; + "call", "declaration", "null", "boolean", "do wrap", "operations"}; void error_if_finished(char *file, DArray *tokens, size_t *index) { if ((*index) >= tokens->size) { @@ -48,8 +49,8 @@ size_t skip_newlines_and_indents(DArray *tokens, size_t *index) { return count; } -ParsedValue *parse_token(char *file, DArray *tokens, size_t *index, - bool inline_flag) { +ParsedValue *parse_token_full(char *file, DArray *tokens, size_t *index, + bool inline_flag, bool process_operations) { Token *token = darray_get(tokens, *index); ParsedValue *output = NULL; @@ -134,6 +135,12 @@ ParsedValue *parse_token(char *file, DArray *tokens, size_t *index, case TOKEN_DOT: output = parse_access(file, tokens, index, output); break; + SWITCH_OPERATIONS + if (process_operations) { + output = parse_operations(file, tokens, index, output); + break; + } + /* fall through */ default: passed = true; } @@ -142,6 +149,11 @@ ParsedValue *parse_token(char *file, DArray *tokens, size_t *index, return output; } +ParsedValue *parse_token(char *file, DArray *tokens, size_t *index, + bool inline_flag) { + return parse_token_full(file, tokens, index, inline_flag, true); +} + void parser(char *file, DArray *parsed, DArray *tokens, bool inline_flag) { size_t index = 0; bool expecting_new_line = false; @@ -151,8 +163,8 @@ void parser(char *file, DArray *parsed, DArray *tokens, bool inline_flag) { if (parsed_code) { if (expecting_new_line) { Token *token = darray_get(tokens, old_index); - fprintf(stderr, "%s:%zu:%zu error: syntax error\n", file, token->line, - token->column); + fprintf(stderr, "%s:%zu:%zu error: expected a new line\n", file, + token->line, token->column); exit(EXIT_FAILURE); } expecting_new_line = true; @@ -190,6 +202,9 @@ void free_parsed(void *ptr) { case AST_IF: free_parsed_if(parsed); break; + case AST_OPERATION: + free_operation(parsed); + break; case AST_DOWRAP: free_dowrap(parsed); break; diff --git a/src/parser/parser.h b/src/parser/parser.h index 5806e3f..3cf6b66 100644 --- a/src/parser/parser.h +++ b/src/parser/parser.h @@ -5,6 +5,23 @@ #include #include +#define SWITCH_OPERATIONS case TOKEN_AND:\ +case TOKEN_OR:\ +case TOKEN_NOT_IN:\ +case TOKEN_LE:\ +case TOKEN_GE:\ +case TOKEN_LT:\ +case TOKEN_GT:\ +case TOKEN_NE:\ +case TOKEN_EQ:\ +case TOKEN_PLUS:\ +case TOKEN_MINUS:\ +case TOKEN_MODULO:\ +case TOKEN_STAR:\ +case TOKEN_FLOORDIV:\ +case TOKEN_SLASH:\ +case TOKEN_CARET: + typedef struct LinkedList LinkedList; typedef enum { @@ -18,7 +35,8 @@ typedef enum { AST_DECLARATION, AST_NULL, AST_BOOLEAN, - AST_DOWRAP + AST_DOWRAP, + AST_OPERATION } ValueType; extern const char* ValueTypeNames[]; @@ -30,8 +48,11 @@ typedef struct { void parser(char *file, DArray *parsed, DArray *tokens, bool inline_flag); -ParsedValue *parse_token(char *file, DArray *tokens, - size_t *index, bool inline_flag); +ParsedValue *parse_token_full(char *file, DArray *tokens, size_t *index, + bool inline_flag, bool process_operations); + +ParsedValue *parse_token(char *file, DArray *tokens, size_t *index, + bool inline_flag); void free_parsed(void *ptr); diff --git a/test.ar b/test.ar index 6ddc579..0be2816 100644 --- a/test.ar +++ b/test.ar @@ -40,9 +40,4 @@ else term.log("bruh") - -mm - - - - +mm = 10*10 - 10 \ No newline at end of file