Add source location to error messages
diff --git a/lib/scanner.dart b/lib/scanner.dart
index 6943ab6..05d057d 100644
--- a/lib/scanner.dart
+++ b/lib/scanner.dart
@@ -57,9 +57,14 @@
 		_tokens.add(new _Token(type, value, l, c));

 	}

 

-	_expect(int c) {

-		if (c != _read())

-			throw new FormatException('Expected character: ${new String.fromCharCode(c)}');

+	_expect(int expectedCharCode) {

+		int c = _read();

+		if (c != expectedCharCode) {

+			throw new FormatException('Unexpected character, '

+				'expected: ${new String.fromCharCode(expectedCharCode)} ($expectedCharCode), '

+				'was: ${new String.fromCharCode(c)} ($c), '

+				'at: ${_r.line}:${_r.column}');

+		}

 	}

 

 	String _readString() => _r.readWhile(

diff --git a/lib/template.dart b/lib/template.dart
index ca5cc50..916141c 100644
--- a/lib/template.dart
+++ b/lib/template.dart
@@ -21,11 +21,20 @@
 		if (t.type == _TEXT || t.type == _VARIABLE) {

 			stack.last.children.add(new _Node.fromToken(t));

 		} else if (t.type == _OPEN_SECTION || t.type == _OPEN_INV_SECTION) {

+			//TODO in strict mode limit characters allowed in tag names.

 			var child = new _Node.fromToken(t);

 			stack.last.children.add(child);

 			stack.add(child);

+

 		} else if (t.type == _CLOSE_SECTION) {

-			assert(stack.last.value == t.value); //FIXME throw an exception if these don't match.

+			//TODO in strict mode limit characters allowed in tag names.

+			if (stack.last.value != t.value) {

+				throw new FormatException('Mismatched tags, '

+					'expected: ${stack.last.value}, '

+					'was: t.value, '

+					'at: ${t.line}:${t.column}.');

+			}

+

 			stack.removeLast();

 		} else {

 			throw new UnimplementedError();