blob: 59cb73007b04354a1cd2004bd2fcac46aac2a909 [file] [log] [blame]
import 'package:meta/meta.dart';
import '../../context/context.dart';
import '../../context/result.dart';
import '../../core/parser.dart';
import '../combinator/delegate.dart';
import '../misc/failure.dart';
import '../utils/resolvable.dart';
extension SettableParserExtension<R> on Parser<R> {
/// Returns a parser that points to the receiver, but can be changed to point
/// to something else at a later point in time.
///
/// For example, the parser `letter().settable()` behaves exactly the same
/// as `letter()`, but it can be replaced with another parser using
/// [SettableParser.set].
@useResult
SettableParser<R> settable() => SettableParser<R>(this);
}
/// Returns a parser that is not defined, but that can be set at a later
/// point in time.
///
/// For example, the following code sets up a parser that points to itself
/// and that accepts a sequence of a's ended with the letter b.
///
/// final p = undefined();
/// p.set(char('a').seq(p).or(char('b')));
SettableParser<R> undefined<R>([String message = 'undefined parser']) =>
failure<R>(message).settable();
/// A parser that is not defined, but that can be set at a later
/// point in time.
class SettableParser<R> extends DelegateParser<R, R>
implements ResolvableParser<R> {
SettableParser(super.delegate);
/// Sets the receiver to delegate to [parser].
void set(Parser<R> parser) => replace(children[0], parser);
@override
Parser<R> resolve() => delegate;
@override
Result<R> parseOn(Context context) => delegate.parseOn(context);
@override
int fastParseOn(String buffer, int position) =>
delegate.fastParseOn(buffer, position);
@override
SettableParser<R> copy() => SettableParser<R>(delegate);
}