void NumericExpression::init() { StringTokenizer tokenizer( "", "'\"" ); tokenizer.addDelims( "[],()%*/+-", true ); tokenizer.keepEmpties() = false; StringVector t; tokenizer.tokenize( _src, t ); //tokenize(_src, t, "[],()%*/+-", "'\"", false, true); // identify tokens: AtomVector infix; bool invar = false; for( unsigned i=0; i<t.size(); ++i ) { if ( t[i] == "[" && !invar ) { invar = true; } else if ( t[i] == "]" && invar ) { invar = false; infix.push_back( Atom(VARIABLE,0.0) ); _vars.push_back( Variable(t[i-1],0) ); } else if ( t[i] == "(" ) infix.push_back( Atom(LPAREN,0.0) ); else if ( t[i] == ")" ) infix.push_back( Atom(RPAREN,0.0) ); else if ( t[i] == "," ) infix.push_back( Atom(COMMA,0.0) ); else if ( t[i] == "%" ) infix.push_back( Atom(MOD,0.0) ); else if ( t[i] == "*" ) infix.push_back( Atom(MULT,0.0) ); else if ( t[i] == "/" ) infix.push_back( Atom(DIV,0.0) ); else if ( t[i] == "+" ) infix.push_back( Atom(ADD,0.0) ); else if ( t[i] == "-" ) infix.push_back( Atom(SUB,0.0) ); else if ( t[i] == "min" ) infix.push_back( Atom(MIN,0.0) ); else if ( t[i] == "max" ) infix.push_back( Atom(MAX,0.0) ); else if ( t[i][0] >= '0' && t[i][0] <= '9' ) infix.push_back( Atom(OPERAND,as<double>(t[i],0.0)) ); // note: do nothing for a comma } // convert to RPN: // http://en.wikipedia.org/wiki/Shunting-yard_algorithm AtomStack s; unsigned var_i = 0; for( unsigned i=0; i<infix.size(); ++i ) { Atom& a = infix[i]; if ( a.first == LPAREN ) { s.push( a ); } else if ( a.first == RPAREN ) { while( s.size() > 0 ) { Atom top = s.top(); s.pop(); if ( top.first == LPAREN ) break; else _rpn.push_back( top ); } } else if ( a.first == COMMA ) { while( s.size() > 0 && s.top().first != LPAREN ) { _rpn.push_back( s.top() ); s.pop(); } } else if ( IS_OPERATOR(a) ) { if ( s.empty() || a.first > s.top().first ) { s.push( a ); } else { while( s.size() > 0 && a.first < s.top().first && IS_OPERATOR(s.top()) ) { _rpn.push_back( s.top() ); s.pop(); } s.push( a ); } } else if ( a.first == MIN || a.first == MAX ) { s.push( a ); } else if ( a.first == OPERAND ) { _rpn.push_back( a ); } else if ( a.first == VARIABLE ) { _rpn.push_back( a ); _vars[var_i++].second = _rpn.size()-1; // store the index } } while( s.size() > 0 ) { _rpn.push_back( s.top() ); s.pop(); } }
void NumericExpression::init() { _vars.clear(); _rpn.clear(); StringTokenizer variablesTokenizer( "", "" ); variablesTokenizer.addDelims( "[]", true ); variablesTokenizer.addQuotes( "'\"", true ); variablesTokenizer.keepEmpties() = false; StringTokenizer operandTokenizer( "", "" ); operandTokenizer.addDelims( ",()%*/+-", true ); operandTokenizer.addQuotes( "'\"", true ); operandTokenizer.keepEmpties() = false; StringVector variablesTokens; variablesTokenizer.tokenize( _src, variablesTokens ); StringVector t; bool invar = false; for( unsigned i=0; i<variablesTokens.size(); ++i ) { if ( variablesTokens[i] == "[" && !invar ) { // Start variable, add "[" token invar = true; t.push_back(variablesTokens[i]); } else if ( variablesTokens[i] == "]" && invar ) { // End variable, add "]" token invar = false; t.push_back(variablesTokens[i]); } else if ( invar ) { // Variable, add variable token t.push_back(variablesTokens[i]); } else { // Operands, tokenize it and add tokens StringVector operandTokens; operandTokenizer.tokenize( variablesTokens[i], operandTokens ); t.insert(t.end(), operandTokens.begin(), operandTokens.end()); } } // identify tokens: AtomVector infix; invar = false; for( unsigned i=0; i<t.size(); ++i ) { if ( t[i] == "[" && !invar ) { invar = true; } else if ( t[i] == "]" && invar ) { invar = false; infix.push_back( Atom(VARIABLE,0.0) ); _vars.push_back( Variable(t[i-1],0) ); } else if ( t[i] == "(" ) infix.push_back( Atom(LPAREN,0.0) ); else if ( t[i] == ")" ) infix.push_back( Atom(RPAREN,0.0) ); else if ( t[i] == "," ) infix.push_back( Atom(COMMA,0.0) ); else if ( t[i] == "%" ) infix.push_back( Atom(MOD,0.0) ); else if ( t[i] == "*" ) infix.push_back( Atom(MULT,0.0) ); else if ( t[i] == "/" ) infix.push_back( Atom(DIV,0.0) ); else if ( t[i] == "+" ) infix.push_back( Atom(ADD,0.0) ); else if ( t[i] == "-" ) infix.push_back( Atom(SUB,0.0) ); else if ( t[i] == "min" ) infix.push_back( Atom(MIN,0.0) ); else if ( t[i] == "max" ) infix.push_back( Atom(MAX,0.0) ); else if ( (t[i][0] >= '0' && t[i][0] <= '9') || t[i][0] == '.' ) infix.push_back( Atom(OPERAND,as<double>(t[i],0.0)) ); else if ( t[i] != "," && (i == 0 || t[i-1] != "[")) { std::string var = t[i]; // If this is a call to a script function, store the entire function // call in the variable string if (i < t.size() - 1 && t[i+1] == "(") { int parenCount = 0; do { ++i; var += t[i]; if (t[i] == "(") parenCount++; else if (t[i] == ")") parenCount--; } while (i < t.size() - 1 && parenCount > 0); } infix.push_back( Atom(VARIABLE, 0.0) ); _vars.push_back( Variable(var, 0) ); } // note: do nothing for a comma } // convert to RPN: // http://en.wikipedia.org/wiki/Shunting-yard_algorithm AtomStack s; unsigned var_i = 0; for( unsigned i=0; i<infix.size(); ++i ) { Atom& a = infix[i]; if ( a.first == LPAREN ) { s.push( a ); } else if ( a.first == RPAREN ) { while( s.size() > 0 ) { Atom top = s.top(); s.pop(); if ( top.first == LPAREN ) break; else _rpn.push_back( top ); } } else if ( a.first == COMMA ) { while( s.size() > 0 && s.top().first != LPAREN ) { _rpn.push_back( s.top() ); s.pop(); } } else if ( IS_OPERATOR(a) ) { if ( s.empty() || a.first > s.top().first ) { s.push( a ); } else { while( s.size() > 0 && a.first < s.top().first && IS_OPERATOR(s.top()) ) { _rpn.push_back( s.top() ); s.pop(); } s.push( a ); } } else if ( a.first == MIN || a.first == MAX ) { s.push( a ); } else if ( a.first == OPERAND ) { _rpn.push_back( a ); } else if ( a.first == VARIABLE ) { _rpn.push_back( a ); _vars[var_i++].second = _rpn.size()-1; // store the index } } while( s.size() > 0 ) { _rpn.push_back( s.top() ); s.pop(); } }
void NumericExpression::init() { StringVector t; tokenize(_src, t, "[],()%*/+-", "'\"", false, true); // identify tokens: AtomVector infix; bool invar = false; for( unsigned i=0; i<t.size(); ++i ) { if ( t[i] == "[" && !invar ) { invar = true; } else if ( t[i] == "]" && invar ) { invar = false; infix.push_back( Atom(VARIABLE,0.0) ); _vars.push_back( Variable(t[i-1],0) ); } else if ( t[i] == "(" )infix.push_back( Atom(LPAREN,0.0) ); else if ( t[i] == ")" ) infix.push_back( Atom(RPAREN,0.0) ); else if ( t[i] == "%" ) infix.push_back( Atom(MOD,0.0) ); else if ( t[i] == "*" ) infix.push_back( Atom(MULT,0.0) ); else if ( t[i] == "/" ) infix.push_back( Atom(DIV,0.0) ); else if ( t[i] == "+" ) infix.push_back( Atom(ADD,0.0) ); else if ( t[i] == "-" ) infix.push_back( Atom(SUB,0.0) ); else if ( t[i] == "min" ) infix.push_back( Atom(MIN,0.0) ); else if ( t[i] == "max" ) infix.push_back( Atom(MAX,0.0) ); else if ( t[i][0] >= '0' && t[i][0] <= '9' ) infix.push_back( Atom(OPERAND,as<double>(t[i],0.0)) ); // note: do nothing for a comma } // convert to RPN: AtomStack s; unsigned var_i = 0; for( unsigned i=0; i<infix.size(); ++i ) { Atom& a = infix[i]; if ( a.first == LPAREN ) { s.push( a ); } else if ( a.first == RPAREN ) { while( s.size() > 0 ) { Atom top = s.top(); s.pop(); if ( top.first == LPAREN ) break; else _rpn.push_back( top ); } } else if ( a.first == ADD || a.first == SUB || a.first == MULT || a.first == DIV || a.first == MOD ) { if ( s.empty() || a.first > s.top().first ) { s.push( a ); } else { while( s.size() > 0 && a.first < s.top().first ) { _rpn.push_back( s.top() ); s.pop(); } s.push( a ); } } else if ( a.first == MIN || a.first == MAX ) { s.push( a ); } else if ( a.first == OPERAND ) { _rpn.push_back( a ); } else if ( a.first == VARIABLE ) { _rpn.push_back( a ); _vars[var_i++].second = _rpn.size()-1; // store the index } } while( s.size() > 0 ) { _rpn.push_back( s.top() ); s.pop(); } }