@Override
 public boolean hasPrevious() {
   if (tokens == null) {
     return false;
   }
   if (ndx <= 0) {
     return false;
   }
   Token t = tokens.get(ndx);
   if (t.end() <= start) {
     return false;
   }
   return true;
 }
 @SuppressWarnings("unchecked")
 private TokenIterator(int start, int end) {
   this.start = start;
   this.end = end;
   if (tokens != null && !tokens.isEmpty()) {
     Token token = new Token(TokenType.COMMENT, start, end - start);
     ndx = Collections.binarySearch((List) tokens, token);
     // we will probably not find the exact token...
     if (ndx < 0) {
       // so, start from one before the token where we should be...
       // -1 to get the location, and another -1 to go back..
       ndx = (-ndx - 1 - 1 < 0) ? 0 : (-ndx - 1 - 1);
       Token t = tokens.get(ndx);
       // if the prev token does not overlap, then advance one
       if (t.end() <= start) {
         ndx++;
       }
     }
   }
 }
 /**
  * Find the token at a given position. May return null if no token is found (whitespace skipped)
  * or if the position is out of range:
  *
  * @param pos
  * @return
  */
 public Token getTokenAt(int pos) {
   if (tokens == null || tokens.isEmpty() || pos > getLength()) {
     return null;
   }
   Token tok = null;
   Token tKey = new Token(TokenType.DEFAULT, pos, 1);
   @SuppressWarnings("unchecked")
   int ndx = Collections.binarySearch((List) tokens, tKey);
   if (ndx < 0) {
     // so, start from one before the token where we should be...
     // -1 to get the location, and another -1 to go back..
     ndx = (-ndx - 1 - 1 < 0) ? 0 : (-ndx - 1 - 1);
     Token t = tokens.get(ndx);
     if ((t.start <= pos) && (pos <= t.end())) {
       tok = t;
     }
   } else {
     tok = tokens.get(ndx);
   }
   return tok;
 }