remove individuals headers to avoid circular dependencies

This commit is contained in:
hugogogo
2026-05-03 11:29:01 +02:00
parent 42cfdf9734
commit cdc066c935
9 changed files with 213 additions and 194 deletions

View File

@@ -34,10 +34,7 @@ RESET = "\e[0m"
NAME = computorv1 NAME = computorv1
D_LIB = ./libft D_LIB = ./libft
D_HEADERS = ./headers D_HEADERS = ./headers
HEADERS = computorv1.h \ HEADERS = computorv1.h
errors.h \
lexer.h \
parser.h
D_SRCS = ./src D_SRCS = ./src
SRCS = computorv1.c \ SRCS = computorv1.c \
errors.c \ errors.c \

View File

@@ -1,10 +1,104 @@
/* computorv1.h */
#ifndef COMPUTORV1_H #ifndef COMPUTORV1_H
#define COMPUTORV1_H #define COMPUTORV1_H
#include "libft.h" #include "libft.h"
#include "lexer.h" #include <stdio.h> // tmp for printf, for float debug
#include "parser.h" #include <stdarg.h> // for va_list
#include "errors.h" #include <stdbool.h>
#include <stdio.h> // tmp for printf, for float debug
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* 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 #endif

View File

@@ -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

View File

@@ -1,43 +0,0 @@
#ifndef LEXER_H
#define LEXER_H
#include "libft.h"
#include "errors.h"
#include <stdbool.h>
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

View File

@@ -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

View File

@@ -1,6 +1,19 @@
/* computorv1.c */
#include "computorv1.h" #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 *read = s;
char *write = 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; int count = 0;
for (; *s != '\0'; s++) for (; *s != '\0'; s++)
@@ -36,10 +49,24 @@ int count_any_of(const char *s, const char *set)
return count; 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 main(int ac, char **av)
{ {
int i; int i;
int arg_len; size_t arg_len;
int terms_count_prediction; int terms_count_prediction;
char *input; char *input;
@@ -48,79 +75,61 @@ int main(int ac, char **av)
return 0; return 0;
} }
// tmp debug output // init
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++;
}
input = av[1]; input = av[1];
input_g_err = input;
remove_spaces(input); remove_spaces(input);
arg_len = ft_strlen(input) + 1; // +1 for last END token 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 // lexerize
token tokens[arg_len];
tokens_g_err = tokens;
token_fill_null(tokens, arg_len);
int tokens_count = lexerize(input, tokens); int tokens_count = lexerize(input, tokens);
if (tokens_count == 0) 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 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]; term terms[terms_count_prediction];
int term_count = parse(tokens, 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 // DEBUG
ft_putnbr(term_count); // debug ft_putstr("-> terms_count_prediction : ");
ft_putchar('\n'); // debug ft_putnbr(terms_count_prediction);
ft_putchar('\n');
// tmp debug output ft_putstr("-> terms_count : ");
ft_putchar('\n'); // debug ft_putnbr(term_count);
ft_putchar('\n');
ft_putchar('\n');
i = 0; i = 0;
while (terms[i].position != TERM_END) while (terms[i].position != TERM_END)
{ {
ft_printf("term %2i :\n", i); ft_printf("term %2i :\n", i);
// position // position
ft_printf(" position : "); ft_printf(" position : ");
if (terms[i].position == TERM_LEFT) if (terms[i].position == TERM_LEFT)
ft_printf("%s\n", "TERM_LEFT"); ft_printf("%s\n", "TERM_LEFT");
if (terms[i].position == TERM_RIGHT) if (terms[i].position == TERM_RIGHT)
ft_printf("%s\n", "TERM_RIGHT"); ft_printf("%s\n", "TERM_RIGHT");
// sign // sign
ft_printf(" sign : "); ft_printf(" sign : ");
if (terms[i].sign == TERM_PLUS) if (terms[i].sign == TERM_PLUS)
ft_printf("%s\n", "TERM_PLUS"); ft_printf("%s\n", "TERM_PLUS");
if (terms[i].sign == TERM_MINUS) if (terms[i].sign == TERM_MINUS)
ft_printf("%s\n", "TERM_MINUS"); ft_printf("%s\n", "TERM_MINUS");
// coefficient // coefficient
printf(" coefficient : %g\n", terms[i].coefficient); printf(" coefficient : %g\n", terms[i].coefficient);
// exponent // exponent
ft_printf(" exponent : %d\n", terms[i].exponent); ft_printf(" exponent : %d\n", terms[i].exponent);
i++; i++;
} }
ft_putchar('\n'); // debug ft_putchar('\n');
// END tmp debug output
return (0); return (0);
} }

View File

