Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(354)

Side by Side Diff: pkg/string_scanner/lib/string_scanner.dart

Issue 213833013: Add a string_scanner package. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: code review Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/string_scanner/README.md ('k') | pkg/string_scanner/pubspec.yaml » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library shelf.string_scanner; 5 /// A library for parsing strings using a sequence of patterns.
6 library string_scanner;
6 7
8 // TODO(nweiz): Add some integration between this and source maps.
7 /// A class that scans through a string using [Pattern]s. 9 /// A class that scans through a string using [Pattern]s.
8 class StringScanner { 10 class StringScanner {
9 /// The string being scanned through. 11 /// The string being scanned through.
10 final String string; 12 final String string;
11 13
12 /// The current position of the scanner in the string, in characters. 14 /// The current position of the scanner in the string, in characters.
13 int get position => _position; 15 int get position => _position;
14 set position(int position) { 16 set position(int position) {
15 if (position < 0 || position > string.length) { 17 if (position < 0 || position > string.length) {
16 throw new ArgumentError("Invalid position $position"); 18 throw new ArgumentError("Invalid position $position");
(...skipping 28 matching lines...) Expand all
45 /// Returns whether or not [pattern] matched. 47 /// Returns whether or not [pattern] matched.
46 bool scan(Pattern pattern) { 48 bool scan(Pattern pattern) {
47 var success = matches(pattern); 49 var success = matches(pattern);
48 if (success) _position = _lastMatch.end; 50 if (success) _position = _lastMatch.end;
49 return success; 51 return success;
50 } 52 }
51 53
52 /// If [pattern] matches at the current position of the string, scans forward 54 /// If [pattern] matches at the current position of the string, scans forward
53 /// until the end of the match. 55 /// until the end of the match.
54 /// 56 ///
55 /// If [pattern] did not match, throws a [FormatException] with [message]. 57 /// If [pattern] did not match, throws a [FormatException] describing the
56 void expect(Pattern pattern, String message) { 58 /// position of the failure. [name] is used in this error as the expected name
59 /// of the pattern being matched; if it's `null`, the pattern itself is used
60 /// instead.
61 void expect(Pattern pattern, {String name}) {
57 if (scan(pattern)) return; 62 if (scan(pattern)) return;
58 throw new FormatException(message); 63
64 if (name == null) {
65 if (pattern is RegExp) {
66 name = "/${pattern.pattern.replaceAll("/", "\\/")}/";
67 } else {
68 name = pattern.toString()
69 .replaceAll("\\", "\\\\").replaceAll('"', '\\"');
70 name = '"$name"';
71 }
72 }
73 _fail(name);
74 }
75
76 /// If the string has not been fully consumed, this throws a
77 /// [FormatException].
78 void expectDone() {
79 if (isDone) return;
80 _fail("no more input");
59 } 81 }
60 82
61 /// Returns whether or not [pattern] matches at the current position of the 83 /// Returns whether or not [pattern] matches at the current position of the
62 /// string. 84 /// string.
63 /// 85 ///
64 /// This doesn't move the scan pointer forward. 86 /// This doesn't move the scan pointer forward.
65 bool matches(Pattern pattern) { 87 bool matches(Pattern pattern) {
66 _lastMatch = pattern.matchAsPrefix(string, position); 88 _lastMatch = pattern.matchAsPrefix(string, position);
67 return _lastMatch != null; 89 return _lastMatch != null;
68 } 90 }
91
92 // TODO(nweiz): Make this handle long lines more gracefully.
93 /// Throws a [FormatException] describing that [name] is expected at the
94 /// current position in the string.
95 void _fail(String name) {
96 var newlines = "\n".allMatches(string.substring(0, position)).toList();
97 var line = newlines.length + 1;
98 var column;
99 var lastLine;
100 if (newlines.isEmpty) {
101 column = position + 1;
102 lastLine = string.substring(0, position);
103 } else {
104 column = position - newlines.last.end + 1;
105 lastLine = string.substring(newlines.last.end, position);
106 }
107 lastLine += rest.replaceFirst(new RegExp(r"\n.*"), '');
108 throw new FormatException(
109 "Expected $name on line $line, column $column.\n"
110 "$lastLine\n"
111 "${new List.filled(column - 1, ' ').join()}^");
112 }
69 } 113 }
OLDNEW
« no previous file with comments | « pkg/string_scanner/README.md ('k') | pkg/string_scanner/pubspec.yaml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698