/*
expr --> ( expr ) | expr op expr | number
op --> + | - | * | /
number --> integer
integer --> integer digit | digit
digit --> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define SUCC 0
#define FAIL 1
#define YES 0
#define NO 1
#define EMPTY -1
#define STACK_LIMIT 80
typedef union data { char op; double value; } DATA;
typedef struct stack {
int type; /* 0: operator, 1: data */
DATA data;
int priority; } STACK_DATA;
struct stack STACK[STACK_LIMIT];
int STACK_TOP = EMPTY;
char expr[80];
int i = 0;
void push( STACK_DATA data )
{
if ( STACK_TOP < STACK_LIMIT - 1 )
STACK[++STACK_TOP] = data;
else
{
printf( "\nStack Overflow!!\n" );
exit( 1 );
}
}
STACK_DATA pop( void )
{
if ( STACK_TOP != EMPTY )
return( STACK[STACK_TOP--] );
else
{
printf( "\nStack Underflow!!\n" );
exit( 1 );
}
}
int number( void )
{
STACK_DATA data;
int k = 0, mantissa = NO;
char value[80];
while ( expr[i] >= '0' && expr[i] <= '9' ) /* integer */
{
mantissa = YES;
value[k++] = expr[i++];
}
value[k] = '\0';
data.type = 1;
data.data.value = atof( value );
data.priority = 0;
push( data );
return( SUCC );
}
int evaluate( void )
{
STACK_DATA data, data1, data2, opcode;
if ( STACK_TOP == EMPTY )
return( FAIL );
data1 = pop();
if ( data1.type != 1 )
return( FAIL ); /* not an operand */
if ( STACK_TOP == EMPTY )
return( FAIL );
opcode = pop();
if ( opcode.type != 0 )
return( FAIL ); /* not an operator */
if ( STACK_TOP == EMPTY )
return( FAIL );
data2 = pop();
if ( data2.type != 1 )
return( FAIL ); /* not an operand */
switch( opcode.data.op )
{
case '+' : data.data.value = data2.data.value + data1.data.value;
break;
case '-' : data.data.value = data2.data.value - data1.data.value;
break;
case '*' : data.data.value = data2.data.value * data1.data.value;
break;
case '/' : data.data.value = data2.data.value / data1.data.value;
break;
default: return( FAIL );
break;
}
data.type = 1;
data.priority = 0;
push( data );
return( SUCC );
}
int right_parenthesis( void )
{
STACK_DATA data;
while ( STACK_TOP != EMPTY )
{
if ( STACK_TOP-1 != EMPTY && STACK[STACK_TOP-1].data.op == '(' )
{
i++;
data = pop();
pop(); /* remove left parenthesis */
push( data );
return( SUCC );
}
else if ( evaluate() == FAIL )
return( FAIL );
}
return( FAIL );
}
int parenthesis( void )
{
STACK_DATA data;
data.type = 0;
data.data.op = expr[i++];
data.priority = 0; /* left_parenthesis */
push( data );
return( SUCC );
}
int op( void )
{
STACK_DATA data;
switch ( expr[i] )
{
case '+' :
case '-' : data.priority = 1;
break;
case '*' :
case '/' : data.priority = 2;
break;
default :
return( FAIL );
}
while ( STACK_TOP > 0 && data.priority <= STACK[STACK_TOP-1].priority )
{
if ( evaluate() == FAIL )
return( FAIL );
}
data.type = 0;
data.data.op = expr[i++];
push( data );
return( SUCC );
}
int expression( void )
{
while ( expr[i] == ' ' ) /* skip the leading spaces */
i++;
if ( expr[i] == '(' )
return( parenthesis() ); /* ( expr) */
if ( expr[i] == '+' || expr[i] == '-' || expr[i] == '*' || expr[i] == '/' )
return( op() ); /* expr op expr */
if ( expr[i] >= '0' && expr[i] <= '9' )
return( number() ); /* number */
if ( expr[i] == ')') /* end of parenthesis */
return( right_parenthesis() );
if ( expr[i] == '\0') /* end of expression */
return( SUCC );
else
return( FAIL );
}
int result( void )
{
while ( STACK_TOP > 0 )
{
if ( evaluate() == FAIL )
return( FAIL );
}
return( SUCC );
}
void calculate( void )
{
STACK_DATA data;
while ( expr[i] != '\0' )
{
if ( expression() == FAIL ) /* parse the exspression */
break;
}
if ( expr[i] == '\0' ) /* end of expression */
{
if ( result() == SUCC && STACK_TOP == 0 )
{
data = pop();
if ( data.type == 1 )
printf( "The result is %g\n", data.data.value );
else
printf( "Error : Illegal expression\n" );
}
else
printf( "Error : Illegal expression\n" );
}
else
printf( "Error : Illegal expression\n" );
}
void init( void )
{
STACK_TOP = EMPTY; /* clear stack */
i = 0;
}
int main( void )
{
char ch;
do
{
init(); /* initialize */
printf( "Please keyin expression to be evaluated \n" );
fflush( stdin );
gets( expr );
calculate();
printf( "Continue (y/n) ? " );
ch = getchar();
} while( !( ch == 'n' || ch == 'N' ) );
return( 0 );
}
LyoKCWV4cHIgLS0+ICggZXhwciApIHwgZXhwciBvcCBleHByIHwgbnVtYmVyCglvcCAtLT4gKyB8IC0gfCAqIHwgLwoJbnVtYmVyIC0tPiBpbnRlZ2VyCglpbnRlZ2VyIC0tPiBpbnRlZ2VyIGRpZ2l0IHwgZGlnaXQKCWRpZ2l0IC0tPiAwIHwgMSB8IDIgfCAzIHwgNCB8IDUgfCA2IHwgNyB8IDggfCA5CiovCiNpbmNsdWRlIDxzdGRpby5oPgojaW5jbHVkZSA8c3RkbGliLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4KI2luY2x1ZGUgPG1hdGguaD4KCiNkZWZpbmUgU1VDQyAwCiNkZWZpbmUgRkFJTCAxCiNkZWZpbmUgWUVTIDAKI2RlZmluZSBOTyAxCiNkZWZpbmUgRU1QVFkgLTEKI2RlZmluZSBTVEFDS19MSU1JVCA4MAoKdHlwZWRlZiB1bmlvbiBkYXRhIHsgY2hhciBvcDsgZG91YmxlIHZhbHVlOyB9IERBVEE7Cgp0eXBlZGVmIHN0cnVjdCBzdGFjayB7CglpbnQgdHlwZTsJCQkJCQkJCS8qIDA6IG9wZXJhdG9yLCAxOiBkYXRhICovCglEQVRBIGRhdGE7CglpbnQgcHJpb3JpdHk7IH0gU1RBQ0tfREFUQTsKCnN0cnVjdCBzdGFjayBTVEFDS1tTVEFDS19MSU1JVF07CmludCBTVEFDS19UT1AgPSBFTVBUWTsKCmNoYXIgZXhwcls4MF07CmludCBpID0gMDsKCgp2b2lkIHB1c2goIFNUQUNLX0RBVEEgZGF0YSApCgp7CiAgaWYgKCBTVEFDS19UT1AgPCBTVEFDS19MSU1JVCAtIDEgKQogICAgU1RBQ0tbKytTVEFDS19UT1BdID0gZGF0YTsKICBlbHNlCiAgewogICAgcHJpbnRmKCAiXG5TdGFjayBPdmVyZmxvdyEhXG4iICk7CiAgICBleGl0KCAxICk7CiAgfQp9CgpTVEFDS19EQVRBIHBvcCggdm9pZCApCgp7CiAgaWYgKCBTVEFDS19UT1AgIT0gRU1QVFkgKQogICAgcmV0dXJuKCBTVEFDS1tTVEFDS19UT1AtLV0gKTsKICBlbHNlCiAgewogICAgcHJpbnRmKCAiXG5TdGFjayBVbmRlcmZsb3chIVxuIiApOwogICAgZXhpdCggMSApOwogIH0KfQoKaW50IG51bWJlciggdm9pZCApCgp7CglTVEFDS19EQVRBIGRhdGE7CglpbnQgayA9IDAsIG1hbnRpc3NhID0gTk87CgljaGFyIHZhbHVlWzgwXTsKCgl3aGlsZSAoIGV4cHJbaV0gPj0gJzAnICYmIGV4cHJbaV0gPD0gJzknICkJCS8qIGludGVnZXIgKi8KCXsKCQltYW50aXNzYSA9IFlFUzsKCQl2YWx1ZVtrKytdID0gZXhwcltpKytdOwoJfQoKCXZhbHVlW2tdID0gJ1wwJzsKCglkYXRhLnR5cGUgPSAxOwoJZGF0YS5kYXRhLnZhbHVlID0gYXRvZiggdmFsdWUgKTsKCWRhdGEucHJpb3JpdHkgPSAwOwoJcHVzaCggZGF0YSApOwoKCXJldHVybiggU1VDQyApOwp9CgppbnQgZXZhbHVhdGUoIHZvaWQgKQoKewoJU1RBQ0tfREFUQSBkYXRhLCBkYXRhMSwgZGF0YTIsIG9wY29kZTsKCglpZiAoIFNUQUNLX1RPUCA9PSBFTVBUWSApCgkJcmV0dXJuKCBGQUlMICk7CglkYXRhMSA9IHBvcCgpOwoJaWYgKCBkYXRhMS50eXBlICE9IDEgKQoJCXJldHVybiggRkFJTCApOwkJCQkvKiBub3QgYW4gb3BlcmFuZCAqLwoKCWlmICggU1RBQ0tfVE9QID09IEVNUFRZICkKCQlyZXR1cm4oIEZBSUwgKTsKCW9wY29kZSA9IHBvcCgpOwoJaWYgKCBvcGNvZGUudHlwZSAhPSAwICkKCQlyZXR1cm4oIEZBSUwgKTsJCQkJLyogbm90IGFuIG9wZXJhdG9yICovCgoJaWYgKCBTVEFDS19UT1AgPT0gRU1QVFkgKQoJCXJldHVybiggRkFJTCApOwoJZGF0YTIgPSBwb3AoKTsKCWlmICggZGF0YTIudHlwZSAhPSAxICkKCQlyZXR1cm4oIEZBSUwgKTsJCQkJLyogbm90IGFuIG9wZXJhbmQgKi8KCglzd2l0Y2goIG9wY29kZS5kYXRhLm9wICkKCXsKCQljYXNlICcrJyA6IGRhdGEuZGF0YS52YWx1ZSA9IGRhdGEyLmRhdGEudmFsdWUgKyBkYXRhMS5kYXRhLnZhbHVlOwoJCQlicmVhazsKCQljYXNlICctJyA6IGRhdGEuZGF0YS52YWx1ZSA9IGRhdGEyLmRhdGEudmFsdWUgLSBkYXRhMS5kYXRhLnZhbHVlOwoJCQlicmVhazsKCQljYXNlICcqJyA6IGRhdGEuZGF0YS52YWx1ZSA9IGRhdGEyLmRhdGEudmFsdWUgKiBkYXRhMS5kYXRhLnZhbHVlOwoJCQlicmVhazsKCQljYXNlICcvJyA6IGRhdGEuZGF0YS52YWx1ZSA9IGRhdGEyLmRhdGEudmFsdWUgLyBkYXRhMS5kYXRhLnZhbHVlOwoJCQlicmVhazsKCQlkZWZhdWx0OiByZXR1cm4oIEZBSUwgKTsKCQkJYnJlYWs7Cgl9CgoJZGF0YS50eXBlID0gMTsKCWRhdGEucHJpb3JpdHkgPSAwOwoJcHVzaCggZGF0YSApOwoKCXJldHVybiggU1VDQyApOwp9CgppbnQgcmlnaHRfcGFyZW50aGVzaXMoIHZvaWQgKQoKewoJU1RBQ0tfREFUQSBkYXRhOwoKCXdoaWxlICggU1RBQ0tfVE9QICE9IEVNUFRZICkKCXsKCQlpZiAoIFNUQUNLX1RPUC0xICE9IEVNUFRZICYmIFNUQUNLW1NUQUNLX1RPUC0xXS5kYXRhLm9wID09ICcoJyApCgkJewoJCQlpKys7CgkJCWRhdGEgPSBwb3AoKTsJCQkJCQkKCQkJcG9wKCk7CQkJCQkJCQkvKiByZW1vdmUgbGVmdCBwYXJlbnRoZXNpcyAqLwoJCQlwdXNoKCBkYXRhICk7CgkJCXJldHVybiggU1VDQyApOwoJCX0KCQllbHNlIGlmICggZXZhbHVhdGUoKSA9PSBGQUlMICkKCQkJcmV0dXJuKCBGQUlMICk7Cgl9CgoJcmV0dXJuKCBGQUlMICk7Cn0KCmludCBwYXJlbnRoZXNpcyggdm9pZCApCnsKCVNUQUNLX0RBVEEgZGF0YTsKCglkYXRhLnR5cGUgPSAwOwoJZGF0YS5kYXRhLm9wID0gZXhwcltpKytdOwoJZGF0YS5wcmlvcml0eSA9IDA7CQkJCQkJLyogbGVmdF9wYXJlbnRoZXNpcyAqLwoJcHVzaCggZGF0YSApOwkKCglyZXR1cm4oIFNVQ0MgKTsKfQoKaW50IG9wKCB2b2lkICkKewoJU1RBQ0tfREFUQSBkYXRhOwoKCXN3aXRjaCAoIGV4cHJbaV0gKQoJewoJCWNhc2UgJysnIDoKCQljYXNlICctJyA6IGRhdGEucHJpb3JpdHkgPSAxOwoJCQlicmVhazsKCQljYXNlICcqJyA6CgkJY2FzZSAnLycgOiBkYXRhLnByaW9yaXR5ID0gMjsKCQkJYnJlYWs7CgkJZGVmYXVsdCA6CgkJCXJldHVybiggRkFJTCApOwoJfQoKCXdoaWxlICggU1RBQ0tfVE9QID4gMCAmJiBkYXRhLnByaW9yaXR5IDw9IFNUQUNLW1NUQUNLX1RPUC0xXS5wcmlvcml0eSApCgl7CgkJaWYgKCBldmFsdWF0ZSgpID09IEZBSUwgKQoJCQlyZXR1cm4oIEZBSUwgKTsKCX0KCglkYXRhLnR5cGUgPSAwOwoJZGF0YS5kYXRhLm9wID0gZXhwcltpKytdOwoJcHVzaCggZGF0YSApOwoKCXJldHVybiggU1VDQyApOwp9CgppbnQgZXhwcmVzc2lvbiggdm9pZCApCnsKCXdoaWxlICggZXhwcltpXSA9PSAnICcgKQkJCQkvKiBza2lwIHRoZSBsZWFkaW5nIHNwYWNlcyAqLwoJCWkrKzsKCiAgICBpZiAoIGV4cHJbaV0gPT0gJygnICkKIAkJcmV0dXJuKCBwYXJlbnRoZXNpcygpICk7CQkJLyogKCBleHByKSAqLwoKICAgIGlmICggZXhwcltpXSA9PSAnKycgfHwgZXhwcltpXSA9PSAnLScgfHwgZXhwcltpXSA9PSAnKicgfHwgZXhwcltpXSA9PSAnLycgKQoJCXJldHVybiggb3AoKSApOwkJCQkJCS8qIGV4cHIgb3AgZXhwciAqLwoKCWlmICggZXhwcltpXSA+PSAnMCcgJiYgZXhwcltpXSA8PSAnOScJKQkKCQlyZXR1cm4oIG51bWJlcigpICk7CQkJCQkvKiBudW1iZXIgKi8KCglpZiAoIGV4cHJbaV0gPT0gJyknKQkJCQkJLyogZW5kIG9mIHBhcmVudGhlc2lzICovCgkJcmV0dXJuKCByaWdodF9wYXJlbnRoZXNpcygpICk7CgoJaWYgKCBleHByW2ldID09ICdcMCcpCQkJCQkvKiBlbmQgb2YgZXhwcmVzc2lvbiAqLwoJCXJldHVybiggU1VDQyApOwoJZWxzZQoJCXJldHVybiggRkFJTCApOwp9CgppbnQgcmVzdWx0KCB2b2lkICkKCnsKCXdoaWxlICggU1RBQ0tfVE9QID4gMCApCgl7CgkJaWYgKCBldmFsdWF0ZSgpID09IEZBSUwgKQoJCQlyZXR1cm4oIEZBSUwgKTsKCX0KCglyZXR1cm4oIFNVQ0MgKTsKfQoKdm9pZCBjYWxjdWxhdGUoIHZvaWQgKQp7CglTVEFDS19EQVRBIGRhdGE7CgoJd2hpbGUgKCBleHByW2ldICE9ICdcMCcgKQoJewoJCWlmICggZXhwcmVzc2lvbigpID09IEZBSUwgKQkJLyogcGFyc2UgdGhlIGV4c3ByZXNzaW9uICovCgkJCWJyZWFrOwoJfQoKCWlmICggZXhwcltpXSA9PSAnXDAnICkJLyogZW5kIG9mIGV4cHJlc3Npb24gKi8KICAgIHsKCQlpZiAoIHJlc3VsdCgpID09IFNVQ0MgJiYgU1RBQ0tfVE9QID09IDAgKQoJCXsKCQkJZGF0YSA9IHBvcCgpOwoJCQlpZiAoIGRhdGEudHlwZSA9PSAxICkKCQkJCXByaW50ZiggIlRoZSByZXN1bHQgaXMgJWdcbiIsIGRhdGEuZGF0YS52YWx1ZSApOwoJCQllbHNlCgkJCQlwcmludGYoICJFcnJvciA6IElsbGVnYWwgZXhwcmVzc2lvblxuIiApOwogCQl9CgkJZWxzZQoJCQlwcmludGYoICJFcnJvciA6IElsbGVnYWwgZXhwcmVzc2lvblxuIiApOwogICAgfQoJZWxzZQoJCXByaW50ZiggIkVycm9yIDogSWxsZWdhbCBleHByZXNzaW9uXG4iICk7Cn0KCnZvaWQgaW5pdCggdm9pZCApCnsKCVNUQUNLX1RPUCA9IEVNUFRZOyAgIC8qIGNsZWFyIHN0YWNrICovCglpID0gMDsKfQoKaW50IG1haW4oIHZvaWQgKQp7CgljaGFyIGNoOwoKCWRvCgl7CgkJaW5pdCgpOwkJCQkvKiBpbml0aWFsaXplICovCgkJCgkJcHJpbnRmKCAiUGxlYXNlIGtleWluIGV4cHJlc3Npb24gdG8gYmUgZXZhbHVhdGVkIFxuIiApOwoJCWZmbHVzaCggc3RkaW4gKTsKCQlnZXRzKCBleHByICk7CgoJCWNhbGN1bGF0ZSgpOwoKCQlwcmludGYoICJDb250aW51ZSAoeS9uKSA/ICIgKTsKCQljaCA9IGdldGNoYXIoKTsKCX0gd2hpbGUoICEoIGNoID09ICduJyB8fCBjaCA9PSAnTicgKSApOwoJCglyZXR1cm4oIDAgKTsKfQ==