Make YamlException inherit from SpanFormatException.

R=rnystrom@google.com

Review URL: https://codereview.chromium.org//342943006

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/yaml@37618 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 261a666..fdd9240 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,11 @@
+## 1.1.0
+
+* Make `YamlException` inherit from source_map's [`SpanFormatException`][]. This
+  improves the error formatting and allows callers access to source range
+  information.
+
+[SpanFormatException]: (http://www.dartdocs.org/documentation/source_maps/0.9.2/index.html#source_maps/source_maps.SpanFormatException)
+
 ## 1.0.0+1
 
 * Fix a variable name typo.
diff --git a/lib/src/composer.dart b/lib/src/composer.dart
index 1a23bc6..8612067 100644
--- a/lib/src/composer.dart
+++ b/lib/src/composer.dart
@@ -34,7 +34,8 @@
   /// Returns the anchor to which an alias node refers.
   Node visitAlias(AliasNode alias) {
     if (!_anchors.containsKey(alias.anchor)) {
-      throw new YamlException("No anchor for alias ${alias.anchor}.");
+      throw new YamlException("No anchor for alias ${alias.anchor}.",
+          alias.span);
     }
     return _anchors[alias.anchor];
   }
@@ -56,8 +57,8 @@
 
     var result = _parseByTag(scalar);
     if (result != null) return setAnchor(scalar, result);
-    throw new YamlException('Invalid literal for ${scalar.tag}: '
-        '"${scalar.content}".');
+    throw new YamlException('Invalid literal for ${scalar.tag}.',
+        scalar.span);
   }
 
   ScalarNode _parseByTag(ScalarNode scalar) {
@@ -68,14 +69,15 @@
       case "float": return parseFloat(scalar);
       case "str": return parseString(scalar);
     }
-    throw new YamlException('Undefined tag: ${scalar.tag}.');
+    throw new YamlException('Undefined tag: ${scalar.tag}.', scalar.span);
   }
 
   /// Assigns a tag to the sequence and recursively composes its contents.
   Node visitSequence(SequenceNode seq) {
     var tagName = seq.tag.name;
     if (tagName != "!" && tagName != "?" && tagName != Tag.yaml("seq")) {
-      throw new YamlException("Invalid tag for sequence: ${seq.tag}.");
+      throw new YamlException("Invalid tag for sequence: ${seq.tag}.",
+          seq.span);
     }
 
     var result = setAnchor(seq,
@@ -88,7 +90,8 @@
   Node visitMapping(MappingNode map) {
     var tagName = map.tag.name;
     if (tagName != "!" && tagName != "?" && tagName != Tag.yaml("map")) {
-      throw new YamlException("Invalid tag for mapping: ${map.tag}.");
+      throw new YamlException("Invalid tag for mapping: ${map.tag}.",
+          map.span);
     }
 
     var result = setAnchor(map,
diff --git a/lib/src/model.dart b/lib/src/model.dart
index f0e839c..0973769 100644
--- a/lib/src/model.dart
+++ b/lib/src/model.dart
@@ -208,7 +208,7 @@
       return '"${escapedValue.join()}"';
     }
 
-    throw new YamlException('Unknown scalar value: "$value".');
+    throw new YamlException('Unknown scalar value.', span);
   }
 
   String toString() => '$tag "$content"';
diff --git a/lib/src/yaml_exception.dart b/lib/src/yaml_exception.dart
index a863274..9d43717 100644
--- a/lib/src/yaml_exception.dart
+++ b/lib/src/yaml_exception.dart
@@ -4,12 +4,11 @@
 
 library yaml.exception;
 
+import 'package:source_maps/source_maps.dart';
+
 /// An error thrown by the YAML processor.
-class YamlException implements Exception {
-  final String _msg;
-
-  YamlException(this._msg);
-
-  String toString() => _msg;
+class YamlException extends SpanFormatException {
+  YamlException(String message, Span span)
+      : super(message, span);
 }
 
diff --git a/lib/yaml.dart b/lib/yaml.dart
index f59719d..80a6319 100644
--- a/lib/yaml.dart
+++ b/lib/yaml.dart
@@ -4,6 +4,8 @@
 
 library yaml;
 
+import 'package:string_scanner/string_scanner.dart';
+
 import 'src/composer.dart';
 import 'src/constructor.dart';
 import 'src/parser.dart';
@@ -40,7 +42,8 @@
 YamlNode loadYamlNode(String yaml, {String sourceName}) {
   var stream = loadYamlStream(yaml, sourceName: sourceName);
   if (stream.length != 1) {
-    throw new YamlException("Expected 1 document, were ${stream.length}.");
+    throw new YamlException("Expected 1 document, were ${stream.length}.",
+        stream.span);
   }
   return stream.nodes[0];
 }
@@ -62,8 +65,8 @@
   var pair;
   try {
     pair = new Parser(yaml, sourceName).l_yamlStream();
-  } on FormatException catch (error) {
-    throw new YamlException(error.toString());
+  } on StringScannerException catch (error) {
+    throw new YamlException(error.message, error.span);
   }
 
   var nodes = pair.first
diff --git a/pubspec.yaml b/pubspec.yaml
index b783228..d8eefd4 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,11 +1,12 @@
 name: yaml
-version: 1.0.0+2
+version: 1.1.0-dev
 author: "Dart Team <misc@dartlang.org>"
 homepage: http://www.dartlang.org
 description: A parser for YAML.
 dependencies:
   collection: ">=0.9.2 <0.10.0"
   string_scanner: ">=0.0.2 <0.1.0"
+  source_maps: ">=0.9.2 <0.10.0"
 dev_dependencies:
   unittest: ">=0.9.0 <0.12.0"
 environment: