blob: 97c3e57d53c37f536ca5520b5e5a1772d683319d [file] [log] [blame]
library petitparser.core.predicates.predicate;
import 'package:petitparser/src/core/contexts/context.dart';
import 'package:petitparser/src/core/contexts/result.dart';
import 'package:petitparser/src/core/parser.dart';
/// A generic predicate function returning `true` or `false` for a given
/// [input] argument.
typedef Predicate = bool Function(String input);
/// Returns a parser that reads input of the specified [length], accepts
/// it if the [predicate] matches, or fails with the given [message].
Parser<String> predicate(int length, Predicate predicate, String message) {
return PredicateParser(length, predicate, message);
}
/// A parser for a literal satisfying a predicate.
class PredicateParser extends Parser<String> {
/// The length of the input to read.
final int length;
/// The predicate function testing the input.
final Predicate predicate;
/// The failure message in case of a miss-match.
final String message;
PredicateParser(this.length, this.predicate, this.message)
: assert(length > 0, 'length must be positive'),
assert(predicate != null, 'predicate must not be null'),
assert(message != null, 'message must not be null');
@override
Result<String> parseOn(Context context) {
final start = context.position;
final stop = start + length;
if (stop <= context.buffer.length) {
final result = context.buffer.substring(start, stop);
if (predicate(result)) {
return context.success(result, stop);
}
}
return context.failure(message);
}
@override
int fastParseOn(String buffer, int position) {
final stop = position + length;
return stop <= buffer.length && predicate(buffer.substring(position, stop))
? stop
: -1;
}
@override
String toString() => '${super.toString()}[$message]';
@override
PredicateParser copy() => PredicateParser(length, predicate, message);
@override
bool hasEqualProperties(PredicateParser other) =>
super.hasEqualProperties(other) &&
length == other.length &&
predicate == other.predicate &&
message == other.message;
}