diff --git a/headers/errors.h b/headers/errors.h index b153a81..49ef8e2 100644 --- a/headers/errors.h +++ b/headers/errors.h @@ -9,8 +9,9 @@ typedef enum ERROR_UNKNOWN_TOKEN = -1, ERROR_NUMBER_TOO_BIG = -2, ERROR_PARSING = -3, + ERROR_TOKEN_POSITION = -4, } program_error; -int stop_errors(int err, const char *details); +int stop_errors(program_error err, const char *details); #endif \ No newline at end of file diff --git a/headers/lexer.h b/headers/lexer.h index ea9ab62..ae53511 100644 --- a/headers/lexer.h +++ b/headers/lexer.h @@ -7,13 +7,14 @@ typedef enum { - TOKEN_VARIABLE, // x, y, etc. - TOKEN_NUMBER, // int or double -> all converted into double - TOKEN_POWER, // ^ or ** - TOKEN_SIGN, // + or - - TOKEN_FACTOR, // * or / - TOKEN_EQUAL, // = - TOKEN_END // null (end of input) + TOKEN_VARIABLE, // x, y, etc. + TOKEN_NUMBER_INT, // int + TOKEN_NUMBER_DOUBLE, // double + TOKEN_POWER, // ^ or ** + TOKEN_SIGN, // + or - + TOKEN_FACTOR, // * or / + TOKEN_EQUAL, // = + TOKEN_END // null (end of input) } token_type; typedef struct @@ -22,6 +23,7 @@ typedef struct union { char value_char; + int value_int; double value_double; }; } token; diff --git a/src/computorv1.c b/src/computorv1.c index 5bc7e27..e0fe3e0 100644 --- a/src/computorv1.c +++ b/src/computorv1.c @@ -88,8 +88,10 @@ int main(int ac, char **av) if (tokens[i].type == TOKEN_VARIABLE) ft_printf("%20s", "TOKEN_VARIABLE"); - else if (tokens[i].type == TOKEN_NUMBER) - ft_printf("%20s", "TOKEN_NUMBER"); + 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) @@ -103,7 +105,11 @@ int main(int ac, char **av) ft_putstr(" - value : "); - if (tokens[i].type == TOKEN_NUMBER) + if (tokens[i].type == TOKEN_NUMBER_INT) + { + printf("%i\n", tokens[i].value_int); + } + else if (tokens[i].type == TOKEN_NUMBER_DOUBLE) { printf("%g\n", tokens[i].value_double); } diff --git a/src/errors.c b/src/errors.c index 5fcc214..d8a7b84 100644 --- a/src/errors.c +++ b/src/errors.c @@ -1,6 +1,6 @@ #include "errors.h" -int stop_errors(int err, const char *details) +int stop_errors(program_error err, const char *details) { switch (err) { @@ -13,6 +13,9 @@ int stop_errors(int err, const char *details) case ERROR_PARSING: ft_putstr_fd("error: too much terms to parse, details : ", STDERR_FILENO); break; + case ERROR_TOKEN_POSITION: + ft_putstr_fd("error: token position is not good in grammar, details : ", STDERR_FILENO); + break; default: ft_putstr_fd("unknown error, details : ", STDERR_FILENO); break; diff --git a/src/lexer.c b/src/lexer.c index b87e21f..66982b5 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -11,8 +11,48 @@ static bool token_is_variable(const char *input, int input_pos, int *token_size) return false; } -// number can be int "123" or double "123.456" -static bool token_is_number(const char *input, int input_pos, int *token_size) +// number can be int "123" +static bool token_is_number_int(const char *input, int input_pos, int *token_size) +{ + int number_size; + int max_number_size; + + if (!ft_isdigit(input[input_pos])) + { + return false; + } + + 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(ERROR_NUMBER_TOO_BIG, &input[input_pos]); + } + *token_size = number_size; + return true; +} + +// number can be double "123.456" +static bool token_is_number_double(const char *input, int input_pos, int *token_size) { int number_size; int max_number_size; @@ -147,9 +187,14 @@ int lexerize(const char *input, token *tokens) tokens[tokens_count].type = TOKEN_VARIABLE; tokens[tokens_count].value_char = 'x'; } - else if (token_is_number(input, input_pos, &token_size)) + else if (token_is_number_int(input, input_pos, &token_size)) { - tokens[tokens_count].type = TOKEN_NUMBER; + tokens[tokens_count].type = TOKEN_NUMBER_INT; + 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].value_double = ft_atof(&input[input_pos]); } else if (token_is_power(input, input_pos, &token_size)) diff --git a/src/parser.c b/src/parser.c index d68a88e..1eee6d5 100644 --- a/src/parser.c +++ b/src/parser.c @@ -10,9 +10,9 @@ TOKEN_EQUAL, // = TOKEN_END // null (end of input) - 1. VARIABLE | NUMBER_INT | NUMBER_DOUBLE | POWER | SIGN | FACTOR | EQUAL | END - 2. VARIABLE | NUMBER_INT | NUMBER_DOUBLE | POWER | SIGN | FACTOR | EQUAL | END - 3. VARIABLE | NUMBER_INT | NUMBER_DOUBLE | POWER | SIGN | FACTOR | EQUAL | END + 1. VARIABLE | NUMBER_INT | NUMBER_DOUBLE | ! POWER | SIGN | ! FACTOR | ! EQUAL | END + 2. VARIABLE | NUMBER_INT | NUMBER_DOUBLE | POWER | SIGN | FACTOR | EQUAL | END + 3. VARIABLE | NUMBER_INT | NUMBER_DOUBLE | POWER | SIGN | FACTOR | EQUAL | END term_position position; term_sign sign; @@ -21,23 +21,52 @@ int exponent; */ -static term_sign get_sign(token *tokens, int *token_count) +static term_sign get_sign(token *tokens, int i, int *token_count) { - if (tokens) // placeholder - *token_count = 1; // placeholder - return '+'; // placeholder + // forbidden tokens + if (tokens[i].type == TOKEN_POWER) + { + stop_errors(ERROR_TOKEN_POSITION, "at begining of term, we should not have a power token : " + tokens[i].value_char); + } + if (tokens[i].type == TOKEN_FACTOR) + { + stop_errors(ERROR_TOKEN_POSITION, "at begining of term, we should not have a factor token : " + tokens[i].value_char); + } + if (tokens[i].type == TOKEN_EQUAL) + { + stop_errors(ERROR_TOKEN_POSITION, "at begining of term, we should not have an equal token : " + tokens[i].value_char); + } + + // sign + if (tokens[i].type == TOKEN_SIGN) + { + *token_count = 1; + return tokens[i].value_char; + } + 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 = 1; + return '+'; + } + 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 = 1; + return '+'; + } + + return stop_errors(ERROR_TOKEN_POSITION, "at begining of term, we should have a sign token " + tokens[i].value_char); } -static double get_coefficient(token *tokens, int *token_count) +static double get_coefficient(token *tokens, int i, int *token_count) { - if (tokens) // placeholder + if (tokens[i].type) // placeholder *token_count = 1; // placeholder return 1.0; // placeholder } -static int get_exponent(token *tokens, int *token_count) +static int get_exponent(token *tokens, int i, int *token_count) { - if (tokens) // placeholder + if (tokens[i].type) // placeholder *token_count = 1; // placeholder return 1; // placeholder } @@ -66,22 +95,22 @@ int parse(token *tokens, term *terms, int terms_count_max) terms[terms_count].position = term_position; // sign - terms[terms_count].sign = get_sign(&tokens[i], &token_count); + terms[terms_count].sign = get_sign(tokens, i, &token_count); i += token_count; // coefficient - terms[terms_count].coefficient = get_coefficient(&tokens[i], &token_count); + terms[terms_count].coefficient = get_coefficient(tokens, i, &token_count); i += token_count; // exponent - terms[terms_count].exponent = get_exponent(&tokens[i], &token_count); + terms[terms_count].exponent = get_exponent(tokens, i, &token_count); i += token_count; i++; terms_count++; } - // last token is TOKEN_END, and terms[] should have at least one more spot for a null + // last token is TOKEN_END, and terms[] should have at least one more spot for the END term if (tokens[i].type == TOKEN_END && terms_count < terms_count_max) { terms[terms_count].position = TERM_END;