예제 #1
0
void Expr::Reduce(void) {
    Expr *a, *b;

    Expr *op = PopOperator();
    Expr *n;
    int o;
    switch(op->c) {
        case '+': o = PLUS;  goto c;
        case '-': o = MINUS; goto c;
        case '*': o = TIMES; goto c;
        case '/': o = DIV;   goto c;
c:
            b = PopOperand();
            a = PopOperand();
            n = a->AnyOp(o, b);
            break;

        case 'n': n = PopOperand()->Negate(); break;
        case 'q': n = PopOperand()->Sqrt(); break;
        case 's': n = (PopOperand()->Times(Expr::From(PI/180)))->Sin(); break;
        case 'c': n = (PopOperand()->Times(Expr::From(PI/180)))->Cos(); break;

        default: oops();
    }
    PushOperand(n);
}
예제 #2
0
void Expr::Parse(void) {
    Expr *e = AllocExpr();
    e->op = ALL_RESOLVED;
    PushOperator(e);

    for(;;) {
        Expr *n = Next();
        if(!n) throw "end of expression unexpected";

        if(n->op == CONSTANT) {
            PushOperand(n);
            Consume();
        } else if(n->op == PAREN && n->c == '(') {
            Consume();
            Parse();
            n = Next();
            if(n->op != PAREN || n->c != ')') throw "expected: )";
            Consume();
        } else if(n->op == UNARY_OP) {
            PushOperator(n);
            Consume();
            continue;
        } else if(n->op == BINARY_OP && n->c == '-') {
            // The minus sign is special, because it might be binary or
            // unary, depending on context.
            n->op = UNARY_OP;
            n->c = 'n';
            PushOperator(n);
            Consume();
            continue;
        } else {
            throw "expected expression";
        }

        n = Next();
        if(n && n->op == BINARY_OP) {
            ReduceAndPush(n);
            Consume();
        } else {
            break;
        }
    }

    while(TopOperator()->op != ALL_RESOLVED) {
        Reduce();
    }
    PopOperator(); // discard the ALL_RESOLVED marker
}
예제 #3
0
 //------------------------------------------------------------------------------
 void Evaluator::ApplyUntilLeftParen(bool discardParen)
 {
   while (!operatorStack.empty())
   {
     Token token = PopOperator();
     if (token.type == Token::Type::LeftParen)
     {
       if (!discardParen)
         operatorStack.push_back(token);
       break;
     }
     else
     {
       ApplyBinOp(token.binOp);
     }
   }
 }
예제 #4
0
  //------------------------------------------------------------------------------
  float Evaluator::Evaluate(const vector<Token>& expression, const Environment* env)
  {

    // Now perform the actual shunting :)
    for (size_t i = 0; i < expression.size(); ++i)
    {
      const Token& t = expression[i];

      if (t.type == Token::Type::Constant)
      {
        operandStack.push_back(t);
      }
      else if (t.type == Token::Type::BinOp)
      {
        // Apply any higher priority operators
        int prio = BINOP_PRIO[t.binOp];
        while (!operatorStack.empty())
        {
          const Token& op = operatorStack.back();
          if (op.type == Token::Type::BinOp && BINOP_PRIO[op.binOp] >= prio)
          {
            ApplyBinOp(op.binOp);
            operatorStack.pop_back();
          }
          else
            break;
        }

        operatorStack.push_back(t);
      }
      else if (t.type == Token::Type::FuncCall)
      {
        operatorStack.push_back(t);
      }
      else if (t.type == Token::Type::LeftParen)
      {
        operatorStack.push_back(t);
      }
      else if (t.type == Token::Type::Comma)
      {
        // apply all the operators until the left paren
        ApplyUntilLeftParen(false);
      }
      else if (t.type == Token::Type::RightParen)
      {
        ApplyUntilLeftParen(true);
        if (!operatorStack.empty())
        {
          // if the token at the top of the operator stack is a function call,
          // then invoke it
          Token t = operatorStack.back();
          if (t.type == Token::Type::FuncCall)
          {
            InvokeFunction(t, env);
            operatorStack.pop_back();
          }
        }
      }
      else if (t.type == Token::Type::Var)
      {
        LookupVar(t, env);
      }
    }

    // apply all the remaining operators
    while (!operatorStack.empty())
    {
      ApplyBinOp(PopOperator().binOp);
    }

    return PopValue();
  }