From caf0edd54871cae220c4a1afc3fb61c570c57998 Mon Sep 17 00:00:00 2001 From: tomasanchez Date: Sat, 14 Nov 2020 00:45:56 -0300 Subject: [PATCH] Finished calculator --- 08-CalcInfAuto/auto/scanner.l | 1 + 08-CalcInfAuto/inc/Calc.h | 5 - 08-CalcInfAuto/inc/parser.h | 5 +- 08-CalcInfAuto/inc/scanner.h | 5 +- 08-CalcInfAuto/inc/solver.h | 67 +++++++ 08-CalcInfAuto/leaks.log | 44 ++--- 08-CalcInfAuto/src/Calc.c | 6 + 08-CalcInfAuto/src/lex.yy.c | 91 ++++----- 08-CalcInfAuto/src/parser.c | 4 +- 08-CalcInfAuto/src/scanner.c | 4 +- 08-CalcInfAuto/src/solver.c | 334 ++++++++++++++++++++++++++++++++++ 11 files changed, 491 insertions(+), 75 deletions(-) create mode 100644 08-CalcInfAuto/inc/solver.h create mode 100644 08-CalcInfAuto/src/solver.c diff --git a/08-CalcInfAuto/auto/scanner.l b/08-CalcInfAuto/auto/scanner.l index a19a013..2bcbd31 100644 --- a/08-CalcInfAuto/auto/scanner.l +++ b/08-CalcInfAuto/auto/scanner.l @@ -12,6 +12,7 @@ bool allOK = true; [a-zA-Z]+ { scanner_GetNextToken(*yytext, VARIABLE); totalTokens_g++;} [+*-]+ { scanner_GetNextToken(*yytext, OPERATOR); totalTokens_g++;} [(] { scanner_GetNextToken(*yytext, LBRACKET); totalTokens_g++;} +[)] { scanner_GetNextToken(*yytext, RBRACKET); totalTokens_g++;} [\n|<>] { return 0;} . { puts("Undefined Symbol: Exiting..."); exit(-1);} %% diff --git a/08-CalcInfAuto/inc/Calc.h b/08-CalcInfAuto/inc/Calc.h index bac919a..97bc243 100644 --- a/08-CalcInfAuto/inc/Calc.h +++ b/08-CalcInfAuto/inc/Calc.h @@ -33,11 +33,6 @@ #include "scanner.h" -/*Calls Flex Scanner*/ -int yylex(); - -/*Calculator Functions*/ - /*Show welcome message*/ int calculator_create(); diff --git a/08-CalcInfAuto/inc/parser.h b/08-CalcInfAuto/inc/parser.h index f709219..b2dfcea 100644 --- a/08-CalcInfAuto/inc/parser.h +++ b/08-CalcInfAuto/inc/parser.h @@ -50,4 +50,7 @@ int parser_delete(); bool parser_GetNextToken(int , token_id_t); /*Prints all token parsed*/ -int parser_print_results(); \ No newline at end of file +int parser_print_results(); + +/*Tells if parse has error*/ +bool parser_has_error(); \ No newline at end of file diff --git a/08-CalcInfAuto/inc/scanner.h b/08-CalcInfAuto/inc/scanner.h index 83ca1ed..a8927ab 100644 --- a/08-CalcInfAuto/inc/scanner.h +++ b/08-CalcInfAuto/inc/scanner.h @@ -30,7 +30,10 @@ ------------------------------------------------------------------------------------ */ #pragma once -#include "parser.h" +#include "solver.h" + +/*Calls Flex Scanner*/ +int yylex(); /*Loads new token from scanner buffer*/ int scanner_GetNextToken(int , token_id_t); \ No newline at end of file diff --git a/08-CalcInfAuto/inc/solver.h b/08-CalcInfAuto/inc/solver.h new file mode 100644 index 0000000..dc2594a --- /dev/null +++ b/08-CalcInfAuto/inc/solver.h @@ -0,0 +1,67 @@ +/* --------------------------------------------------------------------------------- + + solver.h + + solver for infix automatic-scanner calculator. + + MIT License + + Copyright (c) 2020 Tomas Sanchez + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + last modified: 11/13/2020 +------------------------------------------------------------------------------------ */ + +#pragma once + +#include "parser.h" + +/*Token handler*/ +typedef struct Token{ + int token; + token_id_t type; +}token_t; + +/*Object that can solve expressions*/ +typedef struct Solver{ + /*Current token buffered*/ + token_t * token; + /*Queue*/ + t_queue * output_queue; + /*Stack*/ + stack_t * operator_stack; + /*Value obtained after all calculations were applied*/ + int final_result; +}solver_t; + +/*Creates a solver*/ +int solver_create(); + +/*Frees memory usage form solver*/ +int solver_delete(); + +/*Stores next token*/ +int solver_GetNextToken(int, token_id_t); + +/*Solves expression*/ +int solver_update(); + +/*Print results*/ +int solver_print(); \ No newline at end of file diff --git a/08-CalcInfAuto/leaks.log b/08-CalcInfAuto/leaks.log index 6b43130..8eeb49e 100644 --- a/08-CalcInfAuto/leaks.log +++ b/08-CalcInfAuto/leaks.log @@ -1,22 +1,22 @@ -==2575== Memcheck, a memory error detector -==2575== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. -==2575== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info -==2575== Command: ./Calculator.exe -==2575== Parent PID: 2555 -==2575== -==2575== -==2575== HEAP SUMMARY: -==2575== in use at exit: 16,482 bytes in 4 blocks -==2575== total heap usage: 14 allocs, 10 frees, 18,642 bytes allocated -==2575== -==2575== LEAK SUMMARY: -==2575== definitely lost: 0 bytes in 0 blocks -==2575== indirectly lost: 0 bytes in 0 blocks -==2575== possibly lost: 0 bytes in 0 blocks -==2575== still reachable: 16,482 bytes in 4 blocks -==2575== suppressed: 0 bytes in 0 blocks -==2575== Reachable blocks (those to which a pointer was found) are not shown. -==2575== To see them, rerun with: --leak-check=full --show-leak-kinds=all -==2575== -==2575== For counts of detected and suppressed errors, rerun with: -v -==2575== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) +==1772== Memcheck, a memory error detector +==1772== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. +==1772== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info +==1772== Command: ./Calculator.exe +==1772== Parent PID: 1750 +==1772== +==1772== +==1772== HEAP SUMMARY: +==1772== in use at exit: 16,482 bytes in 4 blocks +==1772== total heap usage: 29 allocs, 25 frees, 18,866 bytes allocated +==1772== +==1772== LEAK SUMMARY: +==1772== definitely lost: 0 bytes in 0 blocks +==1772== indirectly lost: 0 bytes in 0 blocks +==1772== possibly lost: 0 bytes in 0 blocks +==1772== still reachable: 16,482 bytes in 4 blocks +==1772== suppressed: 0 bytes in 0 blocks +==1772== Reachable blocks (those to which a pointer was found) are not shown. +==1772== To see them, rerun with: --leak-check=full --show-leak-kinds=all +==1772== +==1772== For counts of detected and suppressed errors, rerun with: -v +==1772== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) diff --git a/08-CalcInfAuto/src/Calc.c b/08-CalcInfAuto/src/Calc.c index ed638b6..cbbcfeb 100644 --- a/08-CalcInfAuto/src/Calc.c +++ b/08-CalcInfAuto/src/Calc.c @@ -34,6 +34,7 @@ int calculator_create(){ parser_create(); + solver_create(); return puts(" :: == A Simple Infix Calculator With Flex-Generated Scanner == :: "); } @@ -45,10 +46,15 @@ int calculator_read(){ int calculator_update(){ parser_print_results(); + if(! parser_has_error()){ + solver_update(); + solver_print(); + } return OK; } int calculator_delete(){ parser_delete(); + solver_delete(); return puts("\n- :: © 2020 TOMAS SANCHEZ - | :: | All rights reserved :: -"); } \ No newline at end of file diff --git a/08-CalcInfAuto/src/lex.yy.c b/08-CalcInfAuto/src/lex.yy.c index 5829ce7..a579817 100644 --- a/08-CalcInfAuto/src/lex.yy.c +++ b/08-CalcInfAuto/src/lex.yy.c @@ -372,8 +372,8 @@ static void yynoreturn yy_fatal_error ( const char* msg ); YY_FATAL_ERROR( "token too large, exceeds YYLMAX" ); \ yy_flex_strncpy( yytext, (yytext_ptr), yyleng + 1 ); \ (yy_c_buf_p) = yy_cp; -#define YY_NUM_RULES 7 -#define YY_END_OF_BUFFER 8 +#define YY_NUM_RULES 8 +#define YY_END_OF_BUFFER 9 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -381,10 +381,10 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static const flex_int16_t yy_accept[16] = +static const flex_int16_t yy_accept[17] = { 0, - 0, 0, 8, 6, 5, 4, 3, 1, 5, 2, - 2, 3, 1, 2, 0 + 0, 0, 9, 7, 6, 4, 5, 3, 1, 6, + 2, 2, 3, 1, 2, 0 } ; static const YY_CHAR yy_ec[256] = @@ -393,16 +393,16 @@ static const YY_CHAR yy_ec[256] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, - 1, 4, 4, 1, 4, 1, 1, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 1, 1, 6, - 1, 6, 1, 1, 7, 7, 7, 7, 8, 8, - 7, 7, 7, 7, 7, 7, 7, 7, 8, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 1, 1, 1, 1, 1, 1, 7, 7, 7, 7, - - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 1, 6, 1, 1, 1, 1, 1, 1, + 4, 5, 5, 1, 5, 1, 1, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 1, 1, 7, + 1, 7, 1, 1, 8, 8, 8, 8, 9, 9, + 8, 8, 8, 8, 8, 8, 8, 8, 9, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 1, 1, 1, 1, 1, 1, 8, 8, 8, 8, + + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 1, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -419,41 +419,41 @@ static const YY_CHAR yy_ec[256] = 1, 1, 1, 1, 1 } ; -static const YY_CHAR yy_meta[9] = +static const YY_CHAR yy_meta[10] = { 0, - 1, 1, 1, 1, 1, 1, 2, 2 + 1, 1, 1, 1, 1, 1, 1, 2, 2 } ; -static const flex_int16_t yy_base[17] = +static const flex_int16_t yy_base[18] = { 0, - 0, 0, 14, 15, 15, 15, 9, 7, 15, 0, - 0, 7, 5, 0, 15, 7 + 0, 0, 15, 16, 16, 16, 16, 9, 7, 16, + 0, 0, 7, 5, 0, 16, 8 } ; -static const flex_int16_t yy_def[17] = +static const flex_int16_t yy_def[18] = { 0, - 15, 1, 15, 15, 15, 15, 15, 15, 15, 16, - 16, 15, 15, 16, 0, 15 + 16, 1, 16, 16, 16, 16, 16, 16, 16, 16, + 17, 17, 16, 16, 17, 0, 16 } ; -static const flex_int16_t yy_nxt[24] = +static const flex_int16_t yy_nxt[26] = { 0, - 4, 5, 6, 7, 8, 9, 10, 11, 14, 13, - 12, 13, 12, 15, 3, 15, 15, 15, 15, 15, - 15, 15, 15 + 4, 5, 6, 7, 8, 9, 10, 11, 12, 15, + 14, 13, 14, 13, 16, 3, 16, 16, 16, 16, + 16, 16, 16, 16, 16 } ; -static const flex_int16_t yy_chk[24] = +static const flex_int16_t yy_chk[26] = { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 16, 13, - 12, 8, 7, 3, 15, 15, 15, 15, 15, 15, - 15, 15, 15 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, + 14, 13, 9, 8, 3, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16 } ; /* Table of booleans, true if rule could match eol. */ -static const flex_int32_t yy_rule_can_match_eol[8] = +static const flex_int32_t yy_rule_can_match_eol[9] = { 0, -0, 0, 0, 0, 1, 0, 0, }; +0, 0, 0, 0, 0, 1, 0, 0, }; static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; @@ -727,13 +727,13 @@ YY_DECL while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 16 ) + if ( yy_current_state >= 17 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; ++yy_cp; } - while ( yy_base[yy_current_state] != 15 ); + while ( yy_base[yy_current_state] != 16 ); yy_find_action: yy_act = yy_accept[yy_current_state]; @@ -788,22 +788,27 @@ YY_RULE_SETUP { scanner_GetNextToken(*yytext, LBRACKET); totalTokens_g++;} YY_BREAK case 5: -/* rule 5 can match eol */ YY_RULE_SETUP #line 15 "auto/scanner.l" -{ return 0;} +{ scanner_GetNextToken(*yytext, RBRACKET); totalTokens_g++;} YY_BREAK case 6: +/* rule 6 can match eol */ YY_RULE_SETUP #line 16 "auto/scanner.l" -{ puts("Undefined Symbol: Exiting..."); exit(-1);} +{ return 0;} YY_BREAK case 7: YY_RULE_SETUP #line 17 "auto/scanner.l" +{ puts("Undefined Symbol: Exiting..."); exit(-1);} + YY_BREAK +case 8: +YY_RULE_SETUP +#line 18 "auto/scanner.l" ECHO; YY_BREAK -#line 807 "lex.yy.c" +#line 812 "lex.yy.c" case YY_STATE_EOF(INITIAL): yyterminate(); @@ -1100,7 +1105,7 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 16 ) + if ( yy_current_state >= 17 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; @@ -1128,11 +1133,11 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 16 ) + if ( yy_current_state >= 17 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; - yy_is_jam = (yy_current_state == 15); + yy_is_jam = (yy_current_state == 16); return yy_is_jam ? 0 : yy_current_state; } @@ -1818,6 +1823,6 @@ void yyfree (void * ptr ) free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ } -#line 17 "auto/scanner.l" +#line 18 "auto/scanner.l" diff --git a/08-CalcInfAuto/src/parser.c b/08-CalcInfAuto/src/parser.c index c48441c..c0d4d99 100644 --- a/08-CalcInfAuto/src/parser.c +++ b/08-CalcInfAuto/src/parser.c @@ -153,8 +153,8 @@ bool __token_is_valid__(token_id_t new, token_id_t previous){ } } -bool expression_is_valid(){ - return lBrackets == rBrackets; +bool parser_has_error(){ + return !oParser->valid_expression; } int parser_print_results(){ diff --git a/08-CalcInfAuto/src/scanner.c b/08-CalcInfAuto/src/scanner.c index f362408..bee2879 100644 --- a/08-CalcInfAuto/src/scanner.c +++ b/08-CalcInfAuto/src/scanner.c @@ -32,5 +32,7 @@ #include "../inc/scanner.h" int scanner_GetNextToken(int value, token_id_t type){ - parser_GetNextToken(value, type); + if(parser_GetNextToken(value, type)) + solver_GetNextToken(value, type); + return OK; } \ No newline at end of file diff --git a/08-CalcInfAuto/src/solver.c b/08-CalcInfAuto/src/solver.c new file mode 100644 index 0000000..c751085 --- /dev/null +++ b/08-CalcInfAuto/src/solver.c @@ -0,0 +1,334 @@ +/* --------------------------------------------------------------------------------- + + solver.c + + solver for infix automatic-scanner calculator. + + MIT License + + Copyright (c) 2020 Tomas Sanchez + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + last modified: 11/13/2020 +------------------------------------------------------------------------------------ */ + +#include "../inc/solver.h" + +/*Global Token counter*/ +extern int totalTokens_g; + +/*Local Solver*/ +solver_t * oSolver; + +/*Private Functions*/ + +/*Solves '(expression)' operations stacks*/ +int __handle_parenthesis__(); + +/*Solve math expression a (operator) b, operator in {+,-,*}*/ +int __solve__(int a, int b, char operator); + +/*Determines precedence of operators*/ +int __precedence__(int); + +/*Creates a tok with the passed token and its type*/ +token_t * __token_create__(int token, token_id_t type); + +/* +=============================================================================================================================== +============================================= SOLVER ALLOCATIONS ============================================================= +=============================================================================================================================== +*/ + +int solver_create(){ + if(VERBOSE && SOLVER) + puts("[DEBUG] :: [SOLVER] :: Creating solver..."); + /*Reserving solver size*/ + oSolver = malloc(sizeof(solver_t)); + /*Creating dynamic elements*/ + oSolver->token = NULL; + oSolver->output_queue = queue_create(); + oSolver->operator_stack = stack_create(); + oSolver->final_result = 0; + + if(VERBOSE && SOLVER) + puts("[DEBUG] :: [SOLVER] :: Solver created!"); + + return OK; +} + +int solver_delete(){ + + + //Deleting current token + if(oSolver->token != NULL) + free(oSolver->token); + + // Elements should have been removed, but just in case, we verify this + if(!queue_is_empty(oSolver->output_queue)) + queue_destroy_and_destroy_elements(oSolver->output_queue, free); + else + queue_destroy(oSolver->output_queue); + + /* The same applies to the stack */ + if(!stack_is_empty(oSolver->operator_stack)) + stack_delete_and_delete_elements(oSolver->operator_stack, free); + else + stack_delete(oSolver->operator_stack); + + free(oSolver); + + return OK; +} + +/* +=============================================================================================================================== +============================================= TOKENS HANDLING ================================================================= +=============================================================================================================================== +*/ + +token_t * __token_create__(int token, token_id_t type){ + token_t * new = malloc(sizeof(token_t)); + new->token = token; + new->type = type; + return new; +} + +int solver_GetNextToken(int tok, token_id_t type){ + /*Tok for operators handling*/ + token_t * previous = NULL; + + if(VERBOSE && SOLVER) + printf("[DEBUG] :: [SOLVER] :: Evaluating '%d'\n", tok); + + switch (type) + { + case OPERAND: + case VARIABLE: + /*Being operands, only need to be enqueued, however we ensure they have the correct value, by parsing to int*/ + // NOTE: this method parsed variables to 0. + oSolver->token = __token_create__(tok, OPERAND); + if(VERBOSE && SOLVER) + printf("[DEBUG] :: [SOLVER] :: '%d' -> '%d' :: Parser -> outputQueue\n", tok, oSolver->token->token); + queue_push(oSolver->output_queue, oSolver->token); + return OK; + case RBRACKET: + /*As ')' is not needed, we do not allocate memory for it. Is not pushed but solved*/ + if(VERBOSE && SOLVER) + puts("[DEBUG] :: [SOLVER] :: Handling Parenthesis..."); + /*All operators will moved Stack -> output Queue, until the first ')' is found*/ + __handle_parenthesis__(); + return OK; + case LBRACKET: + /*No break, as '(' does need to be pushed*/ + case OPERATOR: + + /*We create a new tok, just to be pushed*/ + oSolver->token = __token_create__(tok, type); + + /*Pattern matching, '(' should be pushed + But also, if the stack was empty for any reason, we verify this before popping from it*/ + if(oSolver->token->token == '('|| stack_is_empty(oSolver->operator_stack)){ + stack_push(oSolver->operator_stack, oSolver->token); + return OK; + } + + previous = stack_pop(oSolver->operator_stack); + + /*If previous has higher precende, no changes are needed*/ + if(__precedence__(previous->token) < __precedence__(oSolver->token->token)){ + + if(VERBOSE && SOLVER){ + printf("[DEBUG] :: [SOLVER] :: Precendence of '%c' < Precende of '%c'\n", previous->token, oSolver->token->token); + printf("[DEBUG] :: [SOLVER] :: Stack::['%c'|'%c']\n", previous->token, oSolver->token->token); + } + stack_push(oSolver->operator_stack,previous); + stack_push(oSolver->operator_stack, oSolver->token); + }else{ + if(VERBOSE && SOLVER){ + printf("[DEBUG] :: [SOLVER] :: Precendence of '%c' > Precende of '%c'\n", previous->token, oSolver->token->token); + printf("[DEBUG] :: [SOLVER] :: Stack ::['%c']\n", oSolver->token->token); + printf("[DEBUG] :: [SOLVER] :: Queue :: <<'%c'>>\n", previous->token); + } + /*Otherwise, we move the previous to the queue, and stack the new one*/ + stack_push(oSolver->operator_stack, oSolver->token); + queue_push(oSolver->output_queue, previous); + } + default: + break; + } + return OK; +} + + +/* +=============================================================================================================================== +============================================= SOLVING HANDLING ================================================================= +=============================================================================================================================== +*/ + +int __precedence__(int op){ + + /*Lower number means higher precedence*/ + switch (op) + { + case '+': + case '-': + return 1; + + case '*': + case '/': + return 2; + + case '^': + return 3; + } + return -1; +} + +int __solve__(int a, int b, char optor){ + + if(VERBOSE && SOLVER) + puts("[DEBUG] :: [SOLVER] :: Solving..."); + + /*Solves for '+', '-', and '*' */ + switch (optor) + { + case '+': + if(VERBOSE && SOLVER) + printf("[DEBUG] :: [SOLVER] :: Solving '%d+%d'...\n", a, b); + + return a+b; + break; + case '*': + if(VERBOSE && SOLVER) + printf("[DEBUG] :: [SOLVER] :: Solving '%d' * '%d'...\n", a, b); + return a*b; + break; + case '-': + if(VERBOSE && SOLVER) + printf("[DEBUG] :: [SOLVER] :: Solving '%d' - '%d'...\n", a, b); + return a-b; + break; + default: + if(VERBOSE && SOLVER) + printf("[DEBUG] :: [SOLVER] :: '%c' is not an arithmetic operator\n", optor); + return -1; + break; + } + + return 0; +} + +int __handle_parenthesis__(){ + + /*Pops operator*/ + oSolver->token = (token_t *) stack_pop(oSolver->operator_stack); + + if(VERBOSE && SOLVER) + printf("[DEBUG] :: [SOLVER] :: [PARENTHESIS_HANDLER] :: First operator is <'%c'>\n", oSolver->token->token ); + /*Until the first LBRACKET is found, all operators will be moved*/ + while(oSolver->token->token != '('){ + /*Moving all operators to output queue*/ + queue_push(oSolver->output_queue, oSolver->token); + if(VERBOSE && SOLVER) + printf("[DEBUG] :: [SOLVER] :: [PARENTHESIS_HANDLER] :: Moved <'%c'> :: Stack -> Queue\n", oSolver->token->token); + oSolver->token = (token_t *) stack_pop(oSolver->operator_stack); + } + + if(VERBOSE && SOLVER) + puts("[DEBUG] :: [SOLVER] :: [PARENTHESIS_HANDLER] :: Parenthesis was solved"); + + // token should be '(', unused so must be freed + free(oSolver->token); + + oSolver->token = NULL; + + return OK; +} + +int solver_update(){ + + /*First operand*/ + token_t * a = NULL; + /*Second operand*/ + token_t * b = NULL; + + if(VERBOSE && SOLVER) + puts("[DEBUG] :: [SOLVER] :: [UPDATE] :: Calculating..."); + + /*First, we need to make sure there are no operators remaining in the stack, if there are, they are moved to the output queue*/ + while(!stack_is_empty(oSolver->operator_stack)){ + if(VERBOSE && SOLVER) + puts("[DEBUG] :: [SOLVER] :: [UPDATE] :: Emptying stack..."); + oSolver->token = (token_t *) stack_pop(oSolver->operator_stack); + queue_push(oSolver->output_queue, oSolver->token); + } + + /*Procedeing to solve the output queue*/ + while (!queue_is_empty(oSolver->output_queue)) + { + oSolver->token = (token_t *) queue_pop(oSolver->output_queue); + + /*As we need operators, operands are pushed to stack*/ + if(oSolver->token->type == OPERAND){ + stack_push(oSolver->operator_stack, oSolver->token); + } + else{ + /*Getting and operator, we proceed to solve the expressions a (operator) b*/ + + /* As stack is LIFO, b should pop first*/ + if(stack_size(oSolver->operator_stack) >= 2){ + b = (token_t *) stack_pop(oSolver->operator_stack); + a = (token_t *) stack_pop(oSolver->operator_stack); + } + /*Overwritting operator, now is an operand*/ + oSolver->token->token = __solve__(a->token, b->token, oSolver->token->token); + oSolver->token->type = OPERAND; + + /*Putting result again in the stack*/ + stack_push(oSolver->operator_stack, oSolver->token); + + /*As tokens were consumed, there is no need of them*/ + free(a); + free(b); + } + } + if(VERBOSE && SOLVER) + puts("[DEBUG] :: [SOLVER] :: Everything was solved"); + + if(totalTokens_g > 0){ + oSolver->token = stack_pop(oSolver->operator_stack); + /*Last token should have the final result*/ + oSolver->final_result = oSolver->token->token; + } + return oSolver->final_result; +} + +int solver_print(){ + /*This is only for aesthetcis, we cheeck if there were tokens*/ + if(totalTokens_g > 0){ + puts("\n:=-----------------::========::-----------------=:"); + puts(" :: :: :: :: :: :: :: RESULTS :: :: :: :: :: :: :: "); + puts(":=-----------------::========::-----------------=:\n"); + printf(" :: :: > > %d\n", oSolver->final_result); + } + return OK; +} \ No newline at end of file