blob: 78f5b4a7a84ed3fbfb531cc185db38d3ea0fd10b [file] [log] [blame]
import 'package:meta/meta.dart';
import '../../context/context.dart';
import '../../context/result.dart';
import '../../core/parser.dart';
import '../../parser/combinator/delegate.dart';
/// Handler function for the [ContinuationParser].
typedef ContinuationHandler<T, R> = Result<R> Function(
ContinuationFunction<T> continuation, Context context);
/// Continuation function of the [ContinuationHandler].
typedef ContinuationFunction<T> = Result<T> Function(Context context);
extension ContinuationParserExtension<T> on Parser<T> {
/// Returns a parser that when activated captures a continuation function
/// and passes it together with the current context into the handler.
///
/// Handlers are not required to call the continuation, but can completely
/// ignore it, call it multiple times, and/or store it away for later use.
/// Similarly handlers can modify the current context and/or modify the
/// returned result.
///
/// The following example shows a simple wrapper. Messages are printed before
/// and after the `digit()` parser is activated:
///
/// final parser = digit().callCC((continuation, context) {
/// print('Parser will be activated, the context is $context.');
/// final result = continuation(context);
/// print('Parser was activated, the result is $result.');
/// return result;
/// });
///
@useResult
Parser<R> callCC<R>(ContinuationHandler<T, R> handler) =>
ContinuationParser<T, R>(this, handler);
}
/// Continuation parser that when activated captures a continuation function
/// and passes it together with the current context into the handler.
class ContinuationParser<T, R> extends DelegateParser<T, R> {
ContinuationParser(super.delegate, this.handler);
/// Activation handler of the continuation.
final ContinuationHandler<T, R> handler;
@override
Result<R> parseOn(Context context) => handler(_parseDelegateOn, context);
Result<T> _parseDelegateOn(Context context) => delegate.parseOn(context);
@override
ContinuationParser<T, R> copy() =>
ContinuationParser<T, R>(delegate, handler);
@override
bool hasEqualProperties(ContinuationParser<T, R> other) =>
super.hasEqualProperties(other) && handler == other.handler;
}