/** * The expression class * serves as a container for * the tokens of an infix or * postfix expression. Once built * its contents are consumed as * they are extracted. * * @author Gary D. Brown * @version 1.1, 10/26/2005 * @since 03/15/2005 */ #include <queue> #include <stdexcept> #include <cstring> #include <iostream> #include <sstream> #include <string> class expression { public: expression() { } expression(std::istream&); expression(std::string); bool nextIsNumber(); bool nextIsOperator(); bool nextIsRight(); bool nextIsLeft(); bool hasNext(); double getNumber() throw (std::range_error); char getOperator() throw (std::range_error); char getParenthesis() throw (std::range_error); std::string nextToString(); void putNumber(double); void putOperator(char) throw (std::invalid_argument); void putParenthesis(char) throw (std::invalid_argument); void putExpression(std::ostream&); void putExpression(std::string&); private: bool isOperator(char); bool isParenthesis(char); struct entry { char type; union { double n; char c; } element; }; std::queue<entry> q; }; expression::expression(std::istream& in) { double n; char c; while (in && (c = in.peek()) != '\n') { if (isdigit(c) || c == '.') { in >> n; putNumber(n); } else if (isOperator(c)) { in >> c; putOperator(c); } else if (isParenthesis(c)) { in >> c; putParenthesis(c); } else in.ignore(); } if (in.peek() == '\n') in.ignore(); } expression::expression(std::string s) { double n; char c; std::istringstream in(s); while (in && (c = in.peek()) != '\n') { if (isdigit(c) || c == '.') { in >> n; putNumber(n); } else if (isOperator(c)) { in >> c; putOperator(c); } else if (isParenthesis(c)) { in >> c; putParenthesis(c); } else in.ignore(); } } bool expression::nextIsNumber() { return (q.front()).type == 'n'; } bool expression::nextIsOperator() { return (q.front()).type == 'o'; } bool expression::nextIsRight() { return (q.front()).type == 'r'; } bool expression::nextIsLeft() { return (q.front()).type == 'l'; } bool expression::hasNext() { return !q.empty(); } double expression::getNumber() throw (std::range_error) { entry ent = q.front(); if (ent.type == 'n') { q.pop(); return ent.element.n; } else throw std::range_error("Entry is not a number."); } char expression::getOperator() throw (std::range_error) { entry ent = q.front(); if (ent.type == 'o') { q.pop(); return ent.element.c; } else throw std::range_error("Entry is not an operator."); } char expression::getParenthesis() throw (std::range_error) { entry ent = q.front(); if (ent.type == 'l' || ent.type == 'r') { q.pop(); return ent.element.c; } else throw std::range_error("Entry is not a parenthesis."); } std::string expression::nextToString() { std::string s; std::ostringstream out(s); if (hasNext()) { entry ent = q.front(); out << "Next is "; switch (ent.type) { case 'n': out << "a number: " << ent.element.n; break; case 'o': out << "an operator: " << ent.element.c; break; case 'l': case 'r': out << "a parenthesis: " << ent.element.c; }} else out << "Expression is empty."; return out.str(); } void expression::putNumber(double n) { entry ent; ent.type = 'n'; ent.element.n = n; q.push(ent); } void expression::putOperator(char o) throw (std::invalid_argument) { if (isOperator(o)) { entry ent; ent.type = 'o'; ent.element.c = o; q.push(ent); } else throw std::invalid_argument("Character is not an operator."); } void expression::putParenthesis(char p) throw (std::invalid_argument) { if (isParenthesis(p)) { entry ent; ent.type = (p == '(') ? 'l' : 'r'; ent.element.c = p; q.push(ent); } else throw std::invalid_argument("Character is not a parenthesis."); } void expression::putExpression(std::ostream& out) { while (hasNext()) if (nextIsNumber()) out << getNumber(); else if (nextIsRight() || nextIsLeft()) out << getParenthesis(); else out << " " << getOperator() << " "; out << std::endl; } void expression::putExpression(std::string& s) { std::ostringstream out(s); while (hasNext()) { if (nextIsNumber()) out << getNumber(); else if (nextIsRight() || nextIsLeft()) out << getParenthesis(); else out << " " << getOperator() << " "; } out << std::endl; s = out.str(); } bool expression::isOperator(char o) { return std::strchr("+-*/", o) != NULL; } bool expression::isParenthesis(char p) { return std::strchr("()", p) != NULL; }