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

Side by Side Diff: sdk/lib/_internal/lib/regexp_helper.dart

Issue 538513002: Move js library back into compiler directory. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 3 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 | « sdk/lib/_internal/lib/preambles/jsshell.js ('k') | sdk/lib/_internal/lib/string_helper.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012, 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 _js_helper;
6
7 // Helper method used by internal libraries.
8 regExpGetNative(JSSyntaxRegExp regexp) => regexp._nativeRegExp;
9
10 /**
11 * Returns a native version of the RegExp with the global flag set.
12 *
13 * The RegExp's `lastIndex` property is zero when it is returned.
14 *
15 * The returned regexp is shared, and its `lastIndex` property may be
16 * modified by other uses, so the returned regexp must be used immediately
17 * when it's returned, with no user-provided code run in between.
18 */
19 regExpGetGlobalNative(JSSyntaxRegExp regexp) {
20 var nativeRegexp = regexp._nativeGlobalVersion;
21 JS("void", "#.lastIndex = 0", nativeRegexp);
22 return nativeRegexp;
23 }
24
25 class JSSyntaxRegExp implements RegExp {
26 final String pattern;
27 final _nativeRegExp;
28 var _nativeGlobalRegExp;
29 var _nativeAnchoredRegExp;
30
31
32 JSSyntaxRegExp(String source,
33 { bool multiLine: false,
34 bool caseSensitive: true })
35 : this.pattern = source,
36 this._nativeRegExp =
37 makeNative(source, multiLine, caseSensitive, false);
38
39 get _nativeGlobalVersion {
40 if (_nativeGlobalRegExp != null) return _nativeGlobalRegExp;
41 return _nativeGlobalRegExp = makeNative(pattern,
42 _isMultiLine,
43 _isCaseSensitive,
44 true);
45 }
46
47 get _nativeAnchoredVersion {
48 if (_nativeAnchoredRegExp != null) return _nativeAnchoredRegExp;
49 // An "anchored version" of a regexp is created by adding "|()" to the
50 // source. This means that the regexp always matches at the first position
51 // that it tries, and you can see if the original regexp matched, or it
52 // was the added zero-width match that matched, by looking at the last
53 // capture. If it is a String, the match participated, otherwise it didn't.
54 return _nativeAnchoredRegExp = makeNative("$pattern|()",
55 _isMultiLine,
56 _isCaseSensitive,
57 true);
58 }
59
60 bool get _isMultiLine => JS("bool", "#.multiline", _nativeRegExp);
61 bool get _isCaseSensitive => JS("bool", "!#.ignoreCase", _nativeRegExp);
62
63 static makeNative(
64 String source, bool multiLine, bool caseSensitive, bool global) {
65 checkString(source);
66 String m = multiLine ? 'm' : '';
67 String i = caseSensitive ? '' : 'i';
68 String g = global ? 'g' : '';
69 // We're using the JavaScript's try catch instead of the Dart one
70 // to avoid dragging in Dart runtime support just because of using
71 // RegExp.
72 var regexp = JS('',
73 '(function() {'
74 'try {'
75 'return new RegExp(#, # + # + #);'
76 '} catch (e) {'
77 'return e;'
78 '}'
79 '})()', source, m, i, g);
80 if (JS('bool', '# instanceof RegExp', regexp)) return regexp;
81 // The returned value is the JavaScript exception. Turn it into a
82 // Dart exception.
83 String errorMessage = JS('String', r'String(#)', regexp);
84 throw new FormatException(
85 "Illegal RegExp pattern: $source, $errorMessage");
86 }
87
88 Match firstMatch(String string) {
89 List<String> m = JS('JSExtendableArray|Null',
90 r'#.exec(#)',
91 _nativeRegExp,
92 checkString(string));
93 if (m == null) return null;
94 return new _MatchImplementation(this, m);
95 }
96
97 bool hasMatch(String string) {
98 return JS('bool', r'#.test(#)', _nativeRegExp, checkString(string));
99 }
100
101 String stringMatch(String string) {
102 var match = firstMatch(string);
103 if (match != null) return match.group(0);
104 return null;
105 }
106
107 Iterable<Match> allMatches(String string, [int start = 0]) {
108 checkString(string);
109 checkInt(start);
110 if (start < 0 || start > string.length) {
111 throw new RangeError.range(start, 0, string.length);
112 }
113 return new _AllMatchesIterable(this, string, start);
114 }
115
116 Match _execGlobal(String string, int start) {
117 Object regexp = _nativeGlobalVersion;
118 JS("void", "#.lastIndex = #", regexp, start);
119 List match = JS("JSExtendableArray|Null", "#.exec(#)", regexp, string);
120 if (match == null) return null;
121 return new _MatchImplementation(this, match);
122 }
123
124 Match _execAnchored(String string, int start) {
125 Object regexp = _nativeAnchoredVersion;
126 JS("void", "#.lastIndex = #", regexp, start);
127 List match = JS("JSExtendableArray|Null", "#.exec(#)", regexp, string);
128 if (match == null) return null;
129 // If the last capture group participated, the original regexp did not
130 // match at the start position.
131 if (match[match.length - 1] != null) return null;
132 match.length -= 1;
133 return new _MatchImplementation(this, match);
134 }
135
136 Match matchAsPrefix(String string, [int start = 0]) {
137 if (start < 0 || start > string.length) {
138 throw new RangeError.range(start, 0, string.length);
139 }
140 return _execAnchored(string, start);
141 }
142
143 bool get isMultiLine => _isMultiLine;
144 bool get isCaseSensitive => _isCaseSensitive;
145 }
146
147 class _MatchImplementation implements Match {
148 final Pattern pattern;
149 // Contains a JS RegExp match object.
150 // It is an Array of String values with extra "index" and "input" properties.
151 final List<String> _match;
152
153 _MatchImplementation(this.pattern, this._match) {
154 assert(JS("var", "#.input", _match) is String);
155 assert(JS("var", "#.index", _match) is int);
156 }
157
158 String get input => JS("String", "#.input", _match);
159 int get start => JS("int", "#.index", _match);
160 int get end => start + _match[0].length;
161
162 String group(int index) => _match[index];
163 String operator [](int index) => group(index);
164 int get groupCount => _match.length - 1;
165
166 List<String> groups(List<int> groups) {
167 List<String> out = [];
168 for (int i in groups) {
169 out.add(group(i));
170 }
171 return out;
172 }
173 }
174
175 class _AllMatchesIterable extends IterableBase<Match> {
176 final JSSyntaxRegExp _re;
177 final String _string;
178 final int _start;
179
180 _AllMatchesIterable(this._re, this._string, this._start);
181
182 Iterator<Match> get iterator => new _AllMatchesIterator(_re, _string, _start);
183 }
184
185 class _AllMatchesIterator implements Iterator<Match> {
186 final JSSyntaxRegExp _regExp;
187 String _string;
188 int _nextIndex;
189 Match _current;
190
191 _AllMatchesIterator(this._regExp, this._string, this._nextIndex);
192
193 Match get current => _current;
194
195 bool moveNext() {
196 if (_string == null) return false;
197 if (_nextIndex <= _string.length) {
198 var match = _regExp._execGlobal(_string, _nextIndex);
199 if (match != null) {
200 _current = match;
201 int nextIndex = match.end;
202 if (match.start == nextIndex) {
203 nextIndex++;
204 }
205 _nextIndex = nextIndex;
206 return true;
207 }
208 }
209 _current = null;
210 _string = null; // Marks iteration as ended.
211 return false;
212 }
213 }
214
215 /** Find the first match of [regExp] in [string] at or after [start]. */
216 Match firstMatchAfter(JSSyntaxRegExp regExp, String string, int start) {
217 return regExp._execGlobal(string, start);
218 }
OLDNEW
« no previous file with comments | « sdk/lib/_internal/lib/preambles/jsshell.js ('k') | sdk/lib/_internal/lib/string_helper.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698