/* * The implementation part of the class expr_stack */ #include #include #include "expr_stack.h" #include "expression_parts.h" /* * Private helper function for expr_stack. This takes the operand, operator, * operand on the stack top, applies the operator, and replaces the three * with the result. The method throws an excpetion if the top part of the * stack does not have one of the following forms: * o operand as the only member of the stack. * o operand ( ... * o operand operator operand ... * The merge is canceled and false is returned, if: * o The stack has the first or second form. * o The prec_limit is given (not -1) and the operator has a lower * precedence. * The parameter, prec_limit means "precedence limit," and is used to end a * series of operations when a lower precedence operator is reached. For * instance, if a series of adjacent multiplies are being reduced, the * prec_limit will be the precedence for multiply. If the next operator is * add, the merge will be cancelled. */ bool expr_stack::merge_top(int prec_limit) { // Get the first operand. if(!top()->is_operand()) throw bad_expression("Missing operand."); auto rt_opnd = std::dynamic_pointer_cast(pop()); // Stack well-formed, but combine is canceled. if(empty() || top()->is_left() || (prec_limit != -1 && top()->is_operator() && std::dynamic_pointer_cast(top())->prec() < prec_limit)) { // Not going to merge. Put that operand back and bail out. push(rt_opnd); return false; } if(top()->is_operand()) throw bad_expression("Successive operands."); if(!top()->is_operator()) throw bad_expression("Operator Expected"); // Perform the combination. auto optor = std::dynamic_pointer_cast(pop()); if(!top()->is_operand()) throw bad_expression("Operator lacks left operand."); auto lf_opnd = std::dynamic_pointer_cast(pop()); push(std::dynamic_pointer_cast(optor)->operate (lf_opnd, rt_opnd)); return true; }