SymbolListPtr CodeBlock::convert_postfix(SymbolListPtr p) { // data structs unique_ptr<stack<SymbolPtr>> op_stack = unique_ptr<stack<SymbolPtr>>(new stack<SymbolPtr>); SymbolListPtr unpostfix_symbols = SymbolListPtr(new SymbolList()); // shunting yard (modified for unary operators!) for (auto i = p->begin(); i != p->end(); i++) { if (is_operand(*i)) { unpostfix_symbols->push_back(*i); if (!op_stack->empty()) { if (is_unary(op_stack->top())) { unpostfix_symbols->push_back(op_stack->top()); op_stack->pop(); } } } else if (is_operator(*i)) { if (is_unary((*i))) { op_stack->push(*i); } else { while (!op_stack->empty() && !is_lparen(op_stack->top()) && compare_ops(*i, op_stack->top()) <= 0) { unpostfix_symbols->push_back(op_stack->top()); op_stack->pop(); } op_stack->push(*i); } } else if (is_lparen(*i)) { op_stack->push(*i); } else if (is_rparen(*i)) { while (!op_stack->empty()) { if (is_lparen(op_stack->top())) { op_stack->pop(); if (!op_stack->empty()) { if (is_unary(op_stack->top())) { unpostfix_symbols->push_back(op_stack->top()); op_stack->pop(); } } break; } unpostfix_symbols->push_back(op_stack->top()); op_stack->pop(); } } } while(!op_stack->empty()) { unpostfix_symbols->push_back(op_stack->top()); op_stack->pop(); } // set the temp symbols as the postfix stuff return unpostfix_symbols; }
string Prototype::operator_name() const { assert(is_unary() || is_binary()); return name;//[name.size() - 1]; }
bool TokenStream::is_binary() { return !is_unary() && !is_keyword();}
/** Take a string (hopefully) containing an operator and either push it to the stack or eval it depending on precedence. **/ int handle_op ( const char* op_str, Stack* op_stack, Stack* num_stack) { #if DEBUG==1 cout << "Handling operator '" << op_str << "'." << endl; #endif op_code new_op = -1; if (! (0 == op_str_len)) { new_op = parse_operator (op_str, op_str_len, check_unm); #if DEBUG==1 cout << "Operator code is: " << new_op << endl; #endif if (new_op == OP_CODE_ERR) { return PARSER_STATUS_NOP; } else { #if DEBUG==1 cout << "Comparing previous op, '" << op_stack -> top() << "' with new op '" << new_op << "'." << endl; cout << "Precedence is: " << compare_prec (new_op, op_stack -> top() ) << endl; #endif /* Only do if holding a low-precedence operator: */ while ((op_stack -> top() != OP_CODE_END) && !compare_prec (new_op, op_stack -> top()) ) { double R_arg = num_stack -> top(); num_stack -> pop(); double L_arg = 0; if ( !is_unary ( op_stack -> top() ) ) { if( num_stack -> empty() ) { cerr << "Operations remain but not enough numbers to " "evaluate." << endl; return PARSER_STATUS_SYNTAX; } #if DEBUG==1 cout << "Operator is binary." <<endl; #endif L_arg = num_stack -> top(); num_stack -> pop(); } double result = perform_op ( L_arg, R_arg, op_stack -> top(), status ); last_result = result; op_stack -> pop(); #if DEBUG==1 cout << "Result is: " << result << endl; #endif num_stack -> push (result); } /* As long as we're not holding a right-paren */ if (new_op != OP_CODE_RPN) { #if DEBUG==1 cout << "Pushing operator '" << new_op << "' to stack."<<endl; #endif op_stack -> push( new_op ); } /* only LPN has higher prec than RPN. Eliminate it. */ else if ( OP_CODE_LPN == op_stack -> top() ) { op_stack -> pop(); } #if DEBUG==1 if( !op_stack -> empty() ) cout << "Next up on stack: " << op_stack -> top() << endl; #endif } } return PARSER_STATUS_GOOD; }
/* add_operator: * Processes a new operator from the input string. */ static void add_operator(char op) { /* bodge for unary negation */ if ((op == OP_MINUS) && (!current_valid)) op = OP_NEGATE; /* check validity */ if ((op == OP_PLUS) || (op == OP_MINUS) || (op == OP_MUL) || (op == OP_DIV) || (op == OP_POWER) || (op == OP_MOD) || (op == OP_EQUALS) || (op == OP_NOT_EQUALS) || (op == OP_LESS) || (op == OP_GREATER) || (op == OP_LESS_EQUALS) || (op == OP_GREATER_EQUALS) || (op == OP_OR) || (op == OP_AND)) { if (!current_valid) { evaluate_error = TRUE; return; } } /* evaluate */ if (op != OP_OPEN_PAREN) { while ((stack_depth > 0) && ((precedence(op) <= precedence(operator_stack[stack_depth-1]) && (!is_unary(operator_stack[stack_depth-1]))) || (precedence(op) < precedence(operator_stack[stack_depth-1]) && (is_unary(operator_stack[stack_depth-1]))))) { stack_depth--; switch (operator_stack[stack_depth]) { case OP_PLUS: current_val = value_stack[stack_depth] + current_val; break; case OP_MINUS: current_val = value_stack[stack_depth] - current_val; break; case OP_MUL: current_val = value_stack[stack_depth] * current_val; break; case OP_DIV: if (current_val != 0) current_val = value_stack[stack_depth] / current_val; else current_val = 0; break; case OP_POWER: current_val = pow(value_stack[stack_depth], current_val); break; case OP_NEGATE: current_val = -current_val; break; case OP_SQRT: if (current_val >= 0) current_val = sqrt(current_val); else current_val = 0; break; case OP_SIN: current_val = sin(DEG2RAD(current_val)); break; case OP_COS: current_val = cos(DEG2RAD(current_val)); break; case OP_TAN: current_val = tan(DEG2RAD(current_val)); break; case OP_ASIN: if ((current_val >= -1) && (current_val <= 1)) current_val = RAD2DEG(asin(current_val)); else current_val = 0; break; case OP_ACOS: if ((current_val >= -1) && (current_val <= 1)) current_val = RAD2DEG(acos(current_val)); else current_val = 0; break; case OP_ATAN: current_val = RAD2DEG(atan(current_val)); break; case OP_LOG: if (current_val > 0) current_val = log10(current_val); else current_val = 0; break; case OP_LN: if (current_val > 0) current_val = log(current_val); else current_val = 0; break; case OP_CEIL: current_val = ceil(current_val); break; case OP_FLOOR: current_val = floor(current_val); break; case OP_ROUND: if (current_val < 0) current_val = (int)(current_val - 0.5); else current_val = (int)(current_val + 0.5); break; case OP_ABS: current_val = fabs(current_val); break; case OP_MOD: if (current_val >= 1) current_val = fmod(value_stack[stack_depth], current_val); else current_val = 0; break; case OP_EQUALS: current_val = (value_stack[stack_depth] == current_val); break; case OP_NOT_EQUALS: current_val = (value_stack[stack_depth] != current_val); break; case OP_LESS: current_val = (value_stack[stack_depth] < current_val); break; case OP_GREATER: current_val = (value_stack[stack_depth] > current_val); break; case OP_LESS_EQUALS: current_val = (value_stack[stack_depth] <= current_val); break; case OP_GREATER_EQUALS: current_val = (value_stack[stack_depth] >= current_val); break; case OP_OR: current_val = ((int)value_stack[stack_depth] || (int)current_val); break; case OP_AND: current_val = ((int)value_stack[stack_depth] && (int)current_val); break; case OP_NOT: current_val = !(int)current_val; break; case OP_OPEN_PAREN: if (op == OP_CLOSE_PAREN) return; break; } } } /* push onto the stack */ if (op != OP_CLOSE_PAREN) { operator_stack[stack_depth] = op; value_stack[stack_depth] = current_val; stack_depth++; current_val = 0; current_valid = FALSE; } else { if (stack_depth <= 0) evaluate_error = TRUE; } }