| part of petitparser.debug; |
| |
| /// Returns a transformed [parser] that when being used measures |
| /// the activation count and total time of each parser. |
| /// |
| /// For example, the snippet |
| /// |
| /// var parser = letter() & word().star(); |
| /// profile(parser).parse('f1234567890'); |
| /// |
| /// produces 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. |
| Parser profile(Parser root, [OutputHandler output = print]) { |
| Map<Parser, int> count = new Map(); |
| Map<Parser, Stopwatch> watch = new Map(); |
| List<Parser> parsers = new List(); |
| return new ContinuationParser(transformParser(root, (parser) { |
| parsers.add(parser); |
| return new ContinuationParser(parser, (continuation, context) { |
| count[parser]++; |
| watch[parser].start(); |
| var result = continuation(context); |
| watch[parser].stop(); |
| return result; |
| }); |
| }), (continuation, context) { |
| parsers.forEach((parser) { |
| count[parser] = 0; |
| watch[parser] = new Stopwatch(); |
| }); |
| var result = continuation(context); |
| parsers.forEach((parser) { |
| output('${count[parser]}\t' |
| '${watch[parser].elapsedMicroseconds}\t' |
| '$parser'); |
| }); |
| return result; |
| }); |
| } |