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;
}
Exemple #2
0
string Prototype::operator_name() const
{
    assert(is_unary() || is_binary());

    return name;//[name.size() - 1];
}
Exemple #3
0
bool TokenStream::is_binary() { return !is_unary() && !is_keyword();}
Exemple #4
0
/** 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;
   }
}