Improve performance by not doing binary searches.

Normally getting the line and column of a SpanScanner or a
SourceLocation needs a binary search through all the line endings in the
source file. This CL avoids those searches by using an eager SpanScanner
which does extra computation to track its current line and column
position, and storing the line and column directly on _SimpleKey
objects.

See dart-lang/yaml#12

R=rnystrom@google.com

Review URL: https://codereview.chromium.org//1325133002 .
diff --git a/pkgs/yaml/lib/src/scanner.dart b/pkgs/yaml/lib/src/scanner.dart
index 512d72e..2e02a8f 100644
--- a/pkgs/yaml/lib/src/scanner.dart
+++ b/pkgs/yaml/lib/src/scanner.dart
@@ -292,7 +292,7 @@
   ///
   /// [sourceUrl] can be a String or a [Uri].
   Scanner(String source, {sourceUrl})
-      : _scanner = new SpanScanner(source, sourceUrl: sourceUrl);
+      : _scanner = new SpanScanner.eager(source, sourceUrl: sourceUrl);
 
   /// Consumes and returns the next token.
   Token scan() {
@@ -485,7 +485,7 @@
       // everything but multiline simple keys in a block context.
       if (!_inBlockContext) continue;
 
-      if (key.location.line == _scanner.line) continue;
+      if (key.line == _scanner.line) continue;
 
       if (key.required) {
         throw new YamlException("Expected ':'.", _scanner.emptySpan);
@@ -513,6 +513,8 @@
     _removeSimpleKey();
     _simpleKeys[_simpleKeys.length - 1] = new _SimpleKey(
         _tokensParsed + _tokens.length,
+        _scanner.line,
+        _scanner.column,
         _scanner.location,
         required: required);
   }
@@ -660,7 +662,7 @@
       _rollIndent(
           _scanner.column,
           TokenType.BLOCK_SEQUENCE_START,
-          _scanner.emptySpan.start);
+          _scanner.location);
     } else {
       // It is an error for the '-' indicator to occur in the flow context, but
       // we let the Parser detect and report it because it's able to point to
@@ -683,7 +685,7 @@
       _rollIndent(
           _scanner.column,
           TokenType.BLOCK_MAPPING_START,
-          _scanner.emptySpan.start);
+          _scanner.location);
     }
 
     // Simple keys are allowed after `?` in a block context.
@@ -703,7 +705,7 @@
       // In the block context, we may need to add the
       // [TokenType.BLOCK_MAPPING_START] token.
       _rollIndent(
-          simpleKey.location.column,
+          simpleKey.column,
           TokenType.BLOCK_MAPPING_START,
           simpleKey.location,
           tokenNumber: simpleKey.tokenNumber);
@@ -1639,10 +1641,23 @@
   /// no longer on the current line.
   final SourceLocation location;
 
+  /// The line on which the key appears.
+  ///
+  /// We could get this from [location], but that requires a binary search
+  /// whereas this is O(1).
+  final int line;
+
+  /// The column on which the key appears.
+  ///
+  /// We could get this from [location], but that requires a binary search
+  /// whereas this is O(1).
+  final int column;
+
   /// Whether this key must exist for the document to be scanned.
   final bool required;
 
-  _SimpleKey(this.tokenNumber, this.location, {bool required})
+  _SimpleKey(this.tokenNumber, this.line, this.column, this.location,
+          {bool required})
       : required = required;
 }
 
diff --git a/pkgs/yaml/pubspec.yaml b/pkgs/yaml/pubspec.yaml
index a25faa6..618f82b 100644
--- a/pkgs/yaml/pubspec.yaml
+++ b/pkgs/yaml/pubspec.yaml
@@ -4,11 +4,12 @@
 homepage: https://github.com/dart-lang/yaml
 description: A parser for YAML.
 dependencies:
+  charcode: "^1.1.0"
   collection: ">=1.1.0 <2.0.0"
   path: ">=1.2.0 <2.0.0"
-  string_scanner: ">=0.1.3 <0.2.0"
+  string_scanner: "^0.1.4"
   source_span: ">=1.0.0 <2.0.0"
 dev_dependencies:
   test: ">=0.12.0 <0.13.0"
 environment:
-  sdk: '>=1.5.0 <2.0.0'
+  sdk: '>=1.8.0 <2.0.0'