docs: protected TokenList extractTokens(String equation , ManagerTempVariables managerTemp ) {
          // add a space to make sure everything is parsed when its done
          equation += " ";
  
          TokenList tokens = new TokenList();
  
          int length = 0;
          boolean again; // process the same character twice
          TokenType type = TokenType.UNKNOWN;
          for( int i = 0; i < equation.length(); i++ ) {
              again = false;
              char c = equation.charAt(i);
              if( type == TokenType.WORD ) {
                  if (isLetter(c)) {
                      storage[length++] = c;
                  } else {
                      // add the variable/function name to token list
                      String name = new String(storage, 0, length);
                      tokens.add(name);
                      type = TokenType.UNKNOWN;
                      again = true; // process unexpected character a second time
                  }
              } else if( type == TokenType.INTEGER ) { // Handle integer numbers.  Until proven to be a float
                  if( c == '.' ) {
                      type = TokenType.FLOAT;
                      storage[length++] = c;
                  } else if( c == 'e' || c == 'E' ) {
                      type = TokenType.FLOAT_EXP;
                      storage[length++] = c;
                  } else if( Character.isDigit(c) ) {
                      storage[length++] = c;
                  } else if( isSymbol(c) || Character.isWhitespace(c) ) {
                      int value = Integer.parseInt( new String(storage, 0, length));
                      tokens.add(managerTemp.createInteger(value));
                      type = TokenType.UNKNOWN;
                      again = true; // process unexpected character a second time
                  } else {
                      throw new ParseError("Unexpected character at the end of an integer "+c);
                  }
              } else if( type == TokenType.FLOAT ) { // Handle floating point numbers
                  if( c == '.') {
                      throw new ParseError("Unexpected '.' in a float");
                  } else if( c == 'e' || c == 'E' ) {
                      storage[length++] = c;
                      type = TokenType.FLOAT_EXP;
                  } else if( Character.isDigit(c) ) {
                      storage[length++] = c;
                  } else if( isSymbol(c) || Character.isWhitespace(c) ) {
                      double value = Double.parseDouble( new String(storage, 0, length));
                      tokens.add(managerTemp.createDouble(value));
                      type = TokenType.UNKNOWN;
                      again = true; // process unexpected character a second time
                  } else {
                      throw new ParseError("Unexpected character at the end of an float "+c);
                  }
              } else if( type == TokenType.FLOAT_EXP ) { // Handle floating point numbers in exponential format
                  boolean end = false;
                  if( c == '-' ) {
                      char p = storage[length-1];
                      if( p == 'e' || p == 'E') {
                          storage[length++] = c;
                      } else {
                          end = true;
                      }
                  } else if( Character.isDigit(c) ) {
                      storage[length++] = c;
                  } else if( isSymbol(c) || Character.isWhitespace(c) ) {
                      end = true;
                  } else {
                      throw new ParseError("Unexpected character at the end of an float "+c);
                  }
  
                  if( end ) {
                      double value = Double.parseDouble( new String(storage, 0, length));
                      tokens.add(managerTemp.createDouble(value));
                      type = TokenType.UNKNOWN;
                      again = true; // process the current character again since it was unexpected
                  }
              } else {
                  if( isSymbol(c) ) {
                      boolean special = false;
                      if( c == '-' ) {
                          // need to handle minus symbols carefully since it can be part of a number of a minus operator
                          // if next to a number it should be negative sign, unless there is no operator to its left
                          // then its a minus sign.
                          if( i+1 < equation.length() && Character.isDigit(equation.charAt(i+1)) &&
                                  (tokens.last == null || isOperatorLR(tokens.last.getSymbol()))) {
                              type = TokenType.INTEGER;
                              storage[0] = c;
                              length = 1;
                              special = true;
                          }
                      }
                      if( !special ) {
                          TokenList.Token t = tokens.add(Symbol.lookup(c));
                          if (t.previous != null && t.previous.getType() == Type.SYMBOL) {
                              // there should only be two symbols in a row if its an element-wise operation
                              if (t.previous.getSymbol() == Symbol.PERIOD) {
                                  tokens.remove(t.previous);
                                  tokens.remove(t);
                                  tokens.add(Symbol.lookupElementWise(c));
                              }
                          }
                      }
                  } else if( Character.isWhitespace(c) ) {
                      continue;// ignore white space
                  } else {
                      // start adding to the word
                      if( Character.isDigit(c) ) {
                          type = TokenType.INTEGER;
                      } else {
                          type = TokenType.WORD;
                      }
                      storage[0] = c;
                      length = 1;
                  }
              }
              // see if it should process the same character again
              if( again )
                  i--;
          }
  
          return tokens;
      }