Index: sdk/lib/_internal/compiler/implementation/lib/regexp_helper.dart |
diff --git a/sdk/lib/_internal/compiler/implementation/lib/regexp_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/regexp_helper.dart |
index 6b8df4f83849ff3703f7b72bfc58b4ad3d96e711..d5aede5f0f741d164e6b6b028ea0ab334743f514 100644 |
--- a/sdk/lib/_internal/compiler/implementation/lib/regexp_helper.dart |
+++ b/sdk/lib/_internal/compiler/implementation/lib/regexp_helper.dart |
@@ -44,3 +44,126 @@ regExpMakeNative(JSSyntaxRegExp regExp, {bool global: false}) { |
} |
int regExpMatchStart(m) => JS('int', r'#.index', m); |
+ |
+class JSSyntaxRegExp implements RegExp { |
+ final String _pattern; |
+ final bool _multiLine; |
+ final bool _ignoreCase; |
+ |
+ const JSSyntaxRegExp(String pattern, |
+ {bool multiLine: false, |
+ bool ignoreCase: false}) |
+ : _pattern = pattern, |
+ _multiLine = multiLine, |
+ _ignoreCase = ignoreCase; |
+ |
+ Match firstMatch(String str) { |
+ List<String> m = regExpExec(this, checkString(str)); |
+ if (m == null) return null; |
+ var matchStart = regExpMatchStart(m); |
+ // m.lastIndex only works with flag 'g'. |
+ var matchEnd = matchStart + m[0].length; |
+ return new _MatchImplementation(pattern, str, matchStart, matchEnd, m); |
+ } |
+ |
+ bool hasMatch(String str) => regExpTest(this, checkString(str)); |
+ |
+ String stringMatch(String str) { |
+ var match = firstMatch(str); |
+ return match == null ? null : match.group(0); |
+ } |
+ |
+ Iterable<Match> allMatches(String str) { |
+ checkString(str); |
+ return new _AllMatchesIterable(this, str); |
+ } |
+ |
+ String get pattern => _pattern; |
+ bool get multiLine => _multiLine; |
+ bool get ignoreCase => _ignoreCase; |
+ |
+ static JSSyntaxRegExp _globalVersionOf(JSSyntaxRegExp other) { |
+ JSSyntaxRegExp re = new JSSyntaxRegExp(other.pattern, |
+ multiLine: other.multiLine, |
+ ignoreCase: other.ignoreCase); |
+ regExpAttachGlobalNative(re); |
+ return re; |
+ } |
+ |
+ _getNative() => regExpGetNative(this); |
+} |
+ |
+class _MatchImplementation implements Match { |
+ final String pattern; |
+ final String str; |
+ final int start; |
+ final int end; |
+ final List<String> _groups; |
+ |
+ const _MatchImplementation( |
+ String this.pattern, |
+ String this.str, |
+ int this.start, |
+ int this.end, |
+ List<String> this._groups); |
+ |
+ String group(int index) => _groups[index]; |
+ String operator [](int index) => group(index); |
+ int get groupCount => _groups.length - 1; |
+ |
+ List<String> groups(List<int> groups) { |
+ List<String> out = []; |
+ for (int i in groups) { |
+ out.add(group(i)); |
+ } |
+ return out; |
+ } |
+} |
+ |
+class _AllMatchesIterable implements Iterable<Match> { |
+ final JSSyntaxRegExp _re; |
+ final String _str; |
+ |
+ const _AllMatchesIterable(this._re, this._str); |
+ |
+ Iterator<Match> iterator() => new _AllMatchesIterator(_re, _str); |
+} |
+ |
+class _AllMatchesIterator implements Iterator<Match> { |
+ final RegExp _re; |
+ final String _str; |
+ Match _next; |
+ bool _done; |
+ |
+ _AllMatchesIterator(JSSyntaxRegExp re, String this._str) |
+ : _done = false, _re = JSSyntaxRegExp._globalVersionOf(re); |
+ |
+ Match next() { |
+ if (!hasNext) { |
+ throw new StateError("No more elements"); |
+ } |
+ |
+ // _next is set by [hasNext]. |
+ var next = _next; |
+ _next = null; |
+ return next; |
+ } |
+ |
+ bool get hasNext { |
+ if (_done) { |
+ return false; |
+ } else if (_next != null) { |
+ return true; |
+ } |
+ |
+ // firstMatch actually acts as nextMatch because of |
+ // hidden global flag. |
+ _next = _re.firstMatch(_str); |
+ if (_next == null) { |
+ _done = true; |
+ return false; |
+ } else { |
+ return true; |
+ } |
+ } |
+} |