| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 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 | 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 part of dart._js_helper; | 5 part of dart._js_helper; |
| 6 | 6 |
| 7 // Helper method used by internal libraries. | 7 // Helper method used by internal libraries. |
| 8 regExpGetNative(JSSyntaxRegExp regexp) => regexp._nativeRegExp; | 8 regExpGetNative(JSSyntaxRegExp regexp) => regexp._nativeRegExp; |
| 9 | 9 |
| 10 List<String> _stringList(List l) => l == null ? l : JS('', 'dart.list(#, #)', l,
String); | 10 List<String> _stringList(List l) => |
| 11 l == null ? l : JS('', 'dart.list(#, #)', l, String); |
| 11 | 12 |
| 12 /** | 13 /** |
| 13 * Returns a native version of the RegExp with the global flag set. | 14 * Returns a native version of the RegExp with the global flag set. |
| 14 * | 15 * |
| 15 * The RegExp's `lastIndex` property is zero when it is returned. | 16 * The RegExp's `lastIndex` property is zero when it is returned. |
| 16 * | 17 * |
| 17 * The returned regexp is shared, and its `lastIndex` property may be | 18 * The returned regexp is shared, and its `lastIndex` property may be |
| 18 * modified by other uses, so the returned regexp must be used immediately | 19 * modified by other uses, so the returned regexp must be used immediately |
| 19 * when it's returned, with no user-provided code run in between. | 20 * when it's returned, with no user-provided code run in between. |
| 20 */ | 21 */ |
| (...skipping 23 matching lines...) Expand all Loading... |
| 44 | 45 |
| 45 class JSSyntaxRegExp implements RegExp { | 46 class JSSyntaxRegExp implements RegExp { |
| 46 final String pattern; | 47 final String pattern; |
| 47 final _nativeRegExp; | 48 final _nativeRegExp; |
| 48 var _nativeGlobalRegExp; | 49 var _nativeGlobalRegExp; |
| 49 var _nativeAnchoredRegExp; | 50 var _nativeAnchoredRegExp; |
| 50 | 51 |
| 51 String toString() => "RegExp/$pattern/"; | 52 String toString() => "RegExp/$pattern/"; |
| 52 | 53 |
| 53 JSSyntaxRegExp(String source, | 54 JSSyntaxRegExp(String source, |
| 54 { bool multiLine: false, | 55 {bool multiLine: false, bool caseSensitive: true}) |
| 55 bool caseSensitive: true }) | |
| 56 : this.pattern = source, | 56 : this.pattern = source, |
| 57 this._nativeRegExp = | 57 this._nativeRegExp = |
| 58 makeNative(source, multiLine, caseSensitive, false); | 58 makeNative(source, multiLine, caseSensitive, false); |
| 59 | 59 |
| 60 get _nativeGlobalVersion { | 60 get _nativeGlobalVersion { |
| 61 if (_nativeGlobalRegExp != null) return _nativeGlobalRegExp; | 61 if (_nativeGlobalRegExp != null) return _nativeGlobalRegExp; |
| 62 return _nativeGlobalRegExp = makeNative(pattern, | 62 return _nativeGlobalRegExp = |
| 63 _isMultiLine, | 63 makeNative(pattern, _isMultiLine, _isCaseSensitive, true); |
| 64 _isCaseSensitive, | |
| 65 true); | |
| 66 } | 64 } |
| 67 | 65 |
| 68 get _nativeAnchoredVersion { | 66 get _nativeAnchoredVersion { |
| 69 if (_nativeAnchoredRegExp != null) return _nativeAnchoredRegExp; | 67 if (_nativeAnchoredRegExp != null) return _nativeAnchoredRegExp; |
| 70 // An "anchored version" of a regexp is created by adding "|()" to the | 68 // An "anchored version" of a regexp is created by adding "|()" to the |
| 71 // source. This means that the regexp always matches at the first position | 69 // source. This means that the regexp always matches at the first position |
| 72 // that it tries, and you can see if the original regexp matched, or it | 70 // that it tries, and you can see if the original regexp matched, or it |
| 73 // was the added zero-width match that matched, by looking at the last | 71 // was the added zero-width match that matched, by looking at the last |
| 74 // capture. If it is a String, the match participated, otherwise it didn't. | 72 // capture. If it is a String, the match participated, otherwise it didn't. |
| 75 return _nativeAnchoredRegExp = makeNative("$pattern|()", | 73 return _nativeAnchoredRegExp = |
| 76 _isMultiLine, | 74 makeNative("$pattern|()", _isMultiLine, _isCaseSensitive, true); |
| 77 _isCaseSensitive, | |
| 78 true); | |
| 79 } | 75 } |
| 80 | 76 |
| 81 bool get _isMultiLine => JS("bool", "#.multiline", _nativeRegExp); | 77 bool get _isMultiLine => JS("bool", "#.multiline", _nativeRegExp); |
| 82 bool get _isCaseSensitive => JS("bool", "!#.ignoreCase", _nativeRegExp); | 78 bool get _isCaseSensitive => JS("bool", "!#.ignoreCase", _nativeRegExp); |
| 83 | 79 |
| 84 static makeNative( | 80 static makeNative( |
| 85 String source, bool multiLine, bool caseSensitive, bool global) { | 81 String source, bool multiLine, bool caseSensitive, bool global) { |
| 86 checkString(source); | 82 checkString(source); |
| 87 String m = multiLine ? 'm' : ''; | 83 String m = multiLine ? 'm' : ''; |
| 88 String i = caseSensitive ? '' : 'i'; | 84 String i = caseSensitive ? '' : 'i'; |
| 89 String g = global ? 'g' : ''; | 85 String g = global ? 'g' : ''; |
| 90 // We're using the JavaScript's try catch instead of the Dart one | 86 // We're using the JavaScript's try catch instead of the Dart one |
| 91 // to avoid dragging in Dart runtime support just because of using | 87 // to avoid dragging in Dart runtime support just because of using |
| 92 // RegExp. | 88 // RegExp. |
| 93 var regexp = JS('', | 89 var regexp = JS( |
| 90 '', |
| 94 '(function() {' | 91 '(function() {' |
| 95 'try {' | 92 'try {' |
| 96 'return new RegExp(#, # + # + #);' | 93 'return new RegExp(#, # + # + #);' |
| 97 '} catch (e) {' | 94 '} catch (e) {' |
| 98 'return e;' | 95 'return e;' |
| 99 '}' | 96 '}' |
| 100 '})()', source, m, i, g); | 97 '})()', |
| 98 source, |
| 99 m, |
| 100 i, |
| 101 g); |
| 101 if (JS('bool', '# instanceof RegExp', regexp)) return regexp; | 102 if (JS('bool', '# instanceof RegExp', regexp)) return regexp; |
| 102 // The returned value is the JavaScript exception. Turn it into a | 103 // The returned value is the JavaScript exception. Turn it into a |
| 103 // Dart exception. | 104 // Dart exception. |
| 104 String errorMessage = JS('String', r'String(#)', regexp); | 105 String errorMessage = JS('String', r'String(#)', regexp); |
| 105 throw new FormatException( | 106 throw new FormatException("Illegal RegExp pattern: $source, $errorMessage"); |
| 106 "Illegal RegExp pattern: $source, $errorMessage"); | |
| 107 } | 107 } |
| 108 | 108 |
| 109 Match firstMatch(String string) { | 109 Match firstMatch(String string) { |
| 110 List m = JS('JSExtendableArray|Null', | 110 List m = JS('JSExtendableArray|Null', r'#.exec(#)', _nativeRegExp, |
| 111 r'#.exec(#)', | 111 checkString(string)); |
| 112 _nativeRegExp, | |
| 113 checkString(string)); | |
| 114 if (m == null) return null; | 112 if (m == null) return null; |
| 115 return new _MatchImplementation(this, _stringList(m)); | 113 return new _MatchImplementation(this, _stringList(m)); |
| 116 } | 114 } |
| 117 | 115 |
| 118 bool hasMatch(String string) { | 116 bool hasMatch(String string) { |
| 119 return JS('bool', r'#.test(#)', _nativeRegExp, checkString(string)); | 117 return JS('bool', r'#.test(#)', _nativeRegExp, checkString(string)); |
| 120 } | 118 } |
| 121 | 119 |
| 122 String stringMatch(String string) { | 120 String stringMatch(String string) { |
| 123 var match = firstMatch(string); | 121 var match = firstMatch(string); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 _current = match; | 219 _current = match; |
| 222 int nextIndex = match.end; | 220 int nextIndex = match.end; |
| 223 if (match.start == nextIndex) { | 221 if (match.start == nextIndex) { |
| 224 nextIndex++; | 222 nextIndex++; |
| 225 } | 223 } |
| 226 _nextIndex = nextIndex; | 224 _nextIndex = nextIndex; |
| 227 return true; | 225 return true; |
| 228 } | 226 } |
| 229 } | 227 } |
| 230 _current = null; | 228 _current = null; |
| 231 _string = null; // Marks iteration as ended. | 229 _string = null; // Marks iteration as ended. |
| 232 return false; | 230 return false; |
| 233 } | 231 } |
| 234 } | 232 } |
| 235 | 233 |
| 236 /** Find the first match of [regExp] in [string] at or after [start]. */ | 234 /** Find the first match of [regExp] in [string] at or after [start]. */ |
| 237 Match firstMatchAfter(JSSyntaxRegExp regExp, String string, int start) { | 235 Match firstMatchAfter(JSSyntaxRegExp regExp, String string, int start) { |
| 238 return regExp._execGlobal(string, start); | 236 return regExp._execGlobal(string, start); |
| 239 } | 237 } |
| OLD | NEW |