profile<T> function

Parser<T> profile<T>(
  1. Parser<T> root, {
  2. VoidCallback<ProfileFrame> output = print,
  3. Predicate<Parser>? predicate,
})

Returns a transformed Parser that when being used measures the activation count and total time of each parser.

For example, the snippet

final parser = letter() & word().star();
profile(parser).parse('f1234567890');

prints the following output:

 1  2006  Instance of 'SequenceParser'
 1   697  Instance of 'PossessiveRepeatingParser'[0..*]
11   406  Instance of 'CharacterParser'[letter or digit expected]
 1   947  Instance of 'CharacterParser'[letter expected]

The first number refers to the number of activations of each parser, and the second number is the microseconds spent in this parser and all its children.

The optional output callback can be used to receive ProfileFrame objects with the full profiling information at the end of the parse.

Implementation

Parser<T> profile<T>(Parser<T> root,
    {VoidCallback<ProfileFrame> output = print, Predicate<Parser>? predicate}) {
  final frames = <ProfileFrame>[];
  return transformParser(root, <T>(parser) {
    if (predicate == null || predicate(parser)) {
      final frame = _ProfileFrame(parser);
      frames.add(frame);
      return parser.callCC((continuation, context) {
        frame.count++;
        frame.stopwatch.start();
        final result = continuation(context);
        frame.stopwatch.stop();
        return result;
      });
    } else {
      return parser;
    }
  }).callCC((continuation, context) {
    final result = continuation(context);
    frames.forEach(output);
    return result;
  });
}