From cdc066c935e9d7fcf6493aee2dbedef64bd1269f Mon Sep 17 00:00:00 2001 From: hugogogo Date: Sun, 3 May 2026 11:29:01 +0200 Subject: [PATCH] remove individuals headers to avoid circular dependencies --- Makefile | 5 +- headers/computorv1.h | 102 +++++++++++++++++++++++++++++++++++++-- headers/errors.h | 17 ------- headers/lexer.h | 43 ----------------- headers/parser.h | 28 ----------- src/computorv1.c | 89 ++++++++++++++++++---------------- src/errors.c | 111 +++++++++++++++++++++++-------------------- src/lexer.c | 4 +- src/parser.c | 8 ++-- 9 files changed, 213 insertions(+), 194 deletions(-) delete mode 100644 headers/errors.h delete mode 100644 headers/lexer.h delete mode 100644 headers/parser.h diff --git a/Makefile b/Makefile index c89ba8d..4911849 100644 --- a/Makefile +++ b/Makefile @@ -34,10 +34,7 @@ RESET = "\e[0m" NAME = computorv1 D_LIB = ./libft D_HEADERS = ./headers -HEADERS = computorv1.h \ - errors.h \ - lexer.h \ - parser.h +HEADERS = computorv1.h D_SRCS = ./src SRCS = computorv1.c \ errors.c \ diff --git a/headers/computorv1.h b/headers/computorv1.h index ab29d7a..a913d3f 100644 --- a/headers/computorv1.h +++ b/headers/computorv1.h @@ -1,10 +1,104 @@ +/* computorv1.h */ + #ifndef COMPUTORV1_H #define COMPUTORV1_H #include "libft.h" -#include "lexer.h" -#include "parser.h" -#include "errors.h" -#include // tmp for printf, for float debug +#include // tmp for printf, for float debug +#include // for va_list +#include + +/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * LEXER.C + */ + +typedef enum +{ + TOKEN_VARIABLE, // x, y, etc. + TOKEN_NUMBER_INT, // int + TOKEN_NUMBER_DOUBLE, // double + TOKEN_POWER, // ^ or ** + TOKEN_SIGN_PLUS, // + + TOKEN_SIGN_MINUS, // - + TOKEN_FACTOR_MULT, // * + TOKEN_FACTOR_DIV, // / or : + TOKEN_EQUAL, // = + TOKEN_END // null (end of input) +} token_type; + +typedef enum +{ + TOKEN_NO_TAG, + TOKEN_NUMBER, + TOKEN_SIGN, + TOKEN_FACTOR, +} token_tag; + +typedef struct +{ + token_type type; + token_tag tag; + union + { + char value_char; + double value_double; + }; +} token; + +int lexerize(const char *input, token *tokens); + +/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * PARSER.C + */ + +typedef enum +{ + TERM_LEFT, // a in "a = b" + TERM_RIGHT, // b in "a = b" + TERM_END, // last term +} term_position; + +typedef enum +{ + TERM_PLUS, // + + TERM_MINUS, // - + TERM_NULL, // null -> for the last term +} term_sign; + +typedef struct +{ + term_position position; + term_sign sign; + double coefficient; + double exponent; +} term; + +int parse(token *tokens, term *terms, int terms_count_max); + +/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * ERRORS.C + */ + +typedef enum +{ + ERROR_BASE = 1, // start at 1 to avoid exit(0) for errors + ERROR_TOKEN_COUNT, + ERROR_UNKNOWN_TOKEN, + ERROR_NUMBER_TOO_BIG, + ERROR_PARSING, + ERROR_TERM_COUNT, + ERROR_TOKEN_POSITION, + ERROR_VAR_DIFF, + ERROR_SENTINEL, // last token not used, only for enum count +} program_error; + +int stop_errors(program_error err, const char *format, ...); + +/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * GLOBALS + */ + +extern char *input_g_err; +extern token *tokens_g_err; #endif \ No newline at end of file diff --git a/headers/errors.h b/headers/errors.h deleted file mode 100644 index f06dbc6..0000000 --- a/headers/errors.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef ERRORS_H -#define ERRORS_H - -typedef enum -{ - ERROR_BASE = 1, // Start at 1 to avoid exit(0) for errors - ERROR_UNKNOWN_TOKEN, - ERROR_NUMBER_TOO_BIG, - ERROR_PARSING, - ERROR_TOKEN_POSITION, - ERROR_VAR_DIFF, - ERROR_SENTINEL, -} program_error; - -int stop_errors(program_error err, token *tokens, char *input, const char *format, ...); - -#endif \ No newline at end of file diff --git a/headers/lexer.h b/headers/lexer.h deleted file mode 100644 index 381489a..0000000 --- a/headers/lexer.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef LEXER_H -#define LEXER_H - -#include "libft.h" -#include "errors.h" -#include - -typedef enum -{ - TOKEN_VARIABLE, // x, y, etc. - TOKEN_NUMBER_INT, // int - TOKEN_NUMBER_DOUBLE, // double - TOKEN_POWER, // ^ or ** - TOKEN_SIGN_PLUS, // + - TOKEN_SIGN_MINUS, // - - TOKEN_FACTOR_MULT, // * - TOKEN_FACTOR_DIV, // / or : - TOKEN_EQUAL, // = - TOKEN_END // null (end of input) -} token_type; - -typedef enum -{ - TOKEN_NO_TAG, - TOKEN_NUMBER, - TOKEN_SIGN, - TOKEN_FACTOR, -} token_tag; - -typedef struct -{ - token_type type; - token_tag tag; - union - { - char value_char; - double value_double; - }; -} token; - -int lexerize(const char *input, token *tokens); - -#endif \ No newline at end of file diff --git a/headers/parser.h b/headers/parser.h deleted file mode 100644 index e96fcac..0000000 --- a/headers/parser.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PARSER_H -#define PARSER_H - -typedef enum -{ - TERM_LEFT, // a in "a = b" - TERM_RIGHT, // b in "a = b" - TERM_END, // last term -} term_position; - -typedef enum -{ - TERM_PLUS, // + - TERM_MINUS, // - - TERM_NULL, // null -> for the last term -} term_sign; - -typedef struct -{ - term_position position; - term_sign sign; - double coefficient; - double exponent; -} term; - -int parse(token *tokens, term *terms, int terms_count_max); - -#endif \ No newline at end of file diff --git a/src/computorv1.c b/src/computorv1.c index 78e2c70..ad9ea4f 100644 --- a/src/computorv1.c +++ b/src/computorv1.c @@ -1,6 +1,19 @@ +/* computorv1.c */ + #include "computorv1.h" -void remove_spaces(char *s) +/** + * GLOBALS + */ + +char *input_g_err; +token *tokens_g_err; + +/** + * PROGRAM + */ + +static void remove_spaces(char *s) { char *read = s; char *write = s; @@ -23,7 +36,7 @@ void remove_spaces(char *s) } } -int count_any_of(const char *s, const char *set) +static int count_any_of(const char *s, const char *set) { int count = 0; for (; *s != '\0'; s++) @@ -36,10 +49,24 @@ int count_any_of(const char *s, const char *set) return count; } +static void token_fill_null(token *tokens, size_t arg_len) +{ + size_t i; + + i = 0; + while (i < arg_len) + { + tokens[i].type = TOKEN_END; + tokens[i].tag = TOKEN_NO_TAG; + tokens[i].value_char = '\0'; + i++; + } +} + int main(int ac, char **av) { int i; - int arg_len; + size_t arg_len; int terms_count_prediction; char *input; @@ -48,79 +75,61 @@ int main(int ac, char **av) return 0; } - // tmp debug output - ft_putstr("-> received args :\n"); // debug - i = 0; - while (i < ac) - { - ft_putstr(" "); - ft_putnbr(i); - ft_putstr(" : "); - ft_putstr(av[i]); - ft_putchar('\n'); - i++; - } - + // init input = av[1]; + input_g_err = input; remove_spaces(input); arg_len = ft_strlen(input) + 1; // +1 for last END token - token tokens[arg_len]; - // by security, make the last token as END (even though the real END token will likely be lower) - tokens[arg_len - 1].type = TOKEN_END; - tokens[arg_len - 1].tag = TOKEN_NO_TAG; - tokens[arg_len - 1].value_char = '\0'; // lexerize + token tokens[arg_len]; + tokens_g_err = tokens; + token_fill_null(tokens, arg_len); int tokens_count = lexerize(input, tokens); if (tokens_count == 0) { - stop_errors(ERROR_BASE, tokens, input, "test error"); + stop_errors(ERROR_TOKEN_COUNT, "lexer returned 0 token"); } + // parse terms_count_prediction = count_any_of(input, "-+=") + 2; // +1 for first term that can have no leading '+', +1 for last term == NULL - - ft_putstr("-> terms_count_prediction : "); // debug - ft_putnbr(terms_count_prediction); // debug - ft_putchar('\n'); // debug - term terms[terms_count_prediction]; int term_count = parse(tokens, terms, terms_count_prediction); + { + stop_errors(ERROR_TERM_COUNT, "parser returned 0 term"); + } - ft_putstr("-> terms_count : "); // debug - ft_putnbr(term_count); // debug - ft_putchar('\n'); // debug - - // tmp debug output - ft_putchar('\n'); // debug + // DEBUG + ft_putstr("-> terms_count_prediction : "); + ft_putnbr(terms_count_prediction); + ft_putchar('\n'); + ft_putstr("-> terms_count : "); + ft_putnbr(term_count); + ft_putchar('\n'); + ft_putchar('\n'); i = 0; while (terms[i].position != TERM_END) { ft_printf("term %2i :\n", i); - // position ft_printf(" position : "); if (terms[i].position == TERM_LEFT) ft_printf("%s\n", "TERM_LEFT"); if (terms[i].position == TERM_RIGHT) ft_printf("%s\n", "TERM_RIGHT"); - // sign ft_printf(" sign : "); if (terms[i].sign == TERM_PLUS) ft_printf("%s\n", "TERM_PLUS"); if (terms[i].sign == TERM_MINUS) ft_printf("%s\n", "TERM_MINUS"); - // coefficient printf(" coefficient : %g\n", terms[i].coefficient); - // exponent ft_printf(" exponent : %d\n", terms[i].exponent); - i++; } - ft_putchar('\n'); // debug - // END tmp debug output + ft_putchar('\n'); return (0); } diff --git a/src/errors.c b/src/errors.c index 13f610c..bb757e9 100644 --- a/src/errors.c +++ b/src/errors.c @@ -1,9 +1,8 @@ -#include "errors.h" -#include "libft.h" -#include "lexer.h" -#include +/* errors.c */ -int stop_errors(program_error err, token *tokens, char *input, const char *details, ...) +#include "computorv1.h" + +int stop_errors(program_error err, const char *details, ...) { int i; @@ -11,14 +10,15 @@ int stop_errors(program_error err, token *tokens, char *input, const char *detai const char *msg = "error: error type is out of range"; // map error codes to messages - const char *error_messages[] = { - [ERROR_BASE] = "error: undefined error, details :", - [ERROR_UNKNOWN_TOKEN] = "error: unknown token, details :", - [ERROR_NUMBER_TOO_BIG] = "error: number is too big, details :", - [ERROR_PARSING] = "error: too much terms to parse, details :", - [ERROR_TOKEN_POSITION] = "error: token position is not good in grammar, details :", - [ERROR_VAR_DIFF] = "error: expression must only contain one variable, details :", - // ⚠️ Add new error messages here when adding new error codes! + const char *error_messages[ERROR_SENTINEL] = { + [ERROR_BASE] = "undefined error", + [ERROR_UNKNOWN_TOKEN] = "LEXER - unknown token", + [ERROR_NUMBER_TOO_BIG] = "LEXER - number is too big", + [ERROR_PARSING] = "PARSER - too much terms to parse", + [ERROR_TOKEN_POSITION] = "PARSER - token position is not good in grammar", + [ERROR_VAR_DIFF] = "PARSER - expression must only contain one variable", + [ERROR_TOKEN_COUNT] = "LEXER - token count error", + [ERROR_TERM_COUNT] = "PARSER - term count error", }; // override msg if err is in the error_messages array @@ -28,49 +28,56 @@ int stop_errors(program_error err, token *tokens, char *input, const char *detai } // print context - ft_dprintf(STDERR_FILENO, "input : %s\n", input); - i = 0; - while (tokens[i].type != TOKEN_END) + if (input_g_err) { - ft_printf("token %2i - type : ", i); - - if (tokens[i].type == TOKEN_VARIABLE) - ft_printf("%20s", "TOKEN_VARIABLE"); - else if (tokens[i].type == TOKEN_NUMBER_INT) - ft_printf("%20s", "TOKEN_NUMBER_INT"); - else if (tokens[i].type == TOKEN_NUMBER_DOUBLE) - ft_printf("%20s", "TOKEN_NUMBER_DOUBLE"); - else if (tokens[i].type == TOKEN_POWER) - ft_printf("%20s", "TOKEN_POWER"); - else if (tokens[i].type == TOKEN_SIGN_PLUS) - ft_printf("%20s", "TOKEN_SIGN_PLUS"); - else if (tokens[i].type == TOKEN_SIGN_MINUS) - ft_printf("%20s", "TOKEN_SIGN_MINUS"); - else if (tokens[i].type == TOKEN_FACTOR_MULT) - ft_printf("%20s", "TOKEN_FACTOR_MULT"); - else if (tokens[i].type == TOKEN_FACTOR_DIV) - ft_printf("%20s", "TOKEN_FACTOR_DIV"); - else if (tokens[i].type == TOKEN_EQUAL) - ft_printf("%20s", "TOKEN_EQUAL"); - else if (tokens[i].type == TOKEN_END) - ft_printf("%20s", "TOKEN_END"); - - ft_putstr(" - value : "); - - if (tokens[i].tag == TOKEN_NUMBER) - { - printf("%g\n", tokens[i].value_double); - } - else - { - ft_printf("%c\n", tokens[i].value_char); - } - i++; + ft_dprintf(STDERR_FILENO, "\ninput : %s\n", input_g_err); + } + if (tokens_g_err) + { + ft_putchar('\n'); + i = 0; + while (tokens_g_err[i].type != TOKEN_END) + { + ft_printf("token %2i - type : ", i); + + if (tokens_g_err[i].type == TOKEN_VARIABLE) + ft_printf("%20s", "TOKEN_VARIABLE"); + else if (tokens_g_err[i].type == TOKEN_NUMBER_INT) + ft_printf("%20s", "TOKEN_NUMBER_INT"); + else if (tokens_g_err[i].type == TOKEN_NUMBER_DOUBLE) + ft_printf("%20s", "TOKEN_NUMBER_DOUBLE"); + else if (tokens_g_err[i].type == TOKEN_POWER) + ft_printf("%20s", "TOKEN_POWER"); + else if (tokens_g_err[i].type == TOKEN_SIGN_PLUS) + ft_printf("%20s", "TOKEN_SIGN_PLUS"); + else if (tokens_g_err[i].type == TOKEN_SIGN_MINUS) + ft_printf("%20s", "TOKEN_SIGN_MINUS"); + else if (tokens_g_err[i].type == TOKEN_FACTOR_MULT) + ft_printf("%20s", "TOKEN_FACTOR_MULT"); + else if (tokens_g_err[i].type == TOKEN_FACTOR_DIV) + ft_printf("%20s", "TOKEN_FACTOR_DIV"); + else if (tokens_g_err[i].type == TOKEN_EQUAL) + ft_printf("%20s", "TOKEN_EQUAL"); + else if (tokens_g_err[i].type == TOKEN_END) + ft_printf("%20s", "TOKEN_END"); + + ft_putstr(" - value : "); + + if (tokens_g_err[i].tag == TOKEN_NUMBER) + { + printf("%g\n", tokens_g_err[i].value_double); + } + else + { + ft_printf("%c\n", tokens_g_err[i].value_char); + } + i++; + } + ft_putchar('\n'); } - ft_putchar('\n'); // print the base message - ft_dprintf(STDERR_FILENO, "%s (%i) - ", msg, err); + ft_dprintf(STDERR_FILENO, "error: (%i) %s - details: ", err, msg); // print the formatted details va_list args; diff --git a/src/lexer.c b/src/lexer.c index 7940796..d98e88c 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -1,4 +1,6 @@ -#include "lexer.h" +/* lexer.c */ + +#include "computorv1.h" // token is alphabet letter, like 'x' or 'y' static bool token_is_variable(const char *input, int input_pos, int *token_size) diff --git a/src/parser.c b/src/parser.c index 0ff44dc..afb0618 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1,8 +1,6 @@ -#include "parser.h" -#include "libft.h" -#include "lexer.h" -#include "errors.h" -#include +/* parser.c */ + +#include "computorv1.h" /** TOKEN_VARIABLE, // x, y, etc.