@Override
 protected void setErrorMessage(IToken leftToken, IToken rightToken, String message) {
   assert leftToken.getTokenizer() == this && rightToken.getTokenizer() == this;
   for (int i = leftToken.getIndex(), max = rightToken.getIndex(); i <= max; i++) {
     tokens.get(i).setError(message);
   }
 }
 public void setStartOffset(int startOffset) {
   assert isAmbigous() || this.startOffset >= getInput().length();
   if (this.startOffset == startOffset) return;
   this.startOffset = startOffset;
   IToken lastToken = getTokenAtOffset(startOffset);
   this.offsetAtLineStart = lastToken.getStartOffset() - lastToken.getColumn();
   this.line = lastToken.getLine();
 }
 @Override
 public String toString() {
   String input = getInput();
   StringBuilder result = new StringBuilder();
   result.append('[');
   for (IToken token : tokens) {
     int offset = token.getStartOffset();
     result.append(input, offset, token.getEndOffset() + 1);
     result.append(',');
   }
   if (tokens.size() > 0) result.deleteCharAt(result.length() - 1);
   result.append(']');
   return result.toString();
 }