blob: 810d2457e934b606d324ac60aab6240766b843ea [file] [log] [blame]
import 'package:meta/meta.dart';
import '../../context/context.dart';
import '../../context/result.dart';
import '../../core/parser.dart';
import 'delegate.dart';
extension OptionalParserExtension<R> on Parser<R> {
/// Returns new parser that accepts the receiver, if possible. The resulting
/// parser returns the result of the receiver, or `null` if not applicable.
///
/// For example, the parser `letter().optional()` accepts a letter as input
/// and returns that letter. When given something else the parser succeeds as
/// well, does not consume anything and returns `null`.
@useResult
Parser<R?> optional() => OptionalParser<R?>(this, null);
/// Returns new parser that accepts the receiver, if possible. The resulting
/// parser returns the result of the receiver, or [value] if not applicable.
///
/// For example, the parser `letter().optionalWith('!')` accepts a letter as
/// input and returns that letter. When given something else the parser
/// succeeds as well, does not consume anything and returns `'!'`.
@useResult
Parser<R> optionalWith(R value) => OptionalParser<R>(this, value);
}
/// A parser that optionally parsers its delegate, or answers `null`.
class OptionalParser<R> extends DelegateParser<R, R> {
OptionalParser(super.delegate, this.otherwise);
/// The value returned if the [delegate] cannot be parsed.
final R otherwise;
@override
Result<R> parseOn(Context context) {
final result = delegate.parseOn(context);
if (result.isSuccess) {
return result;
} else {
return context.success(otherwise);
}
}
@override
int fastParseOn(String buffer, int position) {
final result = delegate.fastParseOn(buffer, position);
return result < 0 ? position : result;
}
@override
OptionalParser<R> copy() => OptionalParser<R>(delegate, otherwise);
@override
bool hasEqualProperties(OptionalParser<R> other) =>
super.hasEqualProperties(other) && otherwise == other.otherwise;
}