Clean up scanner
diff --git a/lib/src/scanner2.dart b/lib/src/scanner2.dart
index 6b601bc..37fe05f 100644
--- a/lib/src/scanner2.dart
+++ b/lib/src/scanner2.dart
@@ -1,10 +1,9 @@
-library scanner2;
-
-//import 'package:mustache/mustache.dart' as m;
+library scanner;
 
 class Scanner {
   
-  Scanner(String source, this._templateName, String delimiters, {bool lenient: true})
+  Scanner(String source, this._templateName, String delimiters,
+      {bool lenient: true})
    : _source = source,
      _lenient = lenient,
      _itr = source.runes.iterator {
@@ -40,11 +39,63 @@
   int _closeDelimiter;
   
   List<Token> scan() {
-    while(true) {
-      int c = _peek();
-      if (c == _EOF) break;
-      else if (c == _openDelimiter) _scanOpenDelimiter();
-      else _scanText();
+    
+    for (int c = _peek(); c != _EOF; c = _peek()) {
+      
+      // Scan text tokens.
+      if (c != _openDelimiter) {
+        _scanText();
+        continue;
+      }
+        
+      int start = _offset;
+      
+      // Read first open delimiter character.
+      _read();
+      
+      // If only a single delimiter character then create a text token.
+      if (_openDelimiterInner != null && _peek() != _openDelimiterInner) {
+        var value = new String.fromCharCode(_openDelimiter);
+        _push(TokenType.text, value, start, _offset);
+        continue;
+      }
+        
+      if (_openDelimiterInner != null) _expect(_openDelimiterInner);
+      
+      // Handle triple mustache.
+      if (_openDelimiterInner == _OPEN_MUSTACHE &&
+          _openDelimiter == _OPEN_MUSTACHE &&
+          _peek() == _OPEN_MUSTACHE) {
+        
+        _read();
+        _push(TokenType.openTripleMustache, '{{{', start, _offset);
+        _scanTagContent();
+        _scanCloseTripleMustache();
+                   
+      } else {
+      
+        // Check to see if this is a change delimiter tag. {{= | | =}}
+        // Need to skip whitespace and check for "=".
+        int wsStart = _offset;
+        var ws = _readWhile(_isWhitespace);
+        
+        if (_peek() == _EQUAL) {
+          _scanChangeDelimiterTag(start);
+          
+        } else {
+          // Scan standard mustache tag.
+          var value = new String.fromCharCodes(_openDelimiterInner == null
+              ? [_openDelimiter]
+              : [_openDelimiter, _openDelimiterInner]);
+          
+          _push(TokenType.openDelimiter, value, start, wsStart);
+          
+          if (ws != '') _push(TokenType.whitespace, ws, wsStart, _offset);
+          
+          _scanTagContent();
+          _scanCloseDelimiter();
+        }
+      }
     }
     return _tokens;
   }
@@ -58,15 +109,11 @@
     return c;
   }
   
-  String _readWhile(bool test(int charCode), [Function endOfFile]) {
-    
+  String _readWhile(bool test(int charCode)) {
     int start = _offset;  
     while (_peek() != _EOF && test(_peek())) {
       _read();
     }
-
-    if (_peek() == _EOF && endOfFile != null) endOfFile();
-    
     int end = _peek() == _EOF ? _source.length : _offset;
     return _source.substring(start, end);
   }
@@ -80,12 +127,14 @@
 
     } else if (c != expectedCharCode) {
       throw new TemplateException('Unexpected character, '
-        'expected: ${new String.fromCharCode(expectedCharCode)} ($expectedCharCode), '
-        'was: ${new String.fromCharCode(c)} ($c)', 
-        _templateName, _source, _offset);
+        'expected: ${new String.fromCharCode(expectedCharCode)}, '
+        'was: ${new String.fromCharCode(c)}', _templateName, _source, _offset);
     }
   }
   
+  _push(TokenType type, String value, int start, int end) =>
+      _tokens.add(new Token(type, value, start, end));
+  
   bool _isWhitespace(int c)
     => const [_SPACE, _TAB , _NEWLINE, _RETURN].contains(c);
   
@@ -130,63 +179,7 @@
           token = TokenType.text;
       }
       
