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

Side by Side Diff: runtime/observatory/lib/src/service/scanner.dart

Issue 1126363005: Show tooltip with local variable value in Observatory debugger (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 7 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
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of service;
6
7 /// A text scanner that keeps track of token position, line, and column.
8 class Scanner {
9 final String string;
10
11 /// The current position of the scanner in the string, in characters.
12 int get tokenPos => _tokenPos;
13 set tokenPos(int newTokenPos) {
14 if (newTokenPos < 0 || newTokenPos > string.length) {
15 throw new ArgumentError("Invalid tokenPos $tokenPos");
16 }
17
18 var oldTokenPos = _tokenPos;
19 _tokenPos = newTokenPos;
20
21 if (newTokenPos > oldTokenPos) {
22 var newlines =
23 "\n".allMatches(string.substring(oldTokenPos, newTokenPos)).toList();
24 _line += newlines.length;
25 if (newlines.isEmpty) {
26 _column += newTokenPos - oldTokenPos;
27 } else {
28 _column = newTokenPos - newlines.last.end;
29 }
30 } else {
31 var newlines =
32 "\n".allMatches(string.substring(newTokenPos, oldTokenPos)).toList();
33 _line -= newlines.length;
34 if (newlines.isEmpty) {
35 _column -= oldTokenPos - newTokenPos;
36 } else {
37 _column = newTokenPos - string.lastIndexOf("\n", newTokenPos) - 1;
38 }
39 }
40 }
41 int _tokenPos = 0;
42
43 /// The scanner's current (zero-based) line number.
44 int get line => _line;
45 int _line = 0;
46
47 /// The scanner's current (zero-based) column number.
48 int get column => _column;
49 int _column = 0;
50
51 /// The scanner's state, including line and column information.
52 ///
53 /// This can be used to efficiently save and restore the state of the scanner
54 /// when backtracking. A given [ScannerState] is only valid for the
55 /// [Scanner] that created it.
56 ScannerState get state => new ScannerState._(this, tokenPos, line, column);
57 set state(ScannerState state) {
58 if (!identical(state._scanner, this)) {
59 throw new ArgumentError("The given LineScannerState was not returned by "
60 "this LineScanner.");
61 }
62
63 _tokenPos = state.tokenPos;
64 _line = state.line;
65 _column = state.column;
66 }
67
68 /// The data about the previous match made by the scanner.
69 ///
70 /// If the last match failed, this will be `null`.
71 Match get lastMatch => _lastMatch;
72 Match _lastMatch;
73
74 /// Whether the scanner has completely consumed [string].
75 bool get isDone => tokenPos == string.length;
76
77 Scanner(this.string, {int tokenPos: 0, int line: 0, int column: 0}) {
78 this._tokenPos = tokenPos;
79 this._line = line;
80 this._column = column;
81 }
82
83 /// Consumes a single character and returns its character code.
84 ///
85 /// This throws a [FormatException] if the string has been fully consumed. It
86 /// doesn't affect [lastMatch].
87 int readChar() {
88 if (isDone) {
89 throw new FormatException('no more input');
90 }
91 var char = string.codeUnitAt(_tokenPos++);
92 if (char == 0xA) {
93 _line += 1;
94 _column = 0;
95 } else {
96 _column += 1;
97 }
98 return char;
99 }
100
101 /// Returns the character code of the character [offset] away from [tokenPos].
102 ///
103 /// [offset] defaults to zero, and may be negative to inspect already-consumed
104 /// characters.
105 ///
106 /// This returns `null` if [offset] points outside the string. It doesn't
107 /// affect [lastMatch].
108 int peekChar([int offset = 0]) {
109 var index = tokenPos + offset;
110 if (index < 0 || index >= string.length) {
111 return null;
112 }
113 return string.codeUnitAt(index);
114 }
115
116 /// If [pattern] matches at the current tokenPos of the string, scans forward
117 /// until the end of the match.
118 ///
119 /// Returns whether or not [pattern] matched.
120 bool scan(Pattern pattern) {
121 var success = matches(pattern);
122 if (!success) {
123 return success;
124 }
125 _tokenPos = _lastMatch.end;
126 var newlines = "\n".allMatches(lastMatch[0]).toList();
127 _line += newlines.length;
128 if (newlines.isEmpty) {
129 _column += lastMatch[0].length;
130 } else {
131 _column = lastMatch[0].length - newlines.last.end;
132 }
133
134 return true;
135 }
136
137 /// If [pattern] matches at the current tokenPos of the string, scans forward
138 /// until the end of the match.
139 ///
140 /// If [pattern] did not match, throws a [FormatException] describing the
141 /// tokenPos of the failure.
142 void expect(Pattern pattern, {String name}) {
143 if (scan(pattern)) {
144 return;
145 }
146 throw new FormatException('expect($pattern) failed.');
147 }
148
149 /// If the string has not been fully consumed, this throws a
150 /// [FormatException].
151 void expectDone() {
152 if (isDone) {
153 return;
154 }
155 throw new FormatException('not done');
156 }
157
158 /// Returns whether or not [pattern] matches at the current tokenPos of the
159 /// string.
160 ///
161 /// This doesn't move the scan pointer forward.
162 bool matches(Pattern pattern) {
163 _lastMatch = pattern.matchAsPrefix(string, tokenPos);
164 return _lastMatch != null;
165 }
166
167 /// Returns the substring of [string] between [start] and [end].
168 ///
169 /// Unlike [String.substring], [end] defaults to [tokenPos] rather than the
170 /// end of the string.
171 String substring(int start, [int end]) {
172 if (end == null) end = tokenPos;
173 return string.substring(start, end);
174 }
175 }
176
177 /// A class representing the state of a [LineScanner].
178 class ScannerState {
179 /// The [LineScanner] that created this.
180 final Scanner _scanner;
181
182 /// The position of the scanner in this state.
183 final int tokenPos;
184
185 /// The zero-based line number of the scanner in this state.
186 final int line;
187
188 /// The zero-based column number of the scanner in this state.
189 final int column;
190
191 ScannerState._(this._scanner, this.tokenPos, this.line, this.column);
192 }
193
194 class ScannedRegion {
195 final ScannerState start;
196 final ScannerState end;
197 ScannedRegion(this.start, this.end);
198
199 bool contained(int line, int column) {
200 // TODO(johnmccutchan): Fix.
201 return false;
202 }
203 }
204
205 /// Computes a list of source regions that are Dart source code comments.
206 /// Handles comments that span multiple lines.
207 class CommentScanner {
208 Scanner _scanner;
209
210 CommentScanner(String source, {int tokenPos: 0, int line: 0, int column: 0}) {
211 _scanner =
212 new Scanner(source, tokenPos: tokenPos, line: line, column: column);
213 }
214
215 void scan() {
216 }
217
218 final List<ScannedRegion> comments = [];
219 }
220
221 /// Computes a list of source regions that are Dart string literals. Will split
222 /// string literal regions that include $expr or ${expr} regions into two string
223 /// literals (one before and one after). Handles string literals that span
224 /// multiple lines.
225 class StringLiteralScanner {
226 Scanner _scanner;
227 CommentScanner(String source, {int tokenPos: 0, int line: 0, int column: 0}) {
228 _scanner =
229 new Scanner(source, tokenPos: tokenPos, line: line, column: column);
230 }
231
232 void scan() {
233 }
234
235 final List<ScannedRegion> stringLiterals = [];
236 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698