bool ExpConditional::Constant() { if (a->Constant()) CollapseConstantTree(a); if (b->Constant()) CollapseConstantTree(b); if (c->Constant()) CollapseConstantTree(c); return (a->Constant() && b->Constant() && c->Constant()); }
// Do a standard binary constant collapse for a binary operator. bool DoBinaryCollapse(ExpPart*& l, ExpPart*& r) { bool leftConst = l->Constant(); bool rightConst = r->Constant(); // If the L part is constant, collapse it. if (leftConst) CollapseConstantTree(l); // If the R part is constant, collapse it. if (rightConst) CollapseConstantTree(r); // This part is constant if the left and right parts are both constant. return (leftConst && rightConst); }
bool ExpArray::Constant() { // Const collapse all items ExpParamIterator i = expElements.begin(); ExpParamConstIterator elements_end = expElements.end(); isConstant = true; for ( ; i != elements_end; i++) { if ((*i)->Constant()) CollapseConstantTree(*i); else isConstant = false; } // If it is constant, get me to evaluate if (isConstant) { ExpReturn unused; // Evaluate checks for the isConstant flag so temporarily turn it off isConstant = false; this->Evaluate(&unused); isConstant = true; } return isConstant!=0; }
bool ExpIdent::Constant() { // Const collapse all parameters ExpPart** curParam = parameters; bool allParamsConstant = true; for ( ; curParam != paramsEnd; curParam++) { // This parameter is constant if ((*curParam)->Constant()) CollapseConstantTree(*curParam); // Collapse it else allParamsConstant = false; } // All parameters are constant: evaluate the parameters if (allParamsConstant) { ExpReturn* expPtr = expParamList; ExpPart** curParam = parameters; // Evaluate every parameter for ( ; curParam != paramsEnd; curParam++) // Send to address of corresponding expParamList array entry (*curParam)->Evaluate(expPtr++); // Switch off parameter evaluation since all parameters are constant and we've evaluated them already. hasParameters = false; } // Return false; no way of telling if the plugin will return a constant value // or not. // UNLESS it is a system expression, in which we can mark constant all expressions which return // a constant output for a constant input. // Note i havent bothered for expressions like max and min. Nobody types max(3,4,5,6). if (oid == -1 && allParamsConstant) { switch (expID) { case 10: // newline case 21: // numtokens case 22: // gettoken case SYSTEM_VARINDEX: // _varindex return true; default: return false; } } return false; }
bool ExpDot::Constant() { // Const collapse all parameters vector<ExpPart*>::iterator i; for (i = parameters.begin(); i != parameters.end(); i++) { // This parameter is constant if ((*i)->Constant()) CollapseConstantTree((*i)); // Collapse it } // Return false; no way of telling if the plugin will return a constant value // or not. return false; }
void CExpression::ParseTokenStream() { // Make the tree int step = 0; pExpressionOwner = NULL; ExpTree = DoTree(step); ExpTree = PostSortTree(ExpTree); // Determine if the overall expression is constant, collapsing constant parts along // the way. isConstant = ExpTree->Constant(); // If constant, get the constant value. if (isConstant) { CollapseConstantTree(ExpTree); ExpTree->Evaluate(&constantValue); } }
bool ExpDot::Constant() { // Const collapse all parameters ExpPart** curParam = parameters; if(hasParameters) { bool allParamsConstant = true; for ( ; curParam != paramsEnd; curParam++) { // This parameter is constant if ((*curParam)->Constant()) CollapseConstantTree(*curParam); // Collapse it else allParamsConstant = false; } // All parameters are constant: evaluate the parameters if (allParamsConstant) { ExpReturn* expPtr = expParamList; ExpPart** curParam = parameters; // Evaluate every parameter for ( ; curParam != paramsEnd; curParam++) // Send to address of corresponding expParamList array entry (*curParam)->Evaluate(expPtr++); // Switch off parameter evaluation since all parameters are constant and we've evaluated them already. hasParameters = false; } } // Return false; no way of telling if the plugin will return a constant value // or not. return false; }
// Tokenise a user's typed expression string void CExpression::ParseUserString(const char* exp, int* pchpos, bool editorMode) { toks.clear(); whitespaceCount = 0; // Loop every char for (int i = 0; exp[i] != NULL; i++) { if (pchpos) *pchpos = i; char NextCh = exp[i+1]; char CurCh = exp[i]; char PrevCh = exp[(i == 0 ? 0 : i-1)]; char strbuf[128]; // Check this char switch (exp[i]) { case '+': AppendToken(T_ADD, "+"); break; case '-': // If previous token is not operand, use as negative sign // Fix 25/4/07: random(4) - random(5) interprets '-' as integer: explicit check for right bracket if (toks.size() == 0 || ((!TokenFitsRule(toks.back().t, T_ANY_VALUE) || toks.back().t == T_LEFTBRACKET) && toks.back().t != T_RIGHTBRACKET)) { i += ConsumeDigits(strbuf, &(exp[i])); // Contains a dot: float if (StrContains(strbuf, '.')) AppendToken(T_FLOAT, strbuf); else // Else integer AppendToken(T_INTEGER, strbuf); } else AppendToken(T_SUBTRACT, "-"); break; case '*': AppendToken(T_MULTIPLY, "*"); break; case '/': AppendToken(T_DIVIDE, "/"); break; case '^': AppendToken(T_POWER, "^"); break; case '%': AppendToken(T_MOD, "%"); break; case '(': AppendToken(T_LEFTBRACKET, "("); break; case ')': AppendToken(T_RIGHTBRACKET, ")"); break; case '{': AppendToken(T_LEFTCURLY, "{"); break; case '}': AppendToken(T_RIGHTCURLY, "}"); break; case '@': AppendToken(T_AT, "@"); break; case ',': AppendToken(T_COMMA, ","); break; case '.': AppendToken(T_DOT, "."); break; case '"': i += AppendString(&(exp[i]), editorMode); break; case '\'': i += AppendString(&(exp[i]), editorMode, true); break; case '=': AppendToken(T_EQUAL, "="); break; case '<': if (NextCh == '=') { AppendToken(T_LESSEQUAL, "<="); i++; } else if (NextCh == '>') { AppendToken(T_NOTEQUAL, "<>"); i++; } else AppendToken(T_LESS, "<"); break; // Alternative not equal operator != <> case '!': if (NextCh == '=') { AppendToken(T_NOTEQUAL, "!="); i++; } else NotifyError("Syntax error: '!'"); break; case '&': AppendToken(T_AND, "&"); break; case '|': AppendToken(T_OR, "|"); break; case '>': if (NextCh == '=') { AppendToken(T_GREATEREQUAL, ">="); i++; } else AppendToken(T_GREATER, ">"); break; case '?': AppendToken(T_CONDITIONAL, "?"); break; case ':': AppendToken(T_COLON, ":"); break; default: // Parse numbers and idents if (IsChAlphaNumeric(CurCh)) i += ConsumeAppendIdentifier(strbuf, &(exp[i])); // Skip over whitespace else if (IsWhitespace(CurCh)) { // In editor mode add a T_WHITESPACE token if (editorMode) { Token t; t.length = 0; t.t = T_WHITESPACE; while (IsWhitespace(exp[i])) { t.str += exp[i]; i++; } // We want the next for loop iteration to see the next char i--; toks.push_back(t); } // Add to last token length if (toks.size() > 0) toks[toks.size() - 1].length++; } // Else unknown character else { string error = "Unknown character '"; error += CurCh; error += "'"; throw runtime_error(error.c_str()); } }//switch }//for // Only perform preprocessing when not in edittime mode if (!editorMode) PreProcessTokStream(); /////////////////////////// // Final step: parse to tree // Determine if the overall expression is constant, collapsing constant parts along // the way. // Runtime only #ifdef RUNTIME // Make the tree int step = 0; ExpTree = DoTree(step); isConstant = ExpTree->Constant(); // If constant, get the constant value. if (isConstant) { CollapseConstantTree(ExpTree); ExpTree->Evaluate(&constantValue); } #endif }