| 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 _js_helper; | 5 part of _js_helper; |
| 6 | 6 |
| 7 List regExpExec(JSSyntaxRegExp regExp, String str) { | 7 List regExpExec(JSSyntaxRegExp regExp, String str) { |
| 8 var nativeRegExp = regExpGetNative(regExp); | 8 var nativeRegExp = regExpGetNative(regExp); |
| 9 var result = JS('=List', r'#.exec(#)', nativeRegExp, str); | 9 var result = JS('=List', r'#.exec(#)', nativeRegExp, str); |
| 10 if (JS('bool', r'# == null', result)) return null; | 10 if (JS('bool', r'# == null', result)) return null; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 } | 23 } |
| 24 return r; | 24 return r; |
| 25 } | 25 } |
| 26 | 26 |
| 27 regExpAttachGlobalNative(JSSyntaxRegExp regExp) { | 27 regExpAttachGlobalNative(JSSyntaxRegExp regExp) { |
| 28 JS('void', r'#._re = #', regExp, regExpMakeNative(regExp, global: true)); | 28 JS('void', r'#._re = #', regExp, regExpMakeNative(regExp, global: true)); |
| 29 } | 29 } |
| 30 | 30 |
| 31 regExpMakeNative(JSSyntaxRegExp regExp, {bool global: false}) { | 31 regExpMakeNative(JSSyntaxRegExp regExp, {bool global: false}) { |
| 32 String pattern = regExp.pattern; | 32 String pattern = regExp.pattern; |
| 33 bool multiLine = regExp.multiLine; | 33 bool isMultiLine = regExp.isMultiLine; |
| 34 bool ignoreCase = regExp.ignoreCase; | 34 bool isCaseSensitive = regExp.isCaseSensitive; |
| 35 checkString(pattern); | 35 checkString(pattern); |
| 36 StringBuffer sb = new StringBuffer(); | 36 StringBuffer sb = new StringBuffer(); |
| 37 if (multiLine) sb.add('m'); | 37 if (isMultiLine) sb.add('m'); |
| 38 if (ignoreCase) sb.add('i'); | 38 if (!isCaseSensitive) sb.add('i'); |
| 39 if (global) sb.add('g'); | 39 if (global) sb.add('g'); |
| 40 try { | 40 try { |
| 41 return JS('var', r'new RegExp(#, #)', pattern, sb.toString()); | 41 return JS('var', r'new RegExp(#, #)', pattern, sb.toString()); |
| 42 } catch (e) { | 42 } catch (e) { |
| 43 throw new IllegalJSRegExpException(pattern, | 43 throw new IllegalJSRegExpException(pattern, |
| 44 JS('String', r'String(#)', e)); | 44 JS('String', r'String(#)', e)); |
| 45 } | 45 } |
| 46 } | 46 } |
| 47 | 47 |
| 48 int regExpMatchStart(m) => JS('int', r'#.index', m); | 48 int regExpMatchStart(m) => JS('int', r'#.index', m); |
| 49 | 49 |
| 50 class JSSyntaxRegExp implements RegExp { | 50 class JSSyntaxRegExp implements RegExp { |
| 51 final String _pattern; | 51 final String _pattern; |
| 52 final bool _multiLine; | 52 final bool _isMultiLine; |
| 53 final bool _ignoreCase; | 53 final bool _isCaseSensitive; |
| 54 | 54 |
| 55 const JSSyntaxRegExp(String pattern, | 55 const JSSyntaxRegExp(String pattern, |
| 56 {bool multiLine: false, | 56 {bool multiLine: false, |
| 57 bool ignoreCase: false}) | 57 bool caseSensitive: true}) |
| 58 : _pattern = pattern, | 58 : _pattern = pattern, |
| 59 _multiLine = multiLine, | 59 _isMultiLine = multiLine, |
| 60 _ignoreCase = ignoreCase; | 60 _isCaseSensitive = caseSensitive; |
| 61 | 61 |
| 62 Match firstMatch(String str) { | 62 Match firstMatch(String str) { |
| 63 List<String> m = regExpExec(this, checkString(str)); | 63 List<String> m = regExpExec(this, checkString(str)); |
| 64 if (m == null) return null; | 64 if (m == null) return null; |
| 65 var matchStart = regExpMatchStart(m); | 65 var matchStart = regExpMatchStart(m); |
| 66 // m.lastIndex only works with flag 'g'. | 66 // m.lastIndex only works with flag 'g'. |
| 67 var matchEnd = matchStart + m[0].length; | 67 var matchEnd = matchStart + m[0].length; |
| 68 return new _MatchImplementation(pattern, str, matchStart, matchEnd, m); | 68 return new _MatchImplementation(pattern, str, matchStart, matchEnd, m); |
| 69 } | 69 } |
| 70 | 70 |
| 71 bool hasMatch(String str) => regExpTest(this, checkString(str)); | 71 bool hasMatch(String str) => regExpTest(this, checkString(str)); |
| 72 | 72 |
| 73 String stringMatch(String str) { | 73 String stringMatch(String str) { |
| 74 var match = firstMatch(str); | 74 var match = firstMatch(str); |
| 75 return match == null ? null : match.group(0); | 75 return match == null ? null : match.group(0); |
| 76 } | 76 } |
| 77 | 77 |
| 78 Iterable<Match> allMatches(String str) { | 78 Iterable<Match> allMatches(String str) { |
| 79 checkString(str); | 79 checkString(str); |
| 80 return new _AllMatchesIterable(this, str); | 80 return new _AllMatchesIterable(this, str); |
| 81 } | 81 } |
| 82 | 82 |
| 83 String get pattern => _pattern; | 83 String get pattern => _pattern; |
| 84 bool get multiLine => _multiLine; | 84 bool get isMultiLine => _isMultiLine; |
| 85 bool get ignoreCase => _ignoreCase; | 85 bool get isCaseSensitive => _isCaseSensitive; |
| 86 | 86 |
| 87 static JSSyntaxRegExp _globalVersionOf(JSSyntaxRegExp other) { | 87 static JSSyntaxRegExp _globalVersionOf(JSSyntaxRegExp other) { |
| 88 JSSyntaxRegExp re = new JSSyntaxRegExp(other.pattern, | 88 JSSyntaxRegExp re = |
| 89 multiLine: other.multiLine, | 89 new JSSyntaxRegExp(other.pattern, |
| 90 ignoreCase: other.ignoreCase); | 90 multiLine: other.isMultiLine, |
| 91 caseSensitive: other.isCaseSensitive); |
| 91 regExpAttachGlobalNative(re); | 92 regExpAttachGlobalNative(re); |
| 92 return re; | 93 return re; |
| 93 } | 94 } |
| 94 | 95 |
| 95 _getNative() => regExpGetNative(this); | 96 _getNative() => regExpGetNative(this); |
| 96 } | 97 } |
| 97 | 98 |
| 98 class _MatchImplementation implements Match { | 99 class _MatchImplementation implements Match { |
| 99 final String pattern; | 100 final String pattern; |
| 100 final String str; | 101 final String str; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 115 | 116 |
| 116 List<String> groups(List<int> groups) { | 117 List<String> groups(List<int> groups) { |
| 117 List<String> out = []; | 118 List<String> out = []; |
| 118 for (int i in groups) { | 119 for (int i in groups) { |
| 119 out.add(group(i)); | 120 out.add(group(i)); |
| 120 } | 121 } |
| 121 return out; | 122 return out; |
| 122 } | 123 } |
| 123 } | 124 } |
| 124 | 125 |
| 125 class _AllMatchesIterable implements Iterable<Match> { | 126 class _AllMatchesIterable extends Iterable<Match> { |
| 126 final JSSyntaxRegExp _re; | 127 final JSSyntaxRegExp _re; |
| 127 final String _str; | 128 final String _str; |
| 128 | 129 |
| 129 const _AllMatchesIterable(this._re, this._str); | 130 const _AllMatchesIterable(this._re, this._str); |
| 130 | 131 |
| 131 Iterator<Match> iterator() => new _AllMatchesIterator(_re, _str); | 132 Iterator<Match> get iterator => new _AllMatchesIterator(_re, _str); |
| 132 } | 133 } |
| 133 | 134 |
| 134 class _AllMatchesIterator implements Iterator<Match> { | 135 class _AllMatchesIterator implements Iterator<Match> { |
| 135 final RegExp _re; | 136 final RegExp _re; |
| 136 final String _str; | 137 final String _str; |
| 137 Match _next; | 138 Match _current; |
| 138 bool _done; | |
| 139 | 139 |
| 140 _AllMatchesIterator(JSSyntaxRegExp re, String this._str) | 140 _AllMatchesIterator(JSSyntaxRegExp re, String this._str) |
| 141 : _done = false, _re = JSSyntaxRegExp._globalVersionOf(re); | 141 : _re = JSSyntaxRegExp._globalVersionOf(re); |
| 142 | 142 |
| 143 Match next() { | 143 Match get current => _current; |
| 144 if (!hasNext) { | |
| 145 throw new StateError("No more elements"); | |
| 146 } | |
| 147 | 144 |
| 148 // _next is set by [hasNext]. | 145 bool moveNext() { |
| 149 var next = _next; | |
| 150 _next = null; | |
| 151 return next; | |
| 152 } | |
| 153 | |
| 154 bool get hasNext { | |
| 155 if (_done) { | |
| 156 return false; | |
| 157 } else if (_next != null) { | |
| 158 return true; | |
| 159 } | |
| 160 | |
| 161 // firstMatch actually acts as nextMatch because of | 146 // firstMatch actually acts as nextMatch because of |
| 162 // hidden global flag. | 147 // hidden global flag. |
| 163 _next = _re.firstMatch(_str); | 148 _current = _re.firstMatch(_str); |
| 164 if (_next == null) { | 149 return _current != null; |
| 165 _done = true; | |
| 166 return false; | |
| 167 } else { | |
| 168 return true; | |
| 169 } | |
| 170 } | 150 } |
| 171 } | 151 } |
| OLD | NEW |