const char* csConditionEvaluator::ResolveOperand (csExpression* expression, CondOperand& operand) { const char* err; if (expression->type == csExpression::Value) { err = ResolveExpValue (expression->valueValue, operand); if (err) { return SetLastError ("Can't resolve value %s: %s", CS::Quote::Single (csExpressionToken::Extractor (expression->valueValue).Get ()), err); } return 0; } const csExpressionToken& t = expression->expressionValue.op; if (TokenEquals (t.tokenStart, t.tokenLen, ".")) { CS_ASSERT (expression->expressionValue.left->type == csExpression::Value); const csExpressionToken& left = expression->expressionValue.left->valueValue; if (TokenEquals (left.tokenStart, left.tokenLen, "vars")) { err = ResolveSVIdentifier (expression->expressionValue.right, operand); if (err) return err; return 0; } else if (TokenEquals (left.tokenStart, left.tokenLen, "consts")) { err = ResolveConst (expression->expressionValue.right, operand); if (err) return err; return 0; } else { return SetLastError ("Unknown identifier %s", CS::Quote::Single (csExpressionToken::Extractor (left).Get ())); } } else { operand.type = operandOperation; err = ProcessExpressionInternal (expression, operand.operation); if (err) return err; return 0; } CS_ASSERT (false); return 0; }
const char* csConditionEvaluator::ProcessExpressionInternal (csExpression* expression, CondOperation& operation) { const char* err; CondOperation newOp; if (expression->type == csExpression::Value) { newOp.operation = opEqual; err = ResolveExpValue (expression->valueValue, newOp.left); if (err) { return SetLastError ("Can't resolve value '%s': %s", csExpressionToken::Extractor (expression->valueValue).Get (), err); } newOp.right.type = operandBoolean; newOp.right.boolVal = true; if (!OpTypesCompatible (newOp.left.type, newOp.right.type)) { return SetLastError ("Type of '%s' is '%s', not compatible to '%s'", csExpressionToken::Extractor (expression->valueValue).Get (), OperandTypeDescription (newOp.left.type), OperandTypeDescription (newOp.right.type)); } } else { const csExpressionToken& t = expression->expressionValue.op; if (TokenEquals (t.tokenStart, t.tokenLen, ".")) { newOp.operation = opEqual; err = ResolveOperand (expression, newOp.left); if (err != 0) return err; newOp.right.Clear(); newOp.right.type = operandBoolean; newOp.right.boolVal = true; } else if (TokenEquals (t.tokenStart, t.tokenLen, "!")) { newOp.operation = opEqual; err = ResolveOperand (expression->expressionValue.right, newOp.left); if (err) return err; if (!OpTypesCompatible (newOp.left.type, operandBoolean)) { return SetLastError ("Type of '%s' is '%s', not compatible to '%s'", csExpressionToken::Extractor (t).Get (), OperandTypeDescription (newOp.left.type), OperandTypeDescription (operandBoolean)); } newOp.right.Clear(); newOp.right.type = operandBoolean; newOp.right.boolVal = false; } else if (TokenEquals (t.tokenStart, t.tokenLen, "==")) { newOp.operation = opEqual; err = ResolveOperand (expression->expressionValue.left, newOp.left); if (err) return err; err = ResolveOperand (expression->expressionValue.right, newOp.right); if (err) return err; if (!OpTypesCompatible (newOp.left.type, newOp.right.type)) { return SetLastError ("Type of '%s' is '%s', not compatible to '%s'", csExpressionToken::Extractor (t).Get (), OperandTypeDescription (newOp.left.type), OperandTypeDescription (newOp.right.type)); } } else if (TokenEquals (t.tokenStart, t.tokenLen, "!=")) { newOp.operation = opNEqual; err = ResolveOperand (expression->expressionValue.left, newOp.left); if (err) return err; err = ResolveOperand (expression->expressionValue.right, newOp.right); if (err) return err; if (!OpTypesCompatible (newOp.left.type, newOp.right.type)) { return SetLastError ("Type of '%s' is '%s', not compatible to '%s'", csExpressionToken::Extractor (t).Get (), OperandTypeDescription (newOp.left.type), OperandTypeDescription (newOp.right.type)); } } else if (TokenEquals (t.tokenStart, t.tokenLen, "<")) { newOp.operation = opLesser; err = ResolveOperand (expression->expressionValue.left, newOp.left); if (err) return err; err = ResolveOperand (expression->expressionValue.right, newOp.right); if (err) return err; if (!OpTypesCompatible (newOp.left.type, newOp.right.type)) { return SetLastError ("Type of '%s' is '%s', not compatible to '%s'", csExpressionToken::Extractor (t).Get (), OperandTypeDescription (newOp.left.type), OperandTypeDescription (newOp.right.type)); } } else if (TokenEquals (t.tokenStart, t.tokenLen, "<=")) { newOp.operation = opLesserEq; err = ResolveOperand (expression->expressionValue.left, newOp.left); if (err) return err; err = ResolveOperand (expression->expressionValue.right, newOp.right); if (err) return err; if (!OpTypesCompatible (newOp.left.type, newOp.right.type)) { return SetLastError ("Type of '%s' is '%s', not compatible to '%s'", csExpressionToken::Extractor (t).Get (), OperandTypeDescription (newOp.left.type), OperandTypeDescription (newOp.right.type)); } } else if (TokenEquals (t.tokenStart, t.tokenLen, ">=")) { newOp.operation = opLesserEq; err = ResolveOperand (expression->expressionValue.left, newOp.right); if (err) return err; err = ResolveOperand (expression->expressionValue.right, newOp.left); if (err) return err; if (!OpTypesCompatible (newOp.left.type, newOp.right.type)) { return SetLastError ("Type of '%s' is '%s', not compatible to '%s'", csExpressionToken::Extractor (t).Get (), OperandTypeDescription (newOp.left.type), OperandTypeDescription (newOp.right.type)); } } else if (TokenEquals (t.tokenStart, t.tokenLen, ">")) { newOp.operation = opLesser; err = ResolveOperand (expression->expressionValue.left, newOp.right); if (err) return err; err = ResolveOperand (expression->expressionValue.right, newOp.left); if (err) return err; if (!OpTypesCompatible (newOp.left.type, newOp.right.type)) { return SetLastError ("Type of '%s' is '%s', not compatible to '%s'", csExpressionToken::Extractor (t).Get (), OperandTypeDescription (newOp.left.type), OperandTypeDescription (newOp.right.type)); } } else if (TokenEquals (t.tokenStart, t.tokenLen, "&&")) { newOp.operation = opAnd; err = ResolveOperand (expression->expressionValue.left, newOp.left); if (err) return err; if (!OpTypesCompatible (newOp.left.type, operandBoolean)) { return SetLastError ("Type of '%s' is '%s', not compatible to '%s'", csExpressionToken::Extractor (t).Get (), OperandTypeDescription (newOp.left.type), OperandTypeDescription (operandBoolean)); } if (newOp.left.type != operandOperation) { /* Convert to "(left eq true) and (right eq true)" to make the possible * value determination simpler. */ CondOperation newOpL; newOpL.operation = opEqual; newOpL.left = newOp.left; newOpL.right.type = operandBoolean; newOpL.right.boolVal = true; newOp.left.Clear(); newOp.left.type = operandOperation; newOp.left.operation = FindOptimizedConditionInternal (newOpL); } err = ResolveOperand (expression->expressionValue.right, newOp.right); if (err) return err; if (!OpTypesCompatible (newOp.right.type, operandBoolean)) { return SetLastError ("Type of '%s' is '%s', not compatible to '%s'", csExpressionToken::Extractor (t).Get (), OperandTypeDescription (newOp.right.type), OperandTypeDescription (operandBoolean)); } if (newOp.right.type != operandOperation) { /* Convert to "(left eq true) and (right eq true)" to make the possible * value determination simpler. */ CondOperation newOpR; newOpR.operation = opEqual; newOpR.left = newOp.right; newOpR.right.type = operandBoolean; newOpR.right.boolVal = true; newOp.right.Clear(); newOp.right.type = operandOperation; newOp.right.operation = FindOptimizedConditionInternal (newOpR); } } else if (TokenEquals (t.tokenStart, t.tokenLen, "||")) { newOp.operation = opOr; err = ResolveOperand (expression->expressionValue.left, newOp.left); if (err) return err; if (!OpTypesCompatible (newOp.left.type, operandBoolean)) { return SetLastError ("Type of '%s' is '%s', not compatible to '%s'", csExpressionToken::Extractor (t).Get (), OperandTypeDescription (newOp.left.type), OperandTypeDescription (operandBoolean)); } if (newOp.left.type != operandOperation) { /* Convert to "(left eq true) or (right eq true)" to make the possible * value determination simpler. */ CondOperation newOpL; newOpL.operation = opEqual; newOpL.left = newOp.left; newOpL.right.type = operandBoolean; newOpL.right.boolVal = true; newOp.left.Clear(); newOp.left.type = operandOperation; newOp.left.operation = FindOptimizedConditionInternal (newOpL); } err = ResolveOperand (expression->expressionValue.right, newOp.right); if (err) return err; if (!OpTypesCompatible (newOp.right.type, operandBoolean)) { return SetLastError ("Type of '%s' is '%s', not compatible to '%s'", csExpressionToken::Extractor (t).Get (), OperandTypeDescription (newOp.right.type), OperandTypeDescription (operandBoolean)); } if (newOp.right.type != operandOperation) { /* Convert to "(left eq true) or (right eq true)" to make the possible * value determination simpler. */ CondOperation newOpR; newOpR.operation = opEqual; newOpR.left = newOp.right; newOpR.right.type = operandBoolean; newOpR.right.boolVal = true; newOp.right.Clear(); newOp.right.type = operandOperation; newOp.right.operation = FindOptimizedConditionInternal (newOpR); } } else { return SetLastError ("Unknown operator '%s'", csExpressionToken::Extractor (t).Get ()); } } operation = newOp; return 0; }