@@ -1,9 +1,8 @@
#include "errors.h" /* errors.c */
#include "libft.h"
#include "lexer.h"
#include <stdarg.h>
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; 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"; const char *msg = "error: error type is out of range";
// map error codes to messages // map error codes to messages
const char *error_messages[] = { const char *error_messages[ERROR_SENTINEL] = {
[ERROR_BASE] = "error: undefined error, details :", [ERROR_BASE] = "undefined error",
[ERROR_UNKNOWN_TOKEN] = "error: unknown token, details :", [ERROR_UNKNOWN_TOKEN] = "LEXER - unknown token",
[ERROR_NUMBER_TOO_BIG] = "error: number is too big, details :", [ERROR_NUMBER_TOO_BIG] = "LEXER - number is too big",
[ERROR_PARSING] = "error: too much terms to parse, details :", [ERROR_PARSING] = "PARSER - too much terms to parse",
[ERROR_TOKEN_POSITION] = "error: token position is not good in grammar, details :", [ERROR_TOKEN_POSITION] = "PARSER - token position is not good in grammar",
[ERROR_VAR_DIFF] = "error: expression must only contain one variable, details :", [ERROR_VAR_DIFF] = "PARSER - expression must only contain one variable",
// ⚠️ Add new error messages here when adding new error codes! [ERROR_TOKEN_COUNT] = "LEXER - token count error",
[ERROR_TERM_COUNT] = "PARSER - term count error",
}; };
// override msg if err is in the error_messages array // 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 // print context
ft_dprintf(STDERR_FILENO, "input : %s\n", input); if (input_g_err)
i = 0;
while (tokens[i].type != TOKEN_END)
{ {
ft_printf("token %2i - type : ", i); ft_dprintf(STDERR_FILENO, "\ninput : %s\n", input_g_err);
}
if (tokens[i].type == TOKEN_VARIABLE) if (tokens_g_err)
ft_printf("%20s", "TOKEN_VARIABLE"); {
else if (tokens[i].type == TOKEN_NUMBER_INT) ft_putchar('\n');
ft_printf("%20s", "TOKEN_NUMBER_INT"); i = 0;
else if (tokens[i].type == TOKEN_NUMBER_DOUBLE) while (tokens_g_err[i].type != TOKEN_END)
ft_printf("%20s", "TOKEN_NUMBER_DOUBLE"); {
else if (tokens[i].type == TOKEN_POWER) ft_printf("token %2i - type : ", i);
ft_printf("%20s", "TOKEN_POWER");
else if (tokens[i].type == TOKEN_SIGN_PLUS) if (tokens_g_err[i].type == TOKEN_VARIABLE)
ft_printf("%20s", "TOKEN_SIGN_PLUS"); ft_printf("%20s", "TOKEN_VARIABLE");
else if (tokens[i].type == TOKEN_SIGN_MINUS) else if (tokens_g_err[i].type == TOKEN_NUMBER_INT)
ft_printf("%20s", "TOKEN_SIGN_MINUS"); ft_printf("%20s", "TOKEN_NUMBER_INT");
else if (tokens[i].type == TOKEN_FACTOR_MULT) else if (tokens_g_err[i].type == TOKEN_NUMBER_DOUBLE)
ft_printf("%20s", "TOKEN_FACTOR_MULT"); ft_printf("%20s", "TOKEN_NUMBER_DOUBLE");
else if (tokens[i].type == TOKEN_FACTOR_DIV) else if (tokens_g_err[i].type == TOKEN_POWER)
ft_printf("%20s", "TOKEN_FACTOR_DIV"); ft_printf("%20s", "TOKEN_POWER");
else if (tokens[i].type == TOKEN_EQUAL) else if (tokens_g_err[i].type == TOKEN_SIGN_PLUS)
ft_printf("%20s", "TOKEN_EQUAL"); ft_printf("%20s", "TOKEN_SIGN_PLUS");
else if (tokens[i].type == TOKEN_END) else if (tokens_g_err[i].type == TOKEN_SIGN_MINUS)
ft_printf("%20s", "TOKEN_END"); ft_printf("%20s", "TOKEN_SIGN_MINUS");
else if (tokens_g_err[i].type == TOKEN_FACTOR_MULT)
ft_putstr(" - value : "); ft_printf("%20s", "TOKEN_FACTOR_MULT");
else if (tokens_g_err[i].type == TOKEN_FACTOR_DIV)
if (tokens[i].tag == TOKEN_NUMBER) ft_printf("%20s", "TOKEN_FACTOR_DIV");
{ else if (tokens_g_err[i].type == TOKEN_EQUAL)
printf("%g\n", tokens[i].value_double); ft_printf("%20s", "TOKEN_EQUAL");
} else if (tokens_g_err[i].type == TOKEN_END)
else ft_printf("%20s", "TOKEN_END");
{
ft_printf("%c\n", tokens[i].value_char); ft_putstr(" - value : ");
}
i++; 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 // 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 // print the formatted details
va_list args; va_list args;

View File

@@ -1,4 +1,6 @@
#include "lexer.h" /* lexer.c */
#include "computorv1.h"
// token is alphabet letter, like 'x' or 'y' // token is alphabet letter, like 'x' or 'y'
static bool token_is_variable(const char *input, int input_pos, int *token_size) static bool token_is_variable(const char *input, int input_pos, int *token_size)

View File

@@ -1,8 +1,6 @@
#include "parser.h" /* parser.c */
#include "libft.h"
#include "lexer.h" #include "computorv1.h"
#include "errors.h"
#include <stdbool.h>
/** /**
TOKEN_VARIABLE, // x, y, etc. TOKEN_VARIABLE, // x, y, etc.