anchor.diff:  		// Grab the next token and if nothing special is needed, simply return it.
   		Token next = super.nextToken();
   		//NOTE: This would be the appropriate spot to count whitespace or deal with NEWLINES, but it is already handled with custom actions down in the lexer rules.
  +		if (pendingDent && null == initialIndentToken && NEWLINE != next.getType()) { initialIndentToken = next; }
   		if (null == next || HIDDEN == next.getChannel() || NEWLINE == next.getType()) { return next; }
   
   		// Handle EOF; in particular, handle an abrupt EOF that comes without an immediately preceding NL.
   		if (next.getType() == EOF) {
   			indentCount = 0;
   			// EOF outside of `pendingDent` mode means we did not have a final NEWLINE before the end of file.
  -			if (!pendingDent) { tokenQueue.offer(new CommonToken(NEWLINE, "NEWLINE")); }
  +			if (!pendingDent) {
  +				initialIndentToken = next;
  +				tokenQueue.offer(createToken(NEWLINE, "NEWLINE", next));
  +			}
   		}
   
   		// Before exiting `pendingDent` state we need to queue up proper INDENTS and DEDENTS.
   		while (indentCount != getSavedIndent()) {
   			if (indentCount > getSavedIndent()) {
   				indentStack.push(indentCount);
  -				CommonToken token = new CommonToken(DentParser.INDENT, "INDENT" + indentCount); //TODO: set start/end character index
  -				tokenQueue.offer(token);
  +				tokenQueue.offer(createToken(DentParser.INDENT, "INDENT" + indentCount, next));
   			} else {
   				indentStack.pop();
  -				CommonToken token = new CommonToken(DentParser.DEDENT, "DEDENT"+getSavedIndent()); //TODO: set start/end character index
  -				tokenQueue.offer(token);
  +				tokenQueue.offer(createToken(DentParser.DEDENT, "DEDENT"+getSavedIndent(), next));
   			}
   		}
   		pendingDent = false;
  
positive.code: 
  blockStatements : LEGIT+ NEWLINE INDENT statement+ DEDENT ;
  
  LEGIT : ~[ \t\r\n]+ ;   // Replace with your language-specific rules...
  
  NEWLINE : ( '\r'? '\n' | '\r' ) { if (pendingDent) { setChannel(HIDDEN); } pendingDent = true; indentCount = 0; } ;
  
  WS : [ \t]+ { setChannel(HIDDEN); if (pendingDent) { indentCount += getText().length(); } } ;
  
  BlockComment : '/*' ( BlockComment | . )*? '*/' -> channel(HIDDEN) ;   // allow nesting comments
  LineComment : '//' ~[\r\n]* -> channel(HIDDEN) ;
  
negative.code: 
  	private java.util.Stack<Integer> indentStack = new java.util.Stack<>();
  
  	private Token initialIndentToken = null;
  
  	private int getSavedIndent() { return indentStack.isEmpty() ? 0 : indentStack.peek(); }
  
  	private CommonToken createToken(int type, String text, Token next) {
  		CommonToken token = new CommonToken(type, text);
  		if (null != initialIndentToken) {
  			token.setStartIndex(initialIndentToken.getStartIndex());
  			token.setLine(initialIndentToken.getLine());
  			token.setCharPositionInLine(initialIndentToken.getCharPositionInLine());
  			token.setStopIndex(next.getStartIndex()-1);
  		}
  		return token;
  	}
  
  	@Override
  	public Token nextToken() {
  