-      _tokens.add(new Token(token, value, start, _offset));
-    }
-  }
-
-  //TODO remove this.
-  var _errorEofInTag = null;
-  
-  void _scanOpenDelimiter() {
-    int start = _offset;
-    _expect(_openDelimiter); //TODO Change to assert.
-    
-    // If only a single delimiter then create a text token.
-    if (_openDelimiterInner != null && _peek() != _openDelimiterInner) {
-      var value = new String.fromCharCode(_openDelimiter);
-      _tokens.add(new Token(TokenType.text, value, start, _offset));
-      
-    } else {
-    
-      if (_openDelimiterInner != null) _expect(_openDelimiterInner);
-      
-      //TODO consider only allowing if other delimiters are set to mustache.
-      if (_peek() == _OPEN_MUSTACHE) {
-        _read();
-        
-        var value = new String.fromCharCodes(_openDelimiterInner != null
-                  ? [_openDelimiter, _openDelimiterInner, _OPEN_MUSTACHE]
-                  : [_openDelimiter, _OPEN_MUSTACHE]);
-        
-        _tokens.add(new Token(TokenType.openTripleMustache, value, start, _offset));
-      
-        _scanTagContent();
-        _scanCloseTripleMustache();
-        
-      } else {
-  
-        var value = _openDelimiterInner != null
-          ? new String.fromCharCodes([_openDelimiter, _openDelimiterInner])
-          : new String.fromCharCode(_openDelimiter);
-          
-        _tokens.add(new Token(TokenType.openDelimiter, value, start, _offset));    
-      
-        // Check to see if this is a change delimiter tag. {{= | | =}}
-        // Need to skip whitespace and check for "=".
-        int wsStart = _offset;
-        var ws = _readWhile(
-            (c) => const [_SPACE, _TAB, _NEWLINE, _RETURN].contains(c));
-        
-        if (_peek() == _EQUAL) {
-          _scanChangeDelimiterTag(start);
-        } else {
-          if (ws.isNotEmpty) {
-            _tokens.add(new Token(TokenType.whitespace, ws, wsStart, _offset));
-          }
-          _scanTagContent();
-          _scanCloseDelimiter();
-        }
-      }
+      _push(token, value, start, _offset);
     }
   }
   
@@ -223,8 +216,7 @@
         case _NEWLINE:
         case _RETURN:
           token = TokenType.whitespace;
-          value = _readWhile(
-              (c) => const [_SPACE, _TAB, _NEWLINE, _RETURN].contains(c));
+          value = _readWhile(_isWhitespace);
           break;
           
         case _PERIOD:
@@ -242,7 +234,7 @@
             c != _closeDelimiterInner &&
             c != _closeDelimiter);
       }
-      _tokens.add(new Token(token, value, start, _offset));    
+      _push(token, value, start, _offset);    
     }    
   }
   
@@ -259,26 +251,21 @@
           ? [_closeDelimiter]
           : [_closeDelimiterInner, _closeDelimiter]);
       
-      _tokens.add(new Token(TokenType.closeDelimiter, value, start, _offset));
+      _push(TokenType.closeDelimiter, value, start, _offset);
     }    
   }
 
   // Scan close triple mustache delimiter token.
-  //TODO consider forcing the delimiters to all be mustaches.
   void _scanCloseTripleMustache() {
     
     if (_peek() != _EOF) {
       int start = _offset;
       
-      if (_closeDelimiterInner != null) _expect(_closeDelimiterInner);
-      _expect(_closeDelimiter);      
+      _expect(_CLOSE_MUSTACHE);
+      _expect(_CLOSE_MUSTACHE);      
       _expect(_CLOSE_MUSTACHE);
       
-      String value = new String.fromCharCodes(_closeDelimiterInner == null
-          ? [_closeDelimiter, _CLOSE_MUSTACHE]
-          : [_closeDelimiterInner, _closeDelimiter, _CLOSE_MUSTACHE]);
-      
-      _tokens.add(new Token(TokenType.closeTripleMustache, value, start, _offset));
+      _push(TokenType.closeTripleMustache, '}}}', start, _offset);
     }
     
   }  
@@ -289,7 +276,7 @@
     var delimiterInner = _closeDelimiterInner;
     var delimiter = _closeDelimiter;
     
-    _readWhile((c) => const [_SPACE, _TAB, _NEWLINE, _RETURN].contains(c));
+    _readWhile(_isWhitespace);
     
     int c;
     c = _read();
@@ -304,7 +291,7 @@
       _openDelimiterInner = c;
     }
     
-    _readWhile((c) => const [_SPACE, _TAB, _NEWLINE, _RETURN].contains(c));
+    _readWhile(_isWhitespace);
     
     c = _read();
     
@@ -319,11 +306,11 @@
       _closeDelimiter = _read();
     }
     
-    _readWhile((c) => const [_SPACE, _TAB, _NEWLINE, _RETURN].contains(c));
+    _readWhile(_isWhitespace);
     
     _expect(_EQUAL);
     
-    _readWhile((c) => const [_SPACE, _TAB, _NEWLINE, _RETURN].contains(c));     
+    _readWhile(_isWhitespace);     
      
     if (delimiterInner != null) _expect(delimiterInner);
      _expect(delimiter);
@@ -334,7 +321,7 @@
          _closeDelimiterInner,
          _closeDelimiter);
           
-     _tokens.add(new Token(TokenType.changeDelimiter, value, start, _offset));
+     _push(TokenType.changeDelimiter, value, start, _offset);
   }
   
   TemplateException _error(String message) {