handle superscript powers
This commit is contained in:
25
Makefile
25
Makefile
@@ -43,6 +43,7 @@ SRCS = main.c \
|
|||||||
parser.c \
|
parser.c \
|
||||||
reducer.c \
|
reducer.c \
|
||||||
errors.c \
|
errors.c \
|
||||||
|
printer.c \
|
||||||
print_enums.c
|
print_enums.c
|
||||||
|
|
||||||
# COMPILATION CONFIG :
|
# COMPILATION CONFIG :
|
||||||
@@ -97,16 +98,24 @@ $(NAME): $(OBJS)
|
|||||||
$(CC) $(OBJS) -o $@ $(LFLAGS)
|
$(CC) $(OBJS) -o $@ $(LFLAGS)
|
||||||
|
|
||||||
run: $(NAME)
|
run: $(NAME)
|
||||||
@echo $(B_PURPLE)"\n---------------------------------------------\n1. run with flag '-d' as last \n"$(RESET)
|
|
||||||
./$(NAME) "3.4 * x^2 + 1 * x^1 - 2.0 * x^0 = 5.123 * x^1" -d
|
|
||||||
@echo $(B_PURPLE)"\n---------------------------------------------\n2. run without flag \n"$(RESET)
|
@echo $(B_PURPLE)"\n---------------------------------------------\n2. run without flag \n"$(RESET)
|
||||||
./$(NAME) "3 * x^2 + 5 * x^1 - 2 * x^0 = 5 * x^1"
|
-./$(NAME) "3 * x^2 + 5 * x^1 - 2 * x^0 = 5 * x^1"
|
||||||
|
@echo $(B_PURPLE)"\n---------------------------------------------\n1. run with flag '-d' as last \n"$(RESET)
|
||||||
|
-./$(NAME) "3.4 * x^2 + 1 * x^1 - 2.0 * x^0 = 5 * x^1" -d
|
||||||
@echo $(B_PURPLE)"\n---------------------------------------------\n3. run with flag '-d' as first \n"$(RESET)
|
@echo $(B_PURPLE)"\n---------------------------------------------\n3. run with flag '-d' as first \n"$(RESET)
|
||||||
./$(NAME) -d "3*x^2 + 2*x = 0"
|
-./$(NAME) -d "3 * x^2 + 2 * x^2 = 5 * x^1"
|
||||||
@echo $(B_PURPLE)"\n---------------------------------------------\n4. run with wrong flag '-e' \n"$(RESET)
|
@echo $(B_PURPLE)"\n---------------------------------------------\n4. run with wrong flag '-e' SHOULD FAIL \n"$(RESET)
|
||||||
-./$(NAME) -d -e "3*x^2 + 2*x -7x^4 = x^4"
|
-./$(NAME) -d -e "3 * x^2 + 2 * x - 7 * x^4 = 1 * x^4"
|
||||||
@echo $(B_PURPLE)"\n---------------------------------------------\n5. run \n"$(RESET)
|
@echo $(B_PURPLE)"\n---------------------------------------------\n3. run with free form \n"$(RESET)
|
||||||
./$(NAME) -d "3*x^2 + 2*x -7x^3 = x^3"
|
-./$(NAME) -d "3*x^2 + 2x = 0"
|
||||||
|
@echo $(B_PURPLE)"\n---------------------------------------------\n1. run with float coefficient \n"$(RESET)
|
||||||
|
-./$(NAME) -d "3.4 * x^2 + 1 * x^1 - 2.0 * x^0 = 5.123 * x^1"
|
||||||
|
@echo $(B_PURPLE)"\n---------------------------------------------\n1. run with float exponent SHOULD FAILS \n"$(RESET)
|
||||||
|
-./$(NAME) -d "3.4 * x^2 + 1 * x^1 - 2.0 * x^0 = 5 * x^1.2"
|
||||||
|
@echo $(B_PURPLE)"\n---------------------------------------------\n4. run with power 4 \n"$(RESET)
|
||||||
|
-./$(NAME) -d "3x^2 + 2x -7x^4 = x^4"
|
||||||
|
@echo $(B_PURPLE)"\n---------------------------------------------\n5. run with utf8 \n"$(RESET)
|
||||||
|
-./$(NAME) -d "3x² + 2x -7x³ = x³"
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(RM_OBJS)
|
$(RM_OBJS)
|
||||||
|
|||||||
@@ -10,9 +10,6 @@
|
|||||||
#include <errno.h> // for errno
|
#include <errno.h> // for errno
|
||||||
#include <string.h> // for strerror
|
#include <string.h> // for strerror
|
||||||
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <termios.h> // For tcflush() and TCIFLUSH
|
|
||||||
|
|
||||||
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
* MAIN.C
|
* MAIN.C
|
||||||
*/
|
*/
|
||||||
@@ -36,16 +33,17 @@ void launch_computorv1(char *input);
|
|||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
TOKEN_VARIABLE, // x, y, etc.
|
TOKEN_VARIABLE, // x, y, etc.
|
||||||
TOKEN_NUMBER_INT, // int
|
TOKEN_NUMBER_INT, // int
|
||||||
TOKEN_NUMBER_DOUBLE, // double
|
TOKEN_NUMBER_DOUBLE, // double
|
||||||
TOKEN_POWER, // ^ or **
|
TOKEN_NUMBER_INT_SUPER, // superscript int, like '²'
|
||||||
TOKEN_SIGN_PLUS, // +
|
TOKEN_POWER, // ^ or **
|
||||||
TOKEN_SIGN_MINUS, // -
|
TOKEN_SIGN_PLUS, // +
|
||||||
TOKEN_FACTOR_MULT, // *
|
TOKEN_SIGN_MINUS, // -
|
||||||
TOKEN_FACTOR_DIV, // / or :
|
TOKEN_FACTOR_MULT, // *
|
||||||
TOKEN_EQUAL, // =
|
TOKEN_FACTOR_DIV, // / or :
|
||||||
TOKEN_END // null (end of input)
|
TOKEN_EQUAL, // =
|
||||||
|
TOKEN_END // null (end of input)
|
||||||
} e_token_type;
|
} e_token_type;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
@@ -120,6 +118,12 @@ const char *token_tag_to_str(e_token_tag tag);
|
|||||||
const char *term_position_to_str(e_term_position pos);
|
const char *term_position_to_str(e_term_position pos);
|
||||||
const char *term_sign_to_str(e_term_sign sign);
|
const char *term_sign_to_str(e_term_sign sign);
|
||||||
|
|
||||||
|
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* UTILS/PRINTER.C
|
||||||
|
*/
|
||||||
|
|
||||||
|
void print_debug(const char *description, ...);
|
||||||
|
|
||||||
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
* GLOBALS
|
* GLOBALS
|
||||||
*/
|
*/
|
||||||
|
|||||||
2
libft
2
libft
Submodule libft updated: b64ede50af...f93c635234
@@ -1,4 +1,4 @@
|
|||||||
/* computorv1.c */
|
/* launcher.c */
|
||||||
|
|
||||||
#include "computorv1.h"
|
#include "computorv1.h"
|
||||||
|
|
||||||
@@ -110,8 +110,8 @@ void launch_computorv1(char *input)
|
|||||||
remove_spaces(input);
|
remove_spaces(input);
|
||||||
|
|
||||||
// lexerize
|
// lexerize
|
||||||
arg_len = ft_strlen(input) + 1; // +1 for last END token
|
arg_len = ft_strlen(input) + 1; // +1 for last END token
|
||||||
// ft_printf("-> tokens[%i]\n", arg_len); // debug
|
print_debug("\n-> tokens[%i]\n", arg_len); // debug
|
||||||
s_token tokens[arg_len];
|
s_token tokens[arg_len];
|
||||||
tokens_g_err = tokens;
|
tokens_g_err = tokens;
|
||||||
tokens_fill_null(tokens, arg_len);
|
tokens_fill_null(tokens, arg_len);
|
||||||
@@ -123,7 +123,7 @@ void launch_computorv1(char *input)
|
|||||||
|
|
||||||
// parse
|
// 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_printf("-> terms[%i]\n", terms_count_prediction); // debug
|
print_debug("-> terms[%i]\n\n", terms_count_prediction); // debug
|
||||||
s_term terms[terms_count_prediction];
|
s_term terms[terms_count_prediction];
|
||||||
terms_g_err = terms;
|
terms_g_err = terms;
|
||||||
terms_fill_null(terms, terms_count_prediction);
|
terms_fill_null(terms, terms_count_prediction);
|
||||||
@@ -141,6 +141,8 @@ void launch_computorv1(char *input)
|
|||||||
polynom_fill_null(polynom, max_exponent);
|
polynom_fill_null(polynom, max_exponent);
|
||||||
reduce(terms, polynom);
|
reduce(terms, polynom);
|
||||||
|
|
||||||
|
// solve
|
||||||
|
|
||||||
// debug
|
// debug
|
||||||
print_state();
|
print_state();
|
||||||
}
|
}
|
||||||
|
|||||||
42
src/lexer.c
42
src/lexer.c
@@ -100,6 +100,42 @@ static bool token_is_number_double(const char *input, int input_pos, int *token_
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// token is superscript int (e.g., ², ³, ⁴, ⁵, etc.)
|
||||||
|
static bool token_is_number_int_super(const char *input, int input_pos, int *token_size)
|
||||||
|
{
|
||||||
|
int digit_size = 0;
|
||||||
|
int number_size = 0;
|
||||||
|
int max_number_size = 16; // same max size as regular integers
|
||||||
|
|
||||||
|
// check if first character is superscript
|
||||||
|
if (!ft_isdigit_superscript(input + input_pos, NULL))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// iterate to find full superscript number
|
||||||
|
while (number_size < max_number_size)
|
||||||
|
{
|
||||||
|
if (ft_isdigit_superscript(input + input_pos + number_size, &digit_size))
|
||||||
|
{
|
||||||
|
// Increment by the length of the UTF-8 character (2 or 3 bytes)
|
||||||
|
number_size += digit_size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (number_size == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*token_size = number_size;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// token is '^' or "**"
|
// token is '^' or "**"
|
||||||
static bool token_is_power(const char *input, int input_pos, int *token_size)
|
static bool token_is_power(const char *input, int input_pos, int *token_size)
|
||||||
{
|
{
|
||||||
@@ -214,6 +250,12 @@ int lexerize(const char *input, s_token *tokens)
|
|||||||
tokens[tokens_count].tag = TOKEN_NUMBER;
|
tokens[tokens_count].tag = TOKEN_NUMBER;
|
||||||
tokens[tokens_count].value_double = ft_atof(&input[input_pos]);
|
tokens[tokens_count].value_double = ft_atof(&input[input_pos]);
|
||||||
}
|
}
|
||||||
|
else if (token_is_number_int_super(input, input_pos, &token_size))
|
||||||
|
{
|
||||||
|
tokens[tokens_count].type = TOKEN_NUMBER_INT_SUPER;
|
||||||
|
tokens[tokens_count].tag = TOKEN_NUMBER;
|
||||||
|
tokens[tokens_count].value_int = ft_atoi_superscript(&input[input_pos]);
|
||||||
|
}
|
||||||
else if (token_is_power(input, input_pos, &token_size))
|
else if (token_is_power(input, input_pos, &token_size))
|
||||||
{
|
{
|
||||||
tokens[tokens_count].type = TOKEN_POWER;
|
tokens[tokens_count].type = TOKEN_POWER;
|
||||||
|
|||||||
23
src/parser.c
23
src/parser.c
@@ -54,7 +54,7 @@ static double get_double_value(s_token token)
|
|||||||
return token.value_int;
|
return token.value_int;
|
||||||
}
|
}
|
||||||
|
|
||||||
static double get_coefficient_absolute(s_token *tokens, int i, int *token_count)
|
static double get_coefficient(s_token *tokens, int i, int *token_count)
|
||||||
{
|
{
|
||||||
double coefficient;
|
double coefficient;
|
||||||
|
|
||||||
@@ -140,13 +140,18 @@ static int get_exponent(s_token *tokens, int i, int *token_count)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// then get power sign '^'
|
// then get power sign '^' or directly superscript power like '²'
|
||||||
if (tokens[i].type == TOKEN_POWER)
|
if (tokens[i].type == TOKEN_POWER)
|
||||||
{
|
{
|
||||||
i++;
|
i++;
|
||||||
*token_count += 1;
|
*token_count += 1;
|
||||||
}
|
}
|
||||||
// else if (tokens[i].type == TOKEN_NUMBER_INT_POWER){}
|
else if (tokens[i].type == TOKEN_NUMBER_INT_SUPER)
|
||||||
|
{
|
||||||
|
*token_count += 1;
|
||||||
|
// return exponent directly
|
||||||
|
return tokens[i].value_int;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// if token is 'x' not followed by '^' -> it's an exponent 1
|
// if token is 'x' not followed by '^' -> it's an exponent 1
|
||||||
@@ -201,13 +206,15 @@ int parse(s_token *tokens, s_term *terms, int terms_count_max)
|
|||||||
|
|
||||||
check_variables(tokens);
|
check_variables(tokens);
|
||||||
|
|
||||||
|
print_debug("PARSER STEPS :\n"); // debug
|
||||||
|
|
||||||
terms_count = 0;
|
terms_count = 0;
|
||||||
token_count = 0;
|
token_count = 0;
|
||||||
i = 0;
|
i = 0;
|
||||||
term_position = TERM_LEFT;
|
term_position = TERM_LEFT;
|
||||||
while (tokens[i].type != TOKEN_END && terms_count < terms_count_max)
|
while (tokens[i].type != TOKEN_END && terms_count < terms_count_max)
|
||||||
{
|
{
|
||||||
// ft_printf("- token[%i]\n", i); // debug
|
print_debug("- token[%i]\n", i); // debug
|
||||||
|
|
||||||
// equal
|
// equal
|
||||||
if (tokens[i].type == TOKEN_EQUAL)
|
if (tokens[i].type == TOKEN_EQUAL)
|
||||||
@@ -229,19 +236,19 @@ int parse(s_token *tokens, s_term *terms, int terms_count_max)
|
|||||||
sign = -1;
|
sign = -1;
|
||||||
}
|
}
|
||||||
i += token_count;
|
i += token_count;
|
||||||
// ft_printf("term[%i] get_sign: (%i)[%s], token_count: [%d]\n", terms_count, ret_sign, term_sign_to_str(ret_sign), token_count); // debug
|
print_debug("term[%i] get_sign: (%i)[%s], token_count: [%d]\n", terms_count, ret_sign, term_sign_to_str(ret_sign), token_count); // debug
|
||||||
|
|
||||||
// coefficient
|
// coefficient
|
||||||
double ret_coefficient = get_coefficient_absolute(tokens, i, &token_count);
|
double ret_coefficient = get_coefficient(tokens, i, &token_count);
|
||||||
terms[terms_count].coefficient = ret_coefficient * sign;
|
terms[terms_count].coefficient = ret_coefficient * sign;
|
||||||
i += token_count;
|
i += token_count;
|
||||||
// printf("term[%i] get_coefficient: [%g], token_count: [%d]\n", terms_count, ret_coefficient, token_count); // debug
|
print_debug("term[%i] get_coefficient: [%g], token_count: [%d]\n", terms_count, ret_coefficient, token_count); // debug
|
||||||
|
|
||||||
// exponent
|
// exponent
|
||||||
int ret_exponent = get_exponent(tokens, i, &token_count);
|
int ret_exponent = get_exponent(tokens, i, &token_count);
|
||||||
terms[terms_count].exponent = ret_exponent;
|
terms[terms_count].exponent = ret_exponent;
|
||||||
i += token_count;
|
i += token_count;
|
||||||
// ft_printf("term[%i] get_exponent: [%i], token_count: [%d]\n", terms_count, ret_exponent, token_count); // debug
|
print_debug("term[%i] get_exponent: [%i], token_count: [%d]\n", terms_count, ret_exponent, token_count); // debug
|
||||||
|
|
||||||
terms_count++;
|
terms_count++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,25 +18,27 @@ static void print_context_tokens()
|
|||||||
ft_dprintf(STDERR_FILENO, "token[%2i] - type : ", i);
|
ft_dprintf(STDERR_FILENO, "token[%2i] - type : ", i);
|
||||||
|
|
||||||
if (tokens_g_err[i].type == TOKEN_VARIABLE)
|
if (tokens_g_err[i].type == TOKEN_VARIABLE)
|
||||||
ft_dprintf(STDERR_FILENO, "%20s", "TOKEN_VARIABLE");
|
ft_dprintf(STDERR_FILENO, "%22s", "TOKEN_VARIABLE");
|
||||||
else if (tokens_g_err[i].type == TOKEN_NUMBER_INT)
|
else if (tokens_g_err[i].type == TOKEN_NUMBER_INT)
|
||||||
ft_dprintf(STDERR_FILENO, "%20s", "TOKEN_NUMBER_INT");
|
ft_dprintf(STDERR_FILENO, "%22s", "TOKEN_NUMBER_INT");
|
||||||
|
else if (tokens_g_err[i].type == TOKEN_NUMBER_INT_SUPER)
|
||||||
|
ft_dprintf(STDERR_FILENO, "%22s", "TOKEN_NUMBER_INT_SUPER");
|
||||||
else if (tokens_g_err[i].type == TOKEN_NUMBER_DOUBLE)
|
else if (tokens_g_err[i].type == TOKEN_NUMBER_DOUBLE)
|
||||||
ft_dprintf(STDERR_FILENO, "%20s", "TOKEN_NUMBER_DOUBLE");
|
ft_dprintf(STDERR_FILENO, "%22s", "TOKEN_NUMBER_DOUBLE");
|
||||||
else if (tokens_g_err[i].type == TOKEN_POWER)
|
else if (tokens_g_err[i].type == TOKEN_POWER)
|
||||||
ft_dprintf(STDERR_FILENO, "%20s", "TOKEN_POWER");
|
ft_dprintf(STDERR_FILENO, "%22s", "TOKEN_POWER");
|
||||||
else if (tokens_g_err[i].type == TOKEN_SIGN_PLUS)
|
else if (tokens_g_err[i].type == TOKEN_SIGN_PLUS)
|
||||||
ft_dprintf(STDERR_FILENO, "%20s", "TOKEN_SIGN_PLUS");
|
ft_dprintf(STDERR_FILENO, "%22s", "TOKEN_SIGN_PLUS");
|
||||||
else if (tokens_g_err[i].type == TOKEN_SIGN_MINUS)
|
else if (tokens_g_err[i].type == TOKEN_SIGN_MINUS)
|
||||||
ft_dprintf(STDERR_FILENO, "%20s", "TOKEN_SIGN_MINUS");
|
ft_dprintf(STDERR_FILENO, "%22s", "TOKEN_SIGN_MINUS");
|
||||||
else if (tokens_g_err[i].type == TOKEN_FACTOR_MULT)
|
else if (tokens_g_err[i].type == TOKEN_FACTOR_MULT)
|
||||||
ft_dprintf(STDERR_FILENO, "%20s", "TOKEN_FACTOR_MULT");
|
ft_dprintf(STDERR_FILENO, "%22s", "TOKEN_FACTOR_MULT");
|
||||||
else if (tokens_g_err[i].type == TOKEN_FACTOR_DIV)
|
else if (tokens_g_err[i].type == TOKEN_FACTOR_DIV)
|
||||||
ft_dprintf(STDERR_FILENO, "%20s", "TOKEN_FACTOR_DIV");
|
ft_dprintf(STDERR_FILENO, "%22s", "TOKEN_FACTOR_DIV");
|
||||||
else if (tokens_g_err[i].type == TOKEN_EQUAL)
|
else if (tokens_g_err[i].type == TOKEN_EQUAL)
|
||||||
ft_dprintf(STDERR_FILENO, "%20s", "TOKEN_EQUAL");
|
ft_dprintf(STDERR_FILENO, "%22s", "TOKEN_EQUAL");
|
||||||
else if (tokens_g_err[i].type == TOKEN_END)
|
else if (tokens_g_err[i].type == TOKEN_END)
|
||||||
ft_dprintf(STDERR_FILENO, "%20s", "TOKEN_END");
|
ft_dprintf(STDERR_FILENO, "%22s", "TOKEN_END");
|
||||||
|
|
||||||
ft_putstr(" - value : ");
|
ft_putstr(" - value : ");
|
||||||
|
|
||||||
@@ -44,6 +46,10 @@ static void print_context_tokens()
|
|||||||
{
|
{
|
||||||
ft_dprintf(STDERR_FILENO, "%i\n", tokens_g_err[i].value_int);
|
ft_dprintf(STDERR_FILENO, "%i\n", tokens_g_err[i].value_int);
|
||||||
}
|
}
|
||||||
|
else if (tokens_g_err[i].type == TOKEN_NUMBER_INT_SUPER)
|
||||||
|
{
|
||||||
|
ft_dprintf(STDERR_FILENO, "%i\n", tokens_g_err[i].value_int);
|
||||||
|
}
|
||||||
else if (tokens_g_err[i].type == TOKEN_NUMBER_DOUBLE)
|
else if (tokens_g_err[i].type == TOKEN_NUMBER_DOUBLE)
|
||||||
{
|
{
|
||||||
dprintf(STDERR_FILENO, "%g\n", tokens_g_err[i].value_double);
|
dprintf(STDERR_FILENO, "%g\n", tokens_g_err[i].value_double);
|
||||||
|
|||||||
16
src/utils/printer.c
Normal file
16
src/utils/printer.c
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/* printer.c */
|
||||||
|
|
||||||
|
#include "computorv1.h"
|
||||||
|
|
||||||
|
void print_debug(const char *description, ...)
|
||||||
|
{
|
||||||
|
if (!flag_debug_mode)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// print the formatted description
|
||||||
|
va_list args;
|
||||||
|
va_start(args, description);
|
||||||
|
// ft_vdprintf(STDOUT_FILENO, description, args);
|
||||||
|
vdprintf(STDOUT_FILENO, description, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user