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
## 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
- project intra : https://projects.intra.42.fr/projects/42cursus-computorv1
- project luke : https://github.com/LuckyLaszlo/computorv1
- project intra : https://projects.intra.42.fr/projects/42cursus-computorv1
- project luke : https://github.com/LuckyLaszlo/computorv1
## install
this project uses submodules (maybe recursively), so either :
this project uses submodules (maybe recursively), so either :
- `git clone --recurse-submodules <repo-url>`
- or, after cloning : `git submodule update --init --recursive`
---
# 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.
Ex :
Ex :
```
solution
@@ -57,12 +66,11 @@ Ex :
--------|---------------------- --> solution
```
## 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.
Ex :
Ex :
```
solution
@@ -91,87 +99,72 @@ Ex :
```
### 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.1. **for value too high `v > s` :**
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
```
v v²
0 (5) 10 15 20 25
v : |----|----|----|----|----|
x/v: |---|---|---|---|---| <----- squiz it, so the previous 5 portions fit the x = 20 size
0 (4) 8 12 16 20
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`
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 :
```
v
0 (5) 10 15 20 25
v : |----|----|----|----|----|
x/v: |---|---|---|---|---| <----- squizz
0 *1 *2 *3 *4 *5 -> number of portions
01234 -> portion size
(x/v)²: |---|---|---|---|
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`
1.2. **for value too high `v < s` :**
- this is the same demonstration but in other direction, let's just summarize it :
- let's take initial value v = 4 :
```
v 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`
1.1. **for value too high `v > s` :**
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
` v v²
0 (5) 10 15 20 25
v : |----|----|----|----|----|
x/v: |---|---|---|---|---| <----- squiz it, so the previous 5 portions fit the x = 20 size
0 (4) 8 12 16 20
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`
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 :
` v
0 (5) 10 15 20 25
v : |----|----|----|----|----|
x/v: |---|---|---|---|---| <----- squizz
0 *1 *2 *3 *4 *5 -> number of portions
01234 -> portion size
(x/v)²: |---|---|---|---|
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`
1.2. **for value too high `v < s` :**
- this is the same demonstration but in other direction, let's just summarize it :
- let's take initial value v = 4 :
```
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 nbr_of_exponents;
int degree;
size_t arg_len;
size_t token_len;
size_t terms_count_prediction;
// init
@@ -99,9 +99,9 @@ void launch_computorv1(char *input)
remove_spaces(input);
// lexerize
arg_len = ft_strlen(input) + 1; // +1 for last END token
print_debug("\n-> tokens[%i]\n", arg_len);
s_token tokens[arg_len];
token_len = ft_strlen(input) + 1; // +1 for last END token
print_debug("\n-> tokens[%i]\n", token_len);
s_token tokens[token_len];
tokens_g_err = tokens;
ft_bzero(tokens, sizeof(tokens));
lexerize(input, tokens);

View File

@@ -2,316 +2,344 @@
#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'
static bool token_is_variable(const char *input, int input_pos, int *token_size)
{
if (ft_isalpha(input[input_pos]))
{
*token_size = 1;
return true;
}
return false;
if (ft_isalpha(input[input_pos]))
{
*token_size = 1;
return true;
}
return false;
}
// token is int "123"
static bool token_is_number_int(const char *input, int input_pos, int *token_size)
{
int number_size;
int max_number_size;
int number_size;
if (!ft_isdigit(input[input_pos]))
{
return false;
}
number_size = 0;
number_size = 1;
max_number_size = 16; // max size for int
while (number_size <= max_number_size)
{
if (ft_isdigit(input[input_pos + number_size]))
{
number_size++;
}
else if (input[input_pos + number_size] == '.')
{
if (ft_isdigit(input[input_pos + number_size + 1]))
{
// number is double
return false;
}
else
break;
}
else
break;
}
if (number_size > max_number_size)
{
stop_errors(&input[input_pos]);
}
*token_size = number_size;
return true;
// if (input[input_pos + number_size] == '-')
// number_size++;
while (input[input_pos + number_size] != '\0')
{
if (ft_isdigit(input[input_pos + number_size]))
{
number_size++;
}
else
break;
}
if (number_size == 0)
{
return false;
}
if (is_number_out_of_int_range(&input[input_pos], number_size))
{
return false;
}
*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)
{
int number_size;
int max_number_size;
bool has_dot;
int number_size;
bool has_dot;
if (!ft_isdigit(input[input_pos]))
{
return false;
}
has_dot = false;
number_size = 0;
has_dot = false;
number_size = 1;
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)
{
if (ft_isdigit(input[input_pos + number_size]))
{
number_size++;
}
else if (input[input_pos + number_size] == '.')
{
if (has_dot)
{
// number is not a valid token, it has 2 dots
return false;
}
if (!ft_isdigit(input[input_pos + number_size + 1]))
{
// number is not valid token, it has a dot with no number after the dot
return false;
}
has_dot = true;
number_size++;
}
else
break;
}
if (number_size > max_number_size)
{
stop_errors(&input[input_pos]);
}
*token_size = number_size;
return true;
// if (input[input_pos + number_size] == '-')
// number_size++;
while (input[input_pos + number_size] != '\0')
{
if (ft_isdigit(input[input_pos + number_size]))
{
number_size++;
}
else if (input[input_pos + number_size] == '.' && !has_dot)
{
has_dot = true;
number_size++;
}
else
break;
}
if (is_number_out_of_int_range(&input[input_pos], number_size))
{
*token_size = number_size;
return true;
}
if (!has_dot)
{
return false;
}
*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)
{
int digit_size = 0;
int number_size = 0;
int max_number_size = 16; // same max size as regular integers
int digit_size = 0;
int number_size = 0;
int superscript_len = 0;
int superscript_len_max = 3; // max length of superscript int we want to support
// check if first character is superscript
if (!ft_isdigit_superscript(input + input_pos, NULL))
{
return false;
}
// iterate to find full superscript number
while (input[input_pos + number_size] != '\0')
{
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
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_size = number_size;
return true;
}
// token is '^' or "**"
static bool token_is_power(const char *input, int input_pos, int *token_size)
{
if (input[input_pos] == '^')
{
*token_size = 1;
return true;
}
if (ft_memcmp(&input[input_pos], "**", 2) == 0)
{
*token_size = 2;
return true;
}
return false;
if (input[input_pos] == '^')
{
*token_size = 1;
return true;
}
if (ft_memcmp(&input[input_pos], "**", 2) == 0)
{
*token_size = 2;
return true;
}
return false;
}
// token is '+'
static bool token_is_sign_plus(const char *input, int input_pos, int *token_size)
{
if (input[input_pos] == '+')
{
*token_size = 1;
return true;
}
return false;
if (input[input_pos] == '+')
{
*token_size = 1;
return true;
}
return false;
}
// token is '-'
static bool token_is_sign_minus(const char *input, int input_pos, int *token_size)
{
if (input[input_pos] == '-')
{
*token_size = 1;
return true;
}
return false;
if (input[input_pos] == '-')
{
*token_size = 1;
return true;
}
return false;
}
// token is '*'
static bool token_is_factor_multiplication(const char *input, int input_pos, int *token_size)
{
if (input[input_pos] == '*')
{
*token_size = 1;
return true;
}
return false;
if (input[input_pos] == '*')
{
*token_size = 1;
return true;
}
return false;
}
// token is '/' or ':'
static bool token_is_factor_division(const char *input, int input_pos, int *token_size)
{
if (input[input_pos] == '/')
{
*token_size = 1;
return true;
}
if (input[input_pos] == ':')
{
*token_size = 1;
return true;
}
return false;
if (input[input_pos] == '/')
{
*token_size = 1;
return true;
}
if (input[input_pos] == ':')
{
*token_size = 1;
return true;
}
return false;
}
// token is '='
static bool token_is_equal(const char *input, int input_pos, int *token_size)
{
if (input[input_pos] == '=')
{
*token_size = 1;
return true;
}
return false;
if (input[input_pos] == '=')
{
*token_size = 1;
return true;
}
return false;
}
/**
* LEXER
*/
void lexerize(const char *input, s_token *tokens)
{
int tokens_count;
int input_pos;
int token_size;
bool has_equal;
int tokens_count;
int input_pos;
int token_size;
bool has_equal;
has_equal = false;
tokens_count = 0;
input_pos = 0;
while (input[input_pos])
{
token_size = 0;
has_equal = false;
tokens_count = 0;
input_pos = 0;
while (input[input_pos])
{
token_size = 0;
if (input[input_pos] == '\0')
{
break;
}
if (input[input_pos] == '\0')
{
break;
}
if (token_is_variable(input, input_pos, &token_size))
{
tokens[tokens_count].type = TOKEN_VARIABLE;
tokens[tokens_count].tag = TOKEN_NO_TAG;
tokens[tokens_count].value_char = 'x';
}
else if (token_is_number_int(input, input_pos, &token_size))
{
tokens[tokens_count].type = TOKEN_NUMBER_INT;
tokens[tokens_count].tag = TOKEN_NUMBER;
tokens[tokens_count].value_int = ft_atoi(&input[input_pos]);
}
else if (token_is_number_double(input, input_pos, &token_size))
{
tokens[tokens_count].type = TOKEN_NUMBER_DOUBLE;
tokens[tokens_count].tag = TOKEN_NUMBER;
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))
{
tokens[tokens_count].type = TOKEN_POWER;
tokens[tokens_count].tag = TOKEN_NO_TAG;
tokens[tokens_count].value_char = '^';
}
else if (token_is_sign_plus(input, input_pos, &token_size))
{
tokens[tokens_count].type = TOKEN_SIGN_PLUS;
tokens[tokens_count].tag = TOKEN_SIGN;
tokens[tokens_count].value_char = input[input_pos];
}
else if (token_is_sign_minus(input, input_pos, &token_size))
{
tokens[tokens_count].type = TOKEN_SIGN_MINUS;
tokens[tokens_count].tag = TOKEN_SIGN;
tokens[tokens_count].value_char = input[input_pos];
}
else if (token_is_factor_multiplication(input, input_pos, &token_size))
{
tokens[tokens_count].type = TOKEN_FACTOR_MULT;
tokens[tokens_count].tag = TOKEN_FACTOR;
tokens[tokens_count].value_char = input[input_pos];
}
else if (token_is_factor_division(input, input_pos, &token_size))
{
tokens[tokens_count].type = TOKEN_FACTOR_DIV;
tokens[tokens_count].tag = TOKEN_FACTOR;
tokens[tokens_count].value_char = input[input_pos];
}
else if (token_is_equal(input, input_pos, &token_size))
{
has_equal = true;
tokens[tokens_count].type = TOKEN_EQUAL;
tokens[tokens_count].tag = TOKEN_NO_TAG;
tokens[tokens_count].value_char = '=';
}
else
{
stop_errors("input[input_pos] is not any token: %s\n", &input[input_pos]);
}
if (token_is_variable(input, input_pos, &token_size))
{
tokens[tokens_count].type = TOKEN_VARIABLE;
tokens[tokens_count].tag = TOKEN_NO_TAG;
tokens[tokens_count].value_char = 'x';
}
else if (token_is_number_double(input, input_pos, &token_size))
{
tokens[tokens_count].type = TOKEN_NUMBER_DOUBLE;
tokens[tokens_count].tag = TOKEN_NUMBER;
tokens[tokens_count].value_double = ft_atof(&input[input_pos]);
}
else if (token_is_number_int(input, input_pos, &token_size))
{
tokens[tokens_count].type = TOKEN_NUMBER_INT;
tokens[tokens_count].tag = TOKEN_NUMBER;
tokens[tokens_count].value_int = ft_atoi(&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))
{
tokens[tokens_count].type = TOKEN_POWER;
tokens[tokens_count].tag = TOKEN_NO_TAG;
tokens[tokens_count].value_char = '^';
}
else if (token_is_sign_plus(input, input_pos, &token_size))
{
tokens[tokens_count].type = TOKEN_SIGN_PLUS;
tokens[tokens_count].tag = TOKEN_SIGN;
tokens[tokens_count].value_char = input[input_pos];
}
else if (token_is_sign_minus(input, input_pos, &token_size))
{
tokens[tokens_count].type = TOKEN_SIGN_MINUS;
tokens[tokens_count].tag = TOKEN_SIGN;
tokens[tokens_count].value_char = input[input_pos];
}
else if (token_is_factor_multiplication(input, input_pos, &token_size))
{
tokens[tokens_count].type = TOKEN_FACTOR_MULT;
tokens[tokens_count].tag = TOKEN_FACTOR;
tokens[tokens_count].value_char = input[input_pos];
}
else if (token_is_factor_division(input, input_pos, &token_size))
{
tokens[tokens_count].type = TOKEN_FACTOR_DIV;
tokens[tokens_count].tag = TOKEN_FACTOR;
tokens[tokens_count].value_char = input[input_pos];
}
else if (token_is_equal(input, input_pos, &token_size))
{
has_equal = true;
tokens[tokens_count].type = TOKEN_EQUAL;
tokens[tokens_count].tag = TOKEN_NO_TAG;
tokens[tokens_count].value_char = '=';
}
else
{
stop_errors("input[input_pos] is not any token: %s\n", &input[input_pos]);
}
tokens_count++;
if (token_size == 0)
{
stop_errors("token_size is 0 : %s\n", &input[input_pos]);
}
input_pos += token_size;
}
tokens_count++;
if (token_size == 0)
{
stop_errors("token_size is 0 : %s\n", &input[input_pos]);
}
input_pos += token_size;
}
if (!has_equal)
stop_errors("the input polynomial does not contains an equal sign, it's an expression not an equation.\n");
if (!has_equal)
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].tag = TOKEN_NO_TAG;
tokens[tokens_count].value_char = '\0';
tokens[tokens_count].type = TOKEN_END;
tokens[tokens_count].tag = TOKEN_NO_TAG;
tokens[tokens_count].value_char = '\0';
}

View File

@@ -21,167 +21,161 @@ s_solution *solution_g_err;
static void print_usage()
{
ft_printf("USAGE :\n\n");
ft_printf("| ./computorv1 [flags] [polynom]\n");
ft_printf("| ./computorv1 [polynom] [flags]\n");
ft_printf("| ./computorv1 [flags] -> interactiv mode\n\n");
ft_printf("[flags] :\n");
ft_printf("-d : print debug\n");
ft_printf("-l : interactive loop\n");
ft_printf("-b : beautify output\n");
ft_putchar('\n');
ft_printf("USAGE :\n\n");
ft_printf("| ./computorv1 [flags] [polynom]\n");
ft_printf("| ./computorv1 [polynom] [flags]\n");
ft_printf("| ./computorv1 [flags] -> interactiv mode\n\n");
ft_printf("[flags] :\n");
ft_printf("-d : print debug\n");
ft_printf("-l : interactive loop\n");
ft_printf("-b : beautify output\n");
ft_putchar('\n');
}
// trim spaces and quotes and newlines
static void clean_copy_input(char *input, char *line)
{
size_t i;
size_t j;
size_t len;
size_t len_trim_end;
size_t len_trim_start;
size_t i;
size_t j;
size_t len;
size_t len_trim_end;
size_t len_trim_start;
len = ft_strlen(line);
len = ft_strlen(line);
// get len minus : ' | " | \n | <space>
i = len;
while (i > 0)
{
if (ft_strchr("\"\'\n", line[i]))
i--;
if (ft_isspace(line[i]))
i--;
break;
}
len_trim_end = i;
// get len minus : ' | " | \n | <space>
i = len;
while (i > 0)
{
if (ft_strchr("\"\'\n", line[i]))
i--;
if (ft_isspace(line[i]))
i--;
break;
}
len_trim_end = i;
// get len of leading chars : ' | " | <space> | \n
i = 0;
while (i < len_trim_end)
{
if (ft_strchr("\"\'\n", line[i]))
i++;
if (ft_isspace(line[i]))
i++;
break;
}
len_trim_start = i;
// get len of leading chars : ' | " | <space> | \n
i = 0;
while (i < len_trim_end)
{
if (ft_strchr("\"\'\n", line[i]))
i++;
if (ft_isspace(line[i]))
i++;
break;
}
len_trim_start = i;
// copy into input
i = len_trim_start;
j = 0;
while (i <= len_trim_end)
{
input[j] = line[i];
j++;
i++;
}
input[j] = '\0';
// copy into input
i = len_trim_start;
j = 0;
while (i <= len_trim_end)
{
input[j] = line[i];
j++;
i++;
}
input[j] = '\0';
}
static void launch_stdin()
{
char *line;
size_t len;
char *line;
size_t len;
line = NULL;
len = 0;
line = NULL;
len = 0;
// get input
getline(&line, &len, stdin);
// get input
getline(&line, &len, stdin);
// prepare input
char input[len];
clean_copy_input(input, line);
// prepare input
char input[len];
clean_copy_input(input, line);
// launch input
launch_computorv1(input);
// launch input
launch_computorv1(input);
// FREE LINE !
free(line);
// FREE LINE !
free(line);
}
static void launch_stdin_loop()
{
while (1)
{
// for the moment it does not work since errors exit
launch_stdin();
}
}
// static void launch_stdin_loop()
// {
// while (1)
// {
// // for the moment it does not work since errors exit
// launch_stdin();
// }
// }
int main(int ac, char **av)
{
int i;
char *input;
e_program_mode program_mode;
int i;
char *input;
e_program_mode program_mode;
// init flags
flag_debug_mode = false;
flag_loop_mode = false;
flag_beautify_mode = false;
// init flags
flag_debug_mode = false;
flag_loop_mode = false;
flag_beautify_mode = false;
// check arguments
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;
}
}
// check arguments
program_mode = MODE_ARGV;
// 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();
}
// 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;
}
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)
{
*token_count = 0;
int j;
e_term_sign ret_sign;
// default to '+'
ret_sign = TERM_PLUS;
// 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)
{
// if most left term, the sign can be ommited for a '+' sign in front of a number or variable
*token_count = 0;
return TERM_PLUS;
ret_sign = TERM_PLUS;
}
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
*token_count = 0;
return TERM_PLUS;
ret_sign = TERM_PLUS;
}
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);
}
return tokens[i].type == TOKEN_SIGN_PLUS ? TERM_PLUS : TERM_MINUS;
return ret_sign;
}
static double get_double_value(s_token token)

View File

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

File diff suppressed because one or more lines are too long