fix number tokens and limits

This commit is contained in:
hugogogo
2026-05-26 12:48:36 +02:00
parent f1a6a8e586
commit c99bdfc63a
8 changed files with 577 additions and 481 deletions

3
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"window.title": "${rootName} — ${activeEditorShort}"
}

169
README.md
View File

@@ -1,19 +1,28 @@
# 42_EXT_05_computorv1 # 42_EXT_05_computorv1
## todo
- [ ] arg limit ?
- [x] change order is_number_int and is_number_double
- [x] remove double limit in lexer
- [ ] check why number stored in int or double
- [x] get rid of lib math (check in libft)
- [x] use ft_abs() instead of abs() -> actually abs() is in stdlib
- [x] handling sign '-' : "+ -2"
- [x] max exponent len :
## ressources ## ressources
- project intra : https://projects.intra.42.fr/projects/42cursus-computorv1 - project intra : https://projects.intra.42.fr/projects/42cursus-computorv1
- project luke : https://github.com/LuckyLaszlo/computorv1 - project luke : https://github.com/LuckyLaszlo/computorv1
## install ## install
this project uses submodules (maybe recursively), so either : this project uses submodules (maybe recursively), so either :
- `git clone --recurse-submodules <repo-url>` - `git clone --recurse-submodules <repo-url>`
- or, after cloning : `git submodule update --init --recursive` - or, after cloning : `git submodule update --init --recursive`
--- ---
# sqrt implementation # sqrt implementation
@@ -24,7 +33,7 @@ finding the square root of x
the dichotomie method, or binary search, consist on dividing the range of research by 2 each time, and choosing the right one for the next iteration. the dichotomie method, or binary search, consist on dividing the range of research by 2 each time, and choosing the right one for the next iteration.
Ex : Ex :
``` ```
solution solution
@@ -57,12 +66,11 @@ Ex :
--------|---------------------- --> solution --------|---------------------- --> solution
``` ```
## NewtonRaphson method ## NewtonRaphson method
it's like a self-correcting binary search, we get rid of the step "choose range", we use the formulae `x/v` to find the next range, with `x` being the number we are trying to get the sqaure root from, and `v` the value found at the previous step. it's like a self-correcting binary search, we get rid of the step "choose range", we use the formulae `x/v` to find the next range, with `x` being the number we are trying to get the sqaure root from, and `v` the value found at the previous step.
Ex : Ex :
``` ```
solution solution
@@ -91,87 +99,72 @@ Ex :
``` ```
### mathematical proof that each range is automatically in the right range : ### mathematical proof that each range is automatically in the right range :
- if the value was higher than the answer, then new value is below old value, and vice versa
- how ? :
- define `x`, solution `s = √x`, and value `v = (old_value + x / old_value) / 2`
- supposition : if `v < s` , then `new_v > v`, else `new_v < v` :
- demonstration :
1. if `v < s` :
v < s
<=> v < √x
<=> v² < x (that's actually how we know that v < s)
<=> v²/v < x/v
<=> v < x/v
-> and is s < x/v ? :
v < s
<=> v < √x
<=> v² < x (as previously)
<=> v² < x²/x
<=> v² * x < x²
<=> (v * √x)² < x²
<=> v * √x < x
<=> v * √x < v * x/v
<=> √x < x/v
-> so indeed : if v < √x, then v < √x < x/v == v < s < x/v
-> conclusion, the new range < v , x/v > contains the solution
2. the same demonstration works for `v > s`
### here is a more intuitive demonstration, with x = 20 : - if the value was higher than the answer, then new value is below old value, and vice versa
- how ? :
- define `x`, solution `s = √x`, and value `v = (old_value + x / old_value) / 2`
- supposition : if `v < s` , then `new_v > v`, else `new_v < v` :
- demonstration :
1. if `v < s` :
v < s
<=> v < √x
<=> v² < x (that's actually how we know that v < s)
<=> v²/v < x/v
<=> v < x/v
-> and is s < x/v ? :
v < s
<=> v < √x
<=> v² < x (as previously)
<=> v² < x²/x
<=> v² _ x < x²
<=> (v _ √x)² < x²
<=> v _ √x < x
<=> v _ √x < v \* x/v
<=> √x < x/v
-> so indeed : if v < √x, then v < √x < x/v == v < s < x/v
-> conclusion, the new range < v , x/v > contains the solution
2. the same demonstration works for `v > s`
### here is a more intuitive demonstration, with x = 20 :
1. **show that if `v² > x` (== `v > s`) then `v > s > x/v`, and if `v² < x` (== `v < s`) then `v < s < x/v` :** 1. **show that if `v² > x` (== `v > s`) then `v > s > x/v`, and if `v² < x` (== `v < s`) then `v < s < x/v` :**
1.1. **for value too high `v > s` :** 1.1. **for value too high `v > s` :**
1.1.1 **why `v > x/v` :** 1.1.1 **why `v > x/v` :** - let's take initial value v = 5 : - is 5² the solution ? 5² == 25 -> so no, 5 is not the sqrt, it's too high
- let's take initial value v = 5 : ` v v²
- is 5² the solution ? 5² == 25 -> so no, 5 is not the sqrt, it's too high 0 (5) 10 15 20 25
``` v : |----|----|----|----|----|
v v² x/v: |---|---|---|---|---| <----- squiz it, so the previous 5 portions fit the x = 20 size
0 (5) 10 15 20 25 0 (4) 8 12 16 20
v : |----|----|----|----|----| x/v x` - the value of the new portion is 4, and we can visually see that it's lower than the previous portion 5 - so : `v > x/v`
x/v: |---|---|---|---|---| <----- squiz it, so the previous 5 portions fit the x = 20 size 1.1.2 **why `s > x/v` :** - let's take the value v = 5 : - we already showed that it's too high, now we will see that x/v == 20/5 is too low :
0 (4) 8 12 16 20 ` v
x/v x 0 (5) 10 15 20 25
``` v : |----|----|----|----|----|
- the value of the new portion is 4, and we can visually see that it's lower than the previous portion 5 x/v: |---|---|---|---|---| <----- squizz
- so : `v > x/v` 0 *1 *2 *3 *4 *5 -> number of portions
1.1.2 **why `s > x/v` :** 01234 -> portion size
- let's take the value v = 5 : (x/v)²: |---|---|---|---|
- we already showed that it's too high, now we will see that x/v == 20/5 is too low : 0 4 8 12 16` - the portion size is smaller than the number of portions, so it's too small to be the sqrt, indeed we visually see that this portion size `x/v` is a root of a smaller number : `(x/v)² == 16` - so : `s > x/v`
``` 1.1.3. **conclusion :** - v > s - and v > x/v (<- this proof is not essential) - and s > x/v (<- we actually only need this proof) - so `v > s > x/v`
v
0 (5) 10 15 20 25 1.2. **for value too high `v < s` :**
v : |----|----|----|----|----| - this is the same demonstration but in other direction, let's just summarize it :
x/v: |---|---|---|---|---| <----- squizz - let's take initial value v = 4 :
0 *1 *2 *3 *4 *5 -> number of portions ```
01234 -> portion size v
(x/v)²: |---|---|---|---| 0 (4) 8 12 16
0 4 8 12 16 (1) v : |---|---|---|---|
``` (2) x/v: |----|----|----|----| -----> stretch
- the portion size is smaller than the number of portions, so it's too small to be the sqrt, indeed we visually see that this portion size `x/v` is a root of a smaller number : `(x/v)² == 16` (3) 0 (5) 10 15 20
- so : `s > x/v` x/v x
1.1.3. **conclusion :** (4) 0 *1 *2 *3 *4 -> number of portions
- v > s 012345 -> portion size
- and v > x/v (<- this proof is not essential) (5) (x/v)²: |----|----|----|----|----|
- and s > x/v (<- we actually only need this proof) 0 5 10 15 20 25
- so `v > s > x/v` ```
- (1) : 4 is not the sqrt of x == 20, it's too smalle : (4² == 16) < 20
1.2. **for value too high `v < s` :** - (2) : stretch it, so the previous 4 portions fit the x = 20 size
- this is the same demonstration but in other direction, let's just summarize it : - (3) : the new portion x/v == 5, is more than v == 4, so `v < x/v`
- let's take initial value v = 4 : - (4) : portion size is bigger than number of portions, so it's too big to be the root
``` - (5) : indeed, we see that the portion² == (x/v)² is bigger than x, so √x < x/v == `s < x/v`
v v² - so `v < s < x/v`
0 (4) 8 12 16
(1) v : |---|---|---|---|
(2) x/v: |----|----|----|----| -----> stretch
(3) 0 (5) 10 15 20
x/v x
(4) 0 *1 *2 *3 *4 -> number of portions
012345 -> portion size
(5) (x/v)²: |----|----|----|----|----|
0 5 10 15 20 25
```
- (1) : 4 is not the sqrt of x == 20, it's too smalle : (4² == 16) < 20
- (2) : stretch it, so the previous 4 portions fit the x = 20 size
- (3) : the new portion x/v == 5, is more than v == 4, so `v < x/v`
- (4) : portion size is bigger than number of portions, so it's too big to be the root
- (5) : indeed, we see that the portion² == (x/v)² is bigger than x, so √x < x/v == `s < x/v`
- so `v < s < x/v`

View File

@@ -91,7 +91,7 @@ void launch_computorv1(char *input)
int max_exponent; int max_exponent;
int nbr_of_exponents; int nbr_of_exponents;
int degree; int degree;
size_t arg_len; size_t token_len;
size_t terms_count_prediction; size_t terms_count_prediction;
// init // init
@@ -99,9 +99,9 @@ void launch_computorv1(char *input)
remove_spaces(input); remove_spaces(input);
// lexerize // lexerize
arg_len = ft_strlen(input) + 1; // +1 for last END token token_len = ft_strlen(input) + 1; // +1 for last END token
print_debug("\n-> tokens[%i]\n", arg_len); print_debug("\n-> tokens[%i]\n", token_len);
s_token tokens[arg_len]; s_token tokens[token_len];
tokens_g_err = tokens; tokens_g_err = tokens;
ft_bzero(tokens, sizeof(tokens)); ft_bzero(tokens, sizeof(tokens));
lexerize(input, tokens); lexerize(input, tokens);

View File

@@ -2,316 +2,344 @@
#include "computorv1.h" #include "computorv1.h"
/**
* INT CHECKS
*/
static bool is_number_bigger_than_int_max(const char *input, int size)
{
const char *int_max_str = "2147483647";
int int_max_len = ft_strlen(int_max_str);
if (size < int_max_len)
return false;
if (size > int_max_len)
return true;
return ft_strncmp(input, int_max_str, int_max_len) > 0;
}
static bool is_number_smaller_than_int_min(const char *input, int size)
{
const char *int_min_str = "-2147483648";
int int_min_len = ft_strlen(int_min_str);
if (size < int_min_len)
return false;
if (size > int_min_len)
return true;
return ft_strncmp(input, int_min_str, int_min_len) < 0;
}
static bool is_number_out_of_int_range(const char *input, int size)
{
if (input[0] == '-')
{
return is_number_smaller_than_int_min(input, size);
}
else
{
return is_number_bigger_than_int_max(input, size);
}
}
/**
* TOKEN CHECKS
*/
// 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)
{ {
if (ft_isalpha(input[input_pos])) if (ft_isalpha(input[input_pos]))
{ {
*token_size = 1; *token_size = 1;
return true; return true;
} }
return false; return false;
} }
// token is int "123" // token is int "123"
static bool token_is_number_int(const char *input, int input_pos, int *token_size) static bool token_is_number_int(const char *input, int input_pos, int *token_size)
{ {
int number_size; int number_size;
int max_number_size;
if (!ft_isdigit(input[input_pos])) number_size = 0;
{
return false;
}
number_size = 1; // if (input[input_pos + number_size] == '-')
max_number_size = 16; // max size for int // number_size++;
while (number_size <= max_number_size)
{ while (input[input_pos + number_size] != '\0')
if (ft_isdigit(input[input_pos + number_size])) {
{ if (ft_isdigit(input[input_pos + number_size]))
number_size++; {
} number_size++;
else if (input[input_pos + number_size] == '.') }
{ else
if (ft_isdigit(input[input_pos + number_size + 1])) break;
{ }
// number is double if (number_size == 0)
return false; {
} return false;
else }
break; if (is_number_out_of_int_range(&input[input_pos], number_size))
} {
else return false;
break; }
} *token_size = number_size;
if (number_size > max_number_size) return true;
{
stop_errors(&input[input_pos]);
}
*token_size = number_size;
return true;
} }
// token is double "123.456" // token is double "123.456" or token < MIN_INT or token > MAX_INT
static bool token_is_number_double(const char *input, int input_pos, int *token_size) static bool token_is_number_double(const char *input, int input_pos, int *token_size)
{ {
int number_size; int number_size;
int max_number_size; bool has_dot;
bool has_dot;
if (!ft_isdigit(input[input_pos])) has_dot = false;
{ number_size = 0;
return false;
}
has_dot = false; // if (input[input_pos + number_size] == '-')
number_size = 1; // number_size++;
max_number_size = 24; // max char needed to represent double : 1 sign + 1 point + 17 fractinoal part + 5 exponent
while (number_size <= max_number_size) while (input[input_pos + number_size] != '\0')
{ {
if (ft_isdigit(input[input_pos + number_size])) if (ft_isdigit(input[input_pos + number_size]))
{ {
number_size++; number_size++;
} }
else if (input[input_pos + number_size] == '.') else if (input[input_pos + number_size] == '.' && !has_dot)
{ {
if (has_dot) has_dot = true;
{ number_size++;
// number is not a valid token, it has 2 dots }
return false; else
} break;
if (!ft_isdigit(input[input_pos + number_size + 1])) }
{ if (is_number_out_of_int_range(&input[input_pos], number_size))
// number is not valid token, it has a dot with no number after the dot {
return false; *token_size = number_size;
} return true;
has_dot = true; }
number_size++; if (!has_dot)
} {
else return false;
break; }
}
if (number_size > max_number_size) *token_size = number_size;
{ return true;
stop_errors(&input[input_pos]);
}
*token_size = number_size;
return true;
} }
// token is superscript int (e.g., ¹, ², ³, ⁴, ⁵, etc.) // token is superscript int e.g. ¹, ², ³, ⁴, ⁵, ⁶⁶⁶
static bool token_is_number_int_super(const char *input, int input_pos, int *token_size) static bool token_is_number_int_super(const char *input, int input_pos, int *token_size)
{ {
int digit_size = 0; int digit_size = 0;
int number_size = 0; int number_size = 0;
int max_number_size = 16; // same max size as regular integers int superscript_len = 0;
int superscript_len_max = 3; // max length of superscript int we want to support
// check if first character is superscript // iterate to find full superscript number
if (!ft_isdigit_superscript(input + input_pos, NULL)) while (input[input_pos + number_size] != '\0')
{ {
return false; if (ft_isdigit_superscript(&input[input_pos + number_size], &digit_size))
} {
superscript_len++;
// 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;
}
if (superscript_len > superscript_len_max)
{
stop_errors("superscript int is too long (max supported length is %d), got : %s\n", superscript_len_max, &input[input_pos]);
}
// iterate to find full superscript number *token_size = number_size;
while (number_size < max_number_size) return true;
{
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)
{ {
if (input[input_pos] == '^') if (input[input_pos] == '^')
{ {
*token_size = 1; *token_size = 1;
return true; return true;
} }
if (ft_memcmp(&input[input_pos], "**", 2) == 0) if (ft_memcmp(&input[input_pos], "**", 2) == 0)
{ {
*token_size = 2; *token_size = 2;
return true; return true;
} }
return false; return false;
} }
// token is '+' // token is '+'
static bool token_is_sign_plus(const char *input, int input_pos, int *token_size) static bool token_is_sign_plus(const char *input, int input_pos, int *token_size)
{ {
if (input[input_pos] == '+') if (input[input_pos] == '+')
{ {
*token_size = 1; *token_size = 1;
return true; return true;
} }
return false; return false;
} }
// token is '-' // token is '-'
static bool token_is_sign_minus(const char *input, int input_pos, int *token_size) static bool token_is_sign_minus(const char *input, int input_pos, int *token_size)
{ {
if (input[input_pos] == '-') if (input[input_pos] == '-')
{ {
*token_size = 1; *token_size = 1;
return true; return true;
} }
return false; return false;
} }
// token is '*' // token is '*'
static bool token_is_factor_multiplication(const char *input, int input_pos, int *token_size) static bool token_is_factor_multiplication(const char *input, int input_pos, int *token_size)
{ {
if (input[input_pos] == '*') if (input[input_pos] == '*')
{ {
*token_size = 1; *token_size = 1;
return true; return true;
} }
return false; return false;
} }
// token is '/' or ':' // token is '/' or ':'
static bool token_is_factor_division(const char *input, int input_pos, int *token_size) static bool token_is_factor_division(const char *input, int input_pos, int *token_size)
{ {
if (input[input_pos] == '/') if (input[input_pos] == '/')
{ {
*token_size = 1; *token_size = 1;
return true; return true;
} }
if (input[input_pos] == ':') if (input[input_pos] == ':')
{ {
*token_size = 1; *token_size = 1;
return true; return true;
} }
return false; return false;
} }
// token is '=' // token is '='
static bool token_is_equal(const char *input, int input_pos, int *token_size) static bool token_is_equal(const char *input, int input_pos, int *token_size)
{ {
if (input[input_pos] == '=') if (input[input_pos] == '=')
{ {
*token_size = 1; *token_size = 1;
return true; return true;
} }
return false; return false;
} }
/** /**
* LEXER * LEXER
*/ */
void lexerize(const char *input, s_token *tokens) void lexerize(const char *input, s_token *tokens)
{ {
int tokens_count; int tokens_count;
int input_pos; int input_pos;
int token_size; int token_size;
bool has_equal; bool has_equal;
has_equal = false; has_equal = false;
tokens_count = 0; tokens_count = 0;
input_pos = 0; input_pos = 0;
while (input[input_pos]) while (input[input_pos])
{ {
token_size = 0; token_size = 0;
if (input[input_pos] == '\0') if (input[input_pos] == '\0')
{ {
break; break;
} }
if (token_is_variable(input, input_pos, &token_size)) if (token_is_variable(input, input_pos, &token_size))
{ {
tokens[tokens_count].type = TOKEN_VARIABLE; tokens[tokens_count].type = TOKEN_VARIABLE;
tokens[tokens_count].tag = TOKEN_NO_TAG; tokens[tokens_count].tag = TOKEN_NO_TAG;
tokens[tokens_count].value_char = 'x'; tokens[tokens_count].value_char = 'x';
} }
else if (token_is_number_int(input, input_pos, &token_size)) else if (token_is_number_double(input, input_pos, &token_size))
{ {
tokens[tokens_count].type = TOKEN_NUMBER_INT; tokens[tokens_count].type = TOKEN_NUMBER_DOUBLE;
tokens[tokens_count].tag = TOKEN_NUMBER; tokens[tokens_count].tag = TOKEN_NUMBER;
tokens[tokens_count].value_int = ft_atoi(&input[input_pos]); tokens[tokens_count].value_double = ft_atof(&input[input_pos]);
} }
else if (token_is_number_double(input, input_pos, &token_size)) else if (token_is_number_int(input, input_pos, &token_size))
{ {
tokens[tokens_count].type = TOKEN_NUMBER_DOUBLE; tokens[tokens_count].type = TOKEN_NUMBER_INT;
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_int = ft_atoi(&input[input_pos]);
} }
else if (token_is_number_int_super(input, input_pos, &token_size)) else if (token_is_number_int_super(input, input_pos, &token_size))
{ {
tokens[tokens_count].type = TOKEN_NUMBER_INT_SUPER; tokens[tokens_count].type = TOKEN_NUMBER_INT_SUPER;
tokens[tokens_count].tag = TOKEN_NUMBER; tokens[tokens_count].tag = TOKEN_NUMBER;
tokens[tokens_count].value_int = ft_atoi_superscript(&input[input_pos]); 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;
tokens[tokens_count].tag = TOKEN_NO_TAG; tokens[tokens_count].tag = TOKEN_NO_TAG;
tokens[tokens_count].value_char = '^'; tokens[tokens_count].value_char = '^';
} }
else if (token_is_sign_plus(input, input_pos, &token_size)) else if (token_is_sign_plus(input, input_pos, &token_size))
{ {
tokens[tokens_count].type = TOKEN_SIGN_PLUS; tokens[tokens_count].type = TOKEN_SIGN_PLUS;
tokens[tokens_count].tag = TOKEN_SIGN; tokens[tokens_count].tag = TOKEN_SIGN;
tokens[tokens_count].value_char = input[input_pos]; tokens[tokens_count].value_char = input[input_pos];
} }
else if (token_is_sign_minus(input, input_pos, &token_size)) else if (token_is_sign_minus(input, input_pos, &token_size))
{ {
tokens[tokens_count].type = TOKEN_SIGN_MINUS; tokens[tokens_count].type = TOKEN_SIGN_MINUS;
tokens[tokens_count].tag = TOKEN_SIGN; tokens[tokens_count].tag = TOKEN_SIGN;
tokens[tokens_count].value_char = input[input_pos]; tokens[tokens_count].value_char = input[input_pos];
} }
else if (token_is_factor_multiplication(input, input_pos, &token_size)) else if (token_is_factor_multiplication(input, input_pos, &token_size))
{ {
tokens[tokens_count].type = TOKEN_FACTOR_MULT; tokens[tokens_count].type = TOKEN_FACTOR_MULT;
tokens[tokens_count].tag = TOKEN_FACTOR; tokens[tokens_count].tag = TOKEN_FACTOR;
tokens[tokens_count].value_char = input[input_pos]; tokens[tokens_count].value_char = input[input_pos];
} }
else if (token_is_factor_division(input, input_pos, &token_size)) else if (token_is_factor_division(input, input_pos, &token_size))
{ {
tokens[tokens_count].type = TOKEN_FACTOR_DIV; tokens[tokens_count].type = TOKEN_FACTOR_DIV;
tokens[tokens_count].tag = TOKEN_FACTOR; tokens[tokens_count].tag = TOKEN_FACTOR;
tokens[tokens_count].value_char = input[input_pos]; tokens[tokens_count].value_char = input[input_pos];
} }
else if (token_is_equal(input, input_pos, &token_size)) else if (token_is_equal(input, input_pos, &token_size))
{ {
has_equal = true; has_equal = true;
tokens[tokens_count].type = TOKEN_EQUAL; tokens[tokens_count].type = TOKEN_EQUAL;
tokens[tokens_count].tag = TOKEN_NO_TAG; tokens[tokens_count].tag = TOKEN_NO_TAG;
tokens[tokens_count].value_char = '='; tokens[tokens_count].value_char = '=';
} }
else else
{ {
stop_errors("input[input_pos] is not any token: %s\n", &input[input_pos]); stop_errors("input[input_pos] is not any token: %s\n", &input[input_pos]);
} }
tokens_count++; tokens_count++;
if (token_size == 0) if (token_size == 0)
{ {
stop_errors("token_size is 0 : %s\n", &input[input_pos]); stop_errors("token_size is 0 : %s\n", &input[input_pos]);
} }
input_pos += token_size; input_pos += token_size;
} }
if (!has_equal) if (!has_equal)
stop_errors("the input polynomial does not contains an equal sign, it's an expression not an equation.\n"); stop_errors("the input polynomial does not contains an equal sign, it's an expression not an equation.\n");
tokens[tokens_count].type = TOKEN_END; tokens[tokens_count].type = TOKEN_END;
tokens[tokens_count].tag = TOKEN_NO_TAG; tokens[tokens_count].tag = TOKEN_NO_TAG;
tokens[tokens_count].value_char = '\0'; tokens[tokens_count].value_char = '\0';
} }

View File

@@ -21,167 +21,161 @@ s_solution *solution_g_err;
static void print_usage() static void print_usage()
{ {
ft_printf("USAGE :\n\n"); ft_printf("USAGE :\n\n");
ft_printf("| ./computorv1 [flags] [polynom]\n"); ft_printf("| ./computorv1 [flags] [polynom]\n");
ft_printf("| ./computorv1 [polynom] [flags]\n"); ft_printf("| ./computorv1 [polynom] [flags]\n");
ft_printf("| ./computorv1 [flags] -> interactiv mode\n\n"); ft_printf("| ./computorv1 [flags] -> interactiv mode\n\n");
ft_printf("[flags] :\n"); ft_printf("[flags] :\n");
ft_printf("-d : print debug\n"); ft_printf("-d : print debug\n");
ft_printf("-l : interactive loop\n"); ft_printf("-l : interactive loop\n");
ft_printf("-b : beautify output\n"); ft_printf("-b : beautify output\n");
ft_putchar('\n'); ft_putchar('\n');
} }
// trim spaces and quotes and newlines // trim spaces and quotes and newlines
static void clean_copy_input(char *input, char *line) static void clean_copy_input(char *input, char *line)
{ {
size_t i; size_t i;
size_t j; size_t j;
size_t len; size_t len;
size_t len_trim_end; size_t len_trim_end;
size_t len_trim_start; size_t len_trim_start;
len = ft_strlen(line); len = ft_strlen(line);
// get len minus : ' | " | \n | <space> // get len minus : ' | " | \n | <space>
i = len; i = len;
while (i > 0) while (i > 0)
{ {
if (ft_strchr("\"\'\n", line[i])) if (ft_strchr("\"\'\n", line[i]))
i--; i--;
if (ft_isspace(line[i])) if (ft_isspace(line[i]))
i--; i--;
break; break;
} }
len_trim_end = i; len_trim_end = i;
// get len of leading chars : ' | " | <space> | \n // get len of leading chars : ' | " | <space> | \n
i = 0; i = 0;
while (i < len_trim_end) while (i < len_trim_end)
{ {
if (ft_strchr("\"\'\n", line[i])) if (ft_strchr("\"\'\n", line[i]))
i++; i++;
if (ft_isspace(line[i])) if (ft_isspace(line[i]))
i++; i++;
break; break;
} }
len_trim_start = i; len_trim_start = i;
// copy into input // copy into input
i = len_trim_start; i = len_trim_start;
j = 0; j = 0;
while (i <= len_trim_end) while (i <= len_trim_end)
{ {
input[j] = line[i]; input[j] = line[i];
j++; j++;
i++; i++;
} }
input[j] = '\0'; input[j] = '\0';
} }
static void launch_stdin() static void launch_stdin()
{ {
char *line; char *line;
size_t len; size_t len;
line = NULL; line = NULL;
len = 0; len = 0;
// get input // get input
getline(&line, &len, stdin); getline(&line, &len, stdin);
// prepare input // prepare input
char input[len]; char input[len];
clean_copy_input(input, line); clean_copy_input(input, line);
// launch input // launch input
launch_computorv1(input); launch_computorv1(input);
// FREE LINE ! // FREE LINE !
free(line); free(line);
} }
static void launch_stdin_loop() // static void launch_stdin_loop()
{ // {
while (1) // while (1)
{ // {
// for the moment it does not work since errors exit // // for the moment it does not work since errors exit
launch_stdin(); // launch_stdin();
} // }
} // }
int main(int ac, char **av) int main(int ac, char **av)
{ {
int i; int i;
char *input; char *input;
e_program_mode program_mode; e_program_mode program_mode;
// init flags // init flags
flag_debug_mode = false; flag_debug_mode = false;
flag_loop_mode = false; flag_loop_mode = false;
flag_beautify_mode = false; flag_beautify_mode = false;
// check arguments // check arguments
program_mode = MODE_ARGV; program_mode = MODE_ARGV;
if (ac == 1)
{
program_mode = MODE_STDIN;
}
else if (ac > 1)
{
// get flags
input = NULL;
i = 1;
while (i < ac)
{
if ((ft_strcmp(av[i], "-d") == 0))
{
// flag -d : debug
flag_debug_mode = true;
}
else if ((ft_strcmp(av[i], "-l") == 0))
{
// flag -l : interactiv loop
flag_loop_mode = true;
program_mode = MODE_LOOP;
}
else if ((ft_strcmp(av[i], "-b") == 0))
{
// flag -b : beautify output
flag_beautify_mode = true;
}
else if (ft_strlen(av[i]) == 2 && av[i][0] == '-')
{
// unknown flag
print_usage();
stop_errors("unknwon flag '%s'", av[i]);
}
else
{
input = av[i];
}
i++;
}
// if input was not set, it means interactiv mode
if (input == NULL)
{
program_mode = MODE_STDIN;
}
}
// launch calculator // get flags
if (program_mode == MODE_ARGV) input = NULL;
{ i = 1;
launch_computorv1(input); while (i < ac)
} {
else if (program_mode == MODE_STDIN) if ((ft_strcmp(av[i], "-d") == 0))
{ {
launch_stdin(); // flag -d : debug
} flag_debug_mode = true;
else if (program_mode == MODE_LOOP) }
{ else if ((ft_strcmp(av[i], "-l") == 0))
launch_stdin_loop(); {
} // flag -l : interactiv loop
flag_loop_mode = true;
program_mode = MODE_LOOP;
}
else if ((ft_strcmp(av[i], "-b") == 0))
{
// flag -b : beautify output
flag_beautify_mode = true;
}
else if (ft_strlen(av[i]) == 2 && av[i][0] == '-')
{
// unknown flag
print_usage();
stop_errors("unknwon flag '%s'", av[i]);
}
else
{
input = av[i];
}
i++;
}
// if input was not set, it means interactiv mode
if (input == NULL)
{
program_mode = MODE_STDIN;
}
return (0); // launch calculator
if (program_mode == MODE_ARGV)
{
launch_computorv1(input);
}
else if (program_mode == MODE_STDIN)
{
launch_stdin();
}
// else if (program_mode == MODE_LOOP)
// {
// launch_stdin_loop();
// }
return (0);
} }

View File

@@ -16,30 +16,44 @@
static e_term_sign get_sign(s_token *tokens, int i, int *token_count) static e_term_sign get_sign(s_token *tokens, int i, int *token_count)
{ {
*token_count = 0; *token_count = 0;
int j;
e_term_sign ret_sign;
// default to '+'
ret_sign = TERM_PLUS;
// sign
if (tokens[i].tag == TOKEN_SIGN) if (tokens[i].tag == TOKEN_SIGN)
{ {
*token_count = 1; // we cna have two signs in a row, like "3 - -2" or "3 - +2"
j = 0;
while (j < 2)
{
if (tokens[i + j].tag != TOKEN_SIGN)
break;
if (tokens[i + j].type == TOKEN_SIGN_MINUS)
ret_sign = (ret_sign == TERM_PLUS) ? TERM_MINUS : TERM_PLUS;
*token_count += 1;
j++;
}
} }
else if (i == 0) else if (i == 0)
{ {
// if most left term, the sign can be ommited for a '+' sign in front of a number or variable // if most left term, the sign can be ommited for a '+' sign in front of a number or variable
*token_count = 0; *token_count = 0;
return TERM_PLUS; ret_sign = TERM_PLUS;
} }
else if (tokens[i - 1].type == TOKEN_EQUAL) else if (tokens[i - 1].type == TOKEN_EQUAL)
{ {
// if first token after 'equal', the sign can be ommited for a '+' sign in front of a number or variable // if first token after 'equal', the sign can be ommited for a '+' sign in front of a number or variable
*token_count = 0; *token_count = 0;
return TERM_PLUS; ret_sign = TERM_PLUS;
} }
else else
{ {
stop_errors("at begining of term, we should have a token 'sign', not '%s' (token[%i])", token_type_to_str(tokens[i].type), i); stop_errors("at begining of term, we should have a token 'sign', not '%s' (token[%i])", token_type_to_str(tokens[i].type), i);
} }
return tokens[i].type == TOKEN_SIGN_PLUS ? TERM_PLUS : TERM_MINUS; return ret_sign;
} }
static double get_double_value(s_token token) static double get_double_value(s_token token)

View File

@@ -65,7 +65,7 @@ int gcd_int(int a, int b)
b = a % b; b = a % b;
a = tmp; a = tmp;
} }
return abs(a); return ft_abs(a);
} }
// returns the gcd, and modify arguments with new reduced values // returns the gcd, and modify arguments with new reduced values

File diff suppressed because one or more lines are too long