+
+ # Display the sizes.
+ print "Sizes (decreasing):\n";
+ my $width = 10;
+ for my $bench (keys %size)
+ {
+ $width = length $bench
+ if $width < length $bench;
+ }
+ # Benches sorted by decreasing size.
+ my @benches_per_size = sort {$size{$b} <=> $size{$a}} keys %size;
+ for my $bench (@benches_per_size)
+ {
+ printf "%${width}s: %5.2fkB\n", $bench, $size{$bench} / 1024;
+ }
+}
+
+######################################################################
+
+=item C<bench_push_parser ()>
+
+Bench the C push parser against the pull parser, pure and impure
+interfaces.
+
+=cut
+
+sub bench_push_parser ()
+{
+ bench ('calc',
+ (
+ '[', '%define api.pure', ']',
+ '&',
+ '[', '%define api.push_pull "both"', ']'
+ ));
+}
+
+######################################################################
+
+=item C<bench_variant_parser ()>
+
+Bench the C++ lalr1.cc parser using Boost.Variants or %union.
+
+=cut
+
+sub bench_variant_parser ()
+{
+ bench ('variant',
+ ('%skeleton "lalr1.cc"',
+ '&',
+ '[', '%debug', ']',
+ '&',
+ '[', '%define variant', ']',
+ '&',
+ '[', "%code {\n#define VARIANT_DESTROY\n}", ']'
+ ));
+}
+
+######################################################################
+
+=item C<bench_fusion_parser ()>
+
+Bench the C++ lalr1.cc parser using Boost.Variants or %union.
+
+=cut
+
+sub bench_fusion_parser ()
+{
+ bench ('list',
+ ('%skeleton "lalr1-split.cc"',
+ '|',
+ '%skeleton "lalr1.cc"'));
+}
+
+############################################################################
+
+sub help ($)
+{
+ my ($verbose) = @_;
+ use Pod::Usage;
+ # See <URL:http://perldoc.perl.org/pod2man.html#NOTES>.
+ pod2usage( { -message => "Bench Bison parsers",
+ -exitval => 0,
+ -verbose => $verbose,
+ -output => \*STDOUT });
+}
+
+######################################################################
+
+# The list of tokens parsed by the following functions.
+my @token;
+
+# Parse directive specifications:
+# expr: term (| term)*
+# term: fact (& fact)*
+# fact: ( expr ) | [ expr ] | dirs
+sub parse (@)
+{
+ @token = @_;
+ verbose 2, "Parsing: @token\n";
+ return parse_expr ();
+}
+
+sub parse_expr ()
+{
+ my @res = parse_term ();
+ while (defined $token[0] && $token[0] eq '|')
+ {
+ shift @token;
+ # Alternation.
+ push @res, parse_term ();
+ }
+ return @res;
+}
+
+sub parse_term ()
+{
+ my @res = parse_fact ();
+ while (defined $token[0] && $token[0] eq '&')
+ {
+ shift @token;
+ # Cartesian product.
+ my @lhs = @res;
+ @res = ();
+ for my $rhs (parse_fact ())
+ {
+ for my $lhs (@lhs)
+ {
+ push @res, "$lhs\n$rhs";
+ }
+ }
+ }
+ return @res;