// =================================================================================== // A. Fischer, June 9, 2002 file: eval.cpp // #include "eval.hpp" #include "operator.hpp" // ---------------------------------------------------- Instructions for the operator. void Eval::instructions( void ){ cout << "This is an infix expression evaluator.\n" << "* Operands start with a digit and may or may not have a decimal point.\n" << "* Operands must not exceed 31 keystrokes.\n" << "* All operators are binary operators. Parentheses are not supported.\n" << "* Operators are: +, -, *, /, % (a mod b) and ^ (a to the power b).\n" << "* Whitespace must be used to delimit both operators and operands.\n" << "* End each expression with a semicolon.\n\n" << "To quit, type semicolon instead of an expression.\n"; } //------------------------------------------------ Read input and evaluate expression. double Eval::evaluate( istream& in ) { Intype next; // Classification of next input character. Operator inOp; // Operator object constructed from inSymbol. double inNum; // Read input operands into this. char ch; for(;;) { in >> ws >>ch; if (in.eof()) next = end; else next = classify( ch ); switch( next ){ case number: in.putback(ch); in >> inNum; if ( Ands.depth() != Ators.depth() ) return expError(); Ands.push( inNum ); break; case op: inOp = Operator(ch); if ( Ands.depth() != Ators.depth()+1 ) return expError(); force( inOp.precedence() ); Ators.push( inOp ); break; case end: if ( Ands.depth() != Ators.depth()+1 ) return expError(); force( 0 ); return Ands.pop(); break; case bad: default: return expError(); } } } // -------------------------------- Evaluate all higher precedence operators on stack. void Eval::force( int rprec ) { while( Ators.depth()>0 && Ators.top().precedence() >= rprec ) dispatch(); } //---------- Decide whether next input char is an operator, a semicolon, the beginning Eval::Intype // of an operand, or garbage. Eval::classify( char ch ){ if (isdigit( ch )) return number; switch(ch){ case '+': case '-': case '*': case '/': case '%': case '^': return op; case ';': return end; default : return bad; } } // ------------------------------------------------------------ Evaluate one operator. void Eval::dispatch() { double result; double right = Ands.pop(); double left = Ands.pop(); Operator op = Ators.pop(); switch (op.symbol()) { case '+': result = left + right; break; case '-': result = left - right; break; case '*': result = left * right; break; case '/': result = left / right; break; case '%': result = fmod(left, right); break; case '^': result = pow (left, right); break; default : result = NAN; break; } Ands.push( result ); } // ------------------------------------------------------------------- Error comments. double Eval::expError(){ cout << "\tIllegal expression.\n"; print(cout); return HUGE_VAL; } // ----------------------------------------------------------------- Print the stacks. ostream& Eval::print( ostream& out ){ out << "\tRemaining contents of operator stack: "; out << "\tRemaining contents of operand stack: " <