blob: e79c2b0a7a170f40dc9283e46d4a2d9c22626716 [file] [log] [blame]
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
/// @assertion complex example with everything
///
/// mixin EnumComparable<T extends Enum> on Enum implements Comparable<T> {
/// int compareTo(T other) => this.index - other.index;
/// }
///
/// // With type argument, mixin and interface.
/// enum Complex<T extends Pattern> with EnumComparable<Complex> implements Pattern {
/// whitespace<RegExp>(r"\s+", RegExp.new),
/// alphanum<RegExp>.captured(r"\w+", RegExp.new),
/// anychar<Glob>("?", Glob.new),
/// ;
///
/// // Static variables. (Could use Expando, this is more likely efficient.)
/// static final List<Pattern?> _patterns = List<Pattern?>.filled(3, null);
///
/// // Final instance variables.
/// final String _patternSource;
/// final T Function(String) _factory;
///
/// // Unnamed constructor. Non-redirecting.
/// const Complex(String pattern, T Function(String) factory)
/// : _patternSource = pattern, _factory = factory;
///
/// // Factory construtor.
/// factory Complex.matching(String text) {
/// for (var value in values) {
/// if (value.allMatches(text).isNotEmpty && value is Complex<T>) {
/// return value;
/// }
/// }
/// throw UnsupportedError("No pattern matching: $text");
/// }
///
/// // Named constructor. Redirecting.
/// const Complex.captured(String regexpPattern)
/// : this("($regexpPattern)", RegExp);
///
/// // Can expose the implicit name.
/// String get name => EnumName(this).name;
///
/// // Instance getter.
/// Pattern get pattern => _patterns[this.index] ??= _factory(_pattern);
///
/// // Instance methods.
/// Iterable<Match> allMatches(String input, [int start = 0]) =>
/// pattern.allMatches(input, start);
///
/// Match? matchAsPrefix(String input, [int start = 0]) =>
/// pattern.matchAsPrefix(input, start);
///
/// // Specifies `toString`.
/// String toString() => "Complex<$T>($_patternSource)";
/// }
///
/// @description Check the example from the specification
/// @author sgrekhov@unipro.ru
// SharedOptions=--enable-experiment=enhanced-enums
import "../../Utils/expect.dart";
mixin EnumComparable<T extends Enum> on Enum implements Comparable<T> {
int compareTo(T other) => this.index - other.index;
}
// With type argument, mixin and interface.
enum Complex<T extends Pattern> with EnumComparable<Complex> implements Pattern {
whitespace<RegExp>(r"\s+", RegExp.new),
alphanum<RegExp>.captured(r"\w+"),
anychar<RegExp>(".", RegExp.new),
;
// Static variables. (Could use Expando, this is more likely efficient.)
static final List<Pattern?> _patterns = List<Pattern?>.filled(3, null);
// Final instance variables.
final String _patternSource;
final T Function(String) _factory;
// Unnamed constructor. Non-redirecting.
const Complex(String pattern, T Function(String) factory)
: _patternSource = pattern, _factory = factory;
// Factory constructor.
factory Complex.matching(String text) {
for (var value in values) {
if (value.allMatches(text).isNotEmpty && value is Complex<T>) {
return value;
}
}
throw UnsupportedError("No pattern matching: $text");
}
// Named constructor. Redirecting.
const Complex.captured(String regexpPattern)
: this("($regexpPattern)", RegExp.new);
// Can expose the implicit name.
String get name => EnumName(this).name;
// Instance getter.
Pattern get pattern => _patterns[this.index] ??= _factory(_patternSource);
// Instance methods.
Iterable<Match> allMatches(String input, [int start = 0]) =>
pattern.allMatches(input, start);
Match? matchAsPrefix(String input, [int start = 0]) =>
pattern.matchAsPrefix(input, start);
// Specifies `toString`.
String toString() => "Complex<$T>($_patternSource)";
}
main() {
Expect.equals("Complex<RegExp>(\\s+)", Complex.whitespace);
Expect.equals("Complex<RegExp>(\\w+)", Complex.alphanum);
Expect.equals("Complex<Glob>(.)", Complex.anychar);
Expect.isNull(Complex.whitespace.matchAsPrefix("something"));
Expect.isNotNull(Complex.alphanum.matchAsPrefix("something"));
Expect.isNotNull(Complex.anychar.matchAsPrefix("Lily was here"));
Expect.listEquals([], Complex.whitespace.allMatches("something"));
Expect.isTrue(Complex.alphanum.allMatches("something").length > 0);
Expect.isTrue(Complex.anychar.allMatches("something").length > 0);
Expect.equals("\\s+", Complex.whitespace.pattern);
Expect.equals("\\w+", Complex.alphanum.pattern);
Expect.equals("?", Complex.anychar.pattern);
Expect.equals("whitespace", Complex.whitespace.name);
Expect.equals("alphanum", Complex.alphanum.name);
Expect.equals("anychar", Complex.anychar.name);
Expect.throws(() {
Complex c = Complex.matching("123");
});
Expect.equals(0, Complex.alphanum.compareTo(Complex.alphanum));
Expect.equals(1, Complex.alphanum.compareTo(Complex.whitespace));
Expect.equals(-1, Complex.alphanum.compareTo(Complex.anychar));
}