/*
* The implementation part of the class expr_stack
*/
#include <memory>
#include <list>
#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<Operand>(pop());
// Stack well-formed, but combine is canceled.
if(empty() || top()->is_left() ||
(prec_limit != -1 && top()->is_operator() &&
std::dynamic_pointer_cast<Operator>(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<Operator>(pop());
if(!top()->is_operand())
throw bad_expression("Operator lacks left operand.");
auto lf_opnd = std::dynamic_pointer_cast<Operand>(pop());
push(std::dynamic_pointer_cast<Operator>(optor)->operate
(lf_opnd, rt_opnd));
return true;
}