static PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> createSimplified(PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> leftSide, PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> rightSide, CalcOperator op) { CalculationCategory leftCategory = leftSide->category(); CalculationCategory rightCategory = rightSide->category(); ASSERT(leftCategory != CalcOther && rightCategory != CalcOther); bool isInteger = isIntegerResult(leftSide.get(), rightSide.get(), op); // Simplify numbers. if (leftCategory == CalcNumber && rightCategory == CalcNumber) { return CSSCalcPrimitiveValue::create(evaluateOperator(leftSide->doubleValue(), rightSide->doubleValue(), op), CSSPrimitiveValue::UnitType::Number, isInteger); } // Simplify addition and subtraction between same types. if (op == CalcAdd || op == CalcSubtract) { if (leftCategory == rightSide->category()) { CSSPrimitiveValue::UnitType leftType = leftSide->typeWithCalcResolved(); if (hasDoubleValue(leftType)) { CSSPrimitiveValue::UnitType rightType = rightSide->typeWithCalcResolved(); if (leftType == rightType) return CSSCalcPrimitiveValue::create(evaluateOperator(leftSide->doubleValue(), rightSide->doubleValue(), op), leftType, isInteger); CSSPrimitiveValue::UnitCategory leftUnitCategory = CSSPrimitiveValue::unitCategory(leftType); if (leftUnitCategory != CSSPrimitiveValue::UOther && leftUnitCategory == CSSPrimitiveValue::unitCategory(rightType)) { CSSPrimitiveValue::UnitType canonicalType = CSSPrimitiveValue::canonicalUnitTypeForCategory(leftUnitCategory); if (canonicalType != CSSPrimitiveValue::UnitType::Unknown) { double leftValue = leftSide->doubleValue() * CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(leftType); double rightValue = rightSide->doubleValue() * CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(rightType); return CSSCalcPrimitiveValue::create(evaluateOperator(leftValue, rightValue, op), canonicalType, isInteger); } } } } } else { // Simplify multiplying or dividing by a number for simplifiable types. ASSERT(op == CalcMultiply || op == CalcDivide); CSSCalcExpressionNode* numberSide = getNumberSide(leftSide.get(), rightSide.get()); if (!numberSide) return create(leftSide, rightSide, op); if (numberSide == leftSide && op == CalcDivide) return nullptr; CSSCalcExpressionNode* otherSide = leftSide == numberSide ? rightSide.get() : leftSide.get(); double number = numberSide->doubleValue(); if (std::isnan(number) || std::isinf(number)) return nullptr; if (op == CalcDivide && !number) return nullptr; CSSPrimitiveValue::UnitType otherType = otherSide->typeWithCalcResolved(); if (hasDoubleValue(otherType)) return CSSCalcPrimitiveValue::create(evaluateOperator(otherSide->doubleValue(), number, op), otherType, isInteger); } return create(leftSide, rightSide, op); }
void tryEvaluateOperatorOnStackThenPush(OperatorToken *newToken,Stack *dataStack,Stack *operatorStack) { OperatorToken *previousToken; previousToken=(OperatorToken*)pop(operatorStack); if(previousToken==NULL) { push(newToken,operatorStack); } else{ while(previousToken!=NULL) { if(newToken->precedence > previousToken->precedence) { break; } else { evaluateOperator(dataStack,previousToken); } previousToken=(OperatorToken*)pop(operatorStack); } if(previousToken!=NULL) { push(previousToken,operatorStack); } push(newToken,operatorStack); } }
bool EXParser::priorityOperatorLoop(std::string &_expression) { for(EXOperatorSet::iterator oiter = operators.begin(); oiter!=operators.end(); ++oiter){ for(size_t index = 0; index<_expression.length(); index++){ if(oiter->first == _expression[index] && !isScientificNotation(_expression, index)){ if(oiter->first != '-' || !isNegitiveSign(_expression, index)){ std::string prevExpression = _expression; if(!evaluateOperator(_expression, index, oiter)) return false; steps.push_back(EXSolveStep(prevExpression.append(" -> ").append(_expression), std::string(&oiter->first, 1))); oiter = operators.begin(); //reset operator loop to beginning } } } } return true; }
void evaluateAllOperatorOnStack(Stack *dataStack,Stack *operatorStack){ OperatorToken *opeToken; while((opeToken=pop(operatorStack))!=NULL) { evaluateOperator(dataStack,opeToken); } }
double evaluate(double leftSide, double rightSide) const { return evaluateOperator(leftSide, rightSide, m_operator); }