/***************************************************************************
* Copyright (C) 2008 by Mattia Bondanza *
* mattia.bond@gmail.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "solver.h"
typedef struct stackN{//PILA DI CARATTERI USATA IN 'convert'
int val;
struct stackN *nextPrt;
}stack_char;
typedef stack_char *stack_charPrt;
typedef struct stack1{//PILA DI DOUBLE USATA IN 'solve'
int val;
struct stack1 *nextPrt;
}stack;
typedef stack *stackPrt;
void _push( stack_charPrt *stack, char value ){//PUSH PER PILA DI CARATTERI
stack_charPrt node = malloc( sizeof( stack_char ) );
if( node == NULL ){
exit( EXIT_FAILURE );
}
node->nextPrt = *stack;
node->val = value;
*stack = node;
}
char _pop( stack_charPrt *stack ){//POP PER PILA DI CARATTERI
if( stack == NULL ){
exit( EXIT_FAILURE );
}
stack_charPrt tmp = *stack;
char out = ( tmp )->val;
*stack = ( tmp )->nextPrt;
free( tmp );
return out;
}
void push( stackPrt *stack, int value ){//PUSH PER PILA DI DOUBLE
stackPrt node = malloc( sizeof( stack ) );
if( node == NULL ){
exit( EXIT_FAILURE );
}
node->nextPrt = *stack;
node->val = value;
*stack = node;
}
int pop( stackPrt *stack ){//POP PER PILA DI DOUBLE
if( stack == NULL ){
exit( EXIT_FAILURE );
}
stackPrt tmp = *stack;
int out = ( tmp )->val;
*stack = ( tmp )->nextPrt;
free( tmp );
return out;
}
int isOperator( char c ){
if( c == '+'||c == '-'||c == '*'||c == '/'||c == '^'||c == '%' )return 1;
else return 0;
}
int priority( char a, char b ){
int a1, b1;
switch( a ){
case '+':
case '-':
a1 = 1;
break;
case '*':
case '/':
case '%':
a1 = 2;
break;
case '^':
a1 = 3;
break;
case '(':
a1 = 0;
}
switch( b ){
case '+':
case '-':
b1 = 1;
break;
case '*':
case '/':
case '%':
b1 = 2;
break;
case '^':
b1 = 3;
break;
case '(':
b1 = 0;
}
return b1-a1;
}
void convert( char input[], char output[] ){
int i, j;
stack_charPrt stack;
_push( &stack, '(' );
for( i = 0; input[ i ] != '\0'; i++ );
input[ i ] = ')';
input[ ++i ] = '\0';
for( i = 0, j = 0; input[ i ] != '\0'; i++){
if( isdigit( input[ i ] ) || isalpha( input[i ] )){
output[ j++ ] = input[ i ];
while( isdigit( input[ i + 1 ] ) || isVariantch(input[i+1]) )
output[ j++ ] = input[ ++i ];
output[ j++ ] = ' ';
}
else if( input[ i ] == '(' ){
_push( &stack, '(' );
}
else if( isOperator( input[ i ] ) ){
while( priority( input[ i ], stack->val ) >= 0 ){
output[ j++ ] = _pop( &stack );
output[ j++ ] = ' ' ;
}
_push( &stack, input[ i ] );
}
else if( input[ i ] == ')' ){
while( stack->val != '(' ){
output[ j++ ] = _pop( &stack );
output[ j++ ] = ' ';
}
_pop( &stack );
}
}
output[ j ] ='\0';
}
int solve( char in[] ){
stackPrt stack;
int i, frst=0;
char input[500], tmp[500];
strcpy(tmp, in);
convert(tmp, input);
for( i = 0; input[ i ] != '\0'; i++ ){
if(input[i]=='p'&&input[i+1]=='i'){
push(&stack, M_PI);
i+=2;
}
else if( isdigit( input[ i ] ) ){
char numero[ 20 ];
int k = 1;
numero[ 0 ] = input[ i ];
while( isdigit( input[ i + 1 ] ) )
numero[ k++ ] = input[ ++i ];
numero[k]='\0';
push( &stack, ricerca( 1, atoi( numero ), "", 0 ) );
}
else if( isalpha( input[ i ] ) ){
char variant[50], indice[50];
int k =0, cnt0=0, isarray=0;
while( isVariantch( input[ i ] ) ){
variant[k++]=input[i++];
}
variant[k]='\0';
push( &stack, ricerca( 0, 0, variant, 0 ) );
}
else if( isOperator( input[ i ] ) ){
int ftc;
int b;
b = pop( &stack );
int a = pop( &stack );
fprintf( output, "%.5d 20%.5d\n", line_out++, a );
switch( input[ i ] ){
case '+':
fprintf( output, "%.5d 30%.5d\n", line_out++, b );
fprintf( output, "%.5d 21%.5d\n", line_out++, location_cnt-- );
push( &stack, location_cnt+1);
break;
case '-':
fprintf( output, "%.5d 31%.5d\n", line_out++, b );
fprintf( output, "%.5d 21%.5d\n", line_out++, location_cnt-- );
push( &stack, location_cnt+1);
break;
case '*':
fprintf( output, "%.5d 33%.5d\n", line_out++, b );
fprintf( output, "%.5d 21%.5d\n", line_out++, location_cnt-- );
push( &stack, location_cnt+1);
break;
case '/':
fprintf( output, "%.5d 32%.5d\n", line_out++, b );
fprintf( output, "%.5d 21%.5d\n", line_out++, location_cnt-- );
push( &stack, location_cnt+1);;
break;
case '^':
fprintf( output, "%.5d 35%.5d\n", line_out++, b );
fprintf( output, "%.5d 21%.5d\n", line_out++, location_cnt-- );
push( &stack, location_cnt+1);
break;
case '%':
fprintf( output, "%.5d 34%.5d\n", line_out++, b );
fprintf( output, "%.5d 21%.5d\n", line_out++, location_cnt-- );
push( &stack, location_cnt+1);
break;
}
}
}
return pop( &stack );
}