Blame etc/bench.pl.in

Packit Service c3aa71
#! /usr/bin/perl -w
Packit Service c3aa71
Packit Service c3aa71
# Copyright (C) 2006, 2008-2015 Free Software Foundation, Inc.
Packit Service c3aa71
#
Packit Service c3aa71
# This file is part of Bison, the GNU Compiler Compiler.
Packit Service c3aa71
#
Packit Service c3aa71
# This program is free software: you can redistribute it and/or modify
Packit Service c3aa71
# it under the terms of the GNU General Public License as published by
Packit Service c3aa71
# the Free Software Foundation, either version 3 of the License, or
Packit Service c3aa71
# (at your option) any later version.
Packit Service c3aa71
#
Packit Service c3aa71
# This program is distributed in the hope that it will be useful,
Packit Service c3aa71
# but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service c3aa71
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service c3aa71
# GNU General Public License for more details.
Packit Service c3aa71
#
Packit Service c3aa71
# You should have received a copy of the GNU General Public License
Packit Service c3aa71
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit Service c3aa71
Packit Service c3aa71
=head1 NAME
Packit Service c3aa71
Packit Service c3aa71
bench.pl - bench marks for Bison parsers.
Packit Service c3aa71
Packit Service c3aa71
=head1 SYNOPSIS
Packit Service c3aa71
Packit Service c3aa71
  ./bench.pl [OPTIONS]... DIRECTIVES
Packit Service c3aa71
Packit Service c3aa71
=head1 DIRECTIVES
Packit Service c3aa71
Packit Service c3aa71
Specify the set of benches to run.  The following grammar defines the
Packit Service c3aa71
I<directives>:
Packit Service c3aa71
Packit Service c3aa71
   directives ::=
Packit Service c3aa71
       directives | directives  -- Alternation
Packit Service c3aa71
     | directives & directives  -- Concatenation
Packit Service c3aa71
     | [ directives> ]          -- Optional
Packit Service c3aa71
     | ( directives> )          -- Parentheses
Packit Service c3aa71
     | %b PATH                  -- Use bison at PATH for this bench
Packit Service c3aa71
     | #d NAME[=VALUE]          -- %code { #define NAME [VALUE] }
Packit Service c3aa71
     | %d NAME[=VALUE]          -- %define NAME ["VALUE"]
Packit Service c3aa71
     | %s skeleton              -- %skeleton "skeleton"
Packit Service c3aa71
     | directive
Packit Service c3aa71
Packit Service c3aa71
Parentheses only group to override precedence.  For instance:
Packit Service c3aa71
Packit Service c3aa71
  [ %debug ] & [ %error-verbose ] & [ %define variant ]
Packit Service c3aa71
Packit Service c3aa71
will generate eight different cases.
Packit Service c3aa71
Packit Service c3aa71
=head1 OPTIONS
Packit Service c3aa71
Packit Service c3aa71
=over 4
Packit Service c3aa71
Packit Service c3aa71
=item B<-b>, B<--bench>
Packit Service c3aa71
Packit Service c3aa71
Predefined benches, that is, combimation between a grammar and a I<directives>
Packit Service c3aa71
request.
Packit Service c3aa71
Packit Service c3aa71
=over 4
Packit Service c3aa71
Packit Service c3aa71
=item I<push>
Packit Service c3aa71
Packit Service c3aa71
Test the push parser vs. the pull interface.  Use the C parser.
Packit Service c3aa71
Packit Service c3aa71
=item I<variant>
Packit Service c3aa71
Packit Service c3aa71
Test the use of variants instead of union in the C++ parser.
Packit Service c3aa71
Packit Service c3aa71
=back
Packit Service c3aa71
Packit Service c3aa71
=item B<-c>, B<--cflags>=I<flags>
Packit Service c3aa71
Packit Service c3aa71
Flags to pass to the C or C++ compiler.  Defaults to -O2.
Packit Service c3aa71
Packit Service c3aa71
=item B<-d>, B<--directive>=I<directives>
Packit Service c3aa71
Packit Service c3aa71
Add a set of Bison directives to bench against each other.
Packit Service c3aa71
Packit Service c3aa71
=item B<-g>, B<--grammar>=I<grammar>
Packit Service c3aa71
Packit Service c3aa71
Select the base I<grammar> to use.  Defaults to I<calc>.
Packit Service c3aa71
Packit Service c3aa71
=over 4
Packit Service c3aa71
Packit Service c3aa71
=item I<calc>
Packit Service c3aa71
Packit Service c3aa71
Traditional calculator.
Packit Service c3aa71
Packit Service c3aa71
=item I<list>
Packit Service c3aa71
Packit Service c3aa71
C++ grammar that uses std::string and std::list.  Can be used with
Packit Service c3aa71
or without %define variant.
Packit Service c3aa71
Packit Service c3aa71
=item I<triangular>
Packit Service c3aa71
Packit Service c3aa71
Artificial grammar with very long rules.
Packit Service c3aa71
Packit Service c3aa71
=back
Packit Service c3aa71
Packit Service c3aa71
=item B<-h>, B<--help>
Packit Service c3aa71
Packit Service c3aa71
Display this message and exit succesfully.  The more verbose, the more
Packit Service c3aa71
details.
Packit Service c3aa71
Packit Service c3aa71
=item B<-i>, B<--iterations>=I<integer>
Packit Service c3aa71
Packit Service c3aa71
Say how many times a single test of the bench must be run.  If
Packit Service c3aa71
negative, specify the minimum number of CPU seconds to run.  Defaults
Packit Service c3aa71
to -1.
Packit Service c3aa71
Packit Service c3aa71
=item B<-q>, B<--quiet>
Packit Service c3aa71
Packit Service c3aa71
Decrease the verbosity level (defaults to 1).
Packit Service c3aa71
Packit Service c3aa71
=item B<-v>, B<--verbose>
Packit Service c3aa71
Packit Service c3aa71
Raise the verbosity level (defaults to 1).
Packit Service c3aa71
Packit Service c3aa71
=back
Packit Service c3aa71
Packit Service c3aa71
=cut
Packit Service c3aa71
Packit Service c3aa71
use strict;
Packit Service c3aa71
use IO::File;
Packit Service c3aa71
Packit Service c3aa71
##################################################################
Packit Service c3aa71
Packit Service c3aa71
=head1 VARIABLES
Packit Service c3aa71
Packit Service c3aa71
=over 4
Packit Service c3aa71
Packit Service c3aa71
=item C<@bench>
Packit Service c3aa71
Packit Service c3aa71
The list of benches to run.
Packit Service c3aa71
Packit Service c3aa71
=item C<$bison>
Packit Service c3aa71
Packit Service c3aa71
The Bison program to use to compile the grammar.
Packit Service c3aa71
Packit Service c3aa71
=item C<$cc>
Packit Service c3aa71
Packit Service c3aa71
The C compiler.
Packit Service c3aa71
Packit Service c3aa71
=item C<$cxx>
Packit Service c3aa71
Packit Service c3aa71
The C++ compiler.
Packit Service c3aa71
Packit Service c3aa71
=item C<$cflags>
Packit Service c3aa71
Packit Service c3aa71
Compiler flags (C or C++).
Packit Service c3aa71
Packit Service c3aa71
=item C<@directive>
Packit Service c3aa71
Packit Service c3aa71
A list of directive sets to measure against each other.
Packit Service c3aa71
Packit Service c3aa71
=item C<$iterations>
Packit Service c3aa71
Packit Service c3aa71
The number of times the parser is run for a bench.
Packit Service c3aa71
Packit Service c3aa71
=item C<$verbose>
Packit Service c3aa71
Packit Service c3aa71
Verbosity level.
Packit Service c3aa71
Packit Service c3aa71
=back
Packit Service c3aa71
Packit Service c3aa71
=cut
Packit Service c3aa71
Packit Service c3aa71
my $bench;
Packit Service c3aa71
my $bison = $ENV{'BISON'} || '@abs_top_builddir@/tests/bison';
Packit Service c3aa71
my $cc = $ENV{'CC'} || 'gcc';
Packit Service c3aa71
my $cxx = $ENV{'CXX'} || 'g++';
Packit Service c3aa71
my $cflags = '-O2';
Packit Service c3aa71
my @directive = ();
Packit Service c3aa71
my $grammar = 'calc';
Packit Service c3aa71
my $iterations = -1;
Packit Service c3aa71
my $verbose = 1;
Packit Service c3aa71
Packit Service c3aa71
=head1 FUNCTIONS
Packit Service c3aa71
Packit Service c3aa71
=over 4
Packit Service c3aa71
Packit Service c3aa71
=item C<verbose($level, $message)>
Packit Service c3aa71
Packit Service c3aa71
Report the C<$message> is C<$level> E<lt>= C<$verbose>.
Packit Service c3aa71
Packit Service c3aa71
=cut
Packit Service c3aa71
Packit Service c3aa71
sub verbose($$)
Packit Service c3aa71
{
Packit Service c3aa71
  my ($level, $message) = @_;
Packit Service c3aa71
  print STDERR $message
Packit Service c3aa71
    if $level <= $verbose;
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
Packit Service c3aa71
######################################################################
Packit Service c3aa71
Packit Service c3aa71
=item C<directives($bench, @directive)>
Packit Service c3aa71
Packit Service c3aa71
Format the list of directives for Bison for bench named C<$bench>.
Packit Service c3aa71
Packit Service c3aa71
=cut
Packit Service c3aa71
Packit Service c3aa71
sub directives($@)
Packit Service c3aa71
{
Packit Service c3aa71
  my ($bench, @directive) = @_;
Packit Service c3aa71
  my $res = "/* Directives for bench '$bench'. */\n";
Packit Service c3aa71
  $res .= join ("\n", @directive) . "\n";
Packit Service c3aa71
  $res .= "/* End of directives for bench '$bench'. */\n";
Packit Service c3aa71
  return $res;
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
######################################################################
Packit Service c3aa71
Packit Service c3aa71
=item C<generate_grammar_triangular ($base, $max, @directive)>
Packit Service c3aa71
Packit Service c3aa71
Create a large triangular grammar which looks like :
Packit Service c3aa71
Packit Service c3aa71
  input:
Packit Service c3aa71
    exp        { if ($1 != 0) abort (); $$ = $1; }
Packit Service c3aa71
  | input exp  { if ($2 != $1 + 1) abort (); $$ = $2; }
Packit Service c3aa71
  ;
Packit Service c3aa71
Packit Service c3aa71
  exp:
Packit Service c3aa71
    END                         { $$ = 0; }
Packit Service c3aa71
  | "1"  END                    { $$ = 1; }
Packit Service c3aa71
  | "1" "2"  END                { $$ = 2; }
Packit Service c3aa71
  | "1" "2" "3"  END            { $$ = 3; }
Packit Service c3aa71
  | "1" "2" "3" "4"  END        { $$ = 4; }
Packit Service c3aa71
  | "1" "2" "3" "4" "5"  END    { $$ = 5; }
Packit Service c3aa71
  ;
Packit Service c3aa71
Packit Service c3aa71
C<$base> is the base name for the file to create (F<$base.y>).
Packit Service c3aa71
C<$max> is the number of such rules (here, 5).  You may pass
Packit Service c3aa71
additional Bison C<@directive>.
Packit Service c3aa71
Packit Service c3aa71
The created parser is self contained: it includes its scanner, and
Packit Service c3aa71
source of input.
Packit Service c3aa71
=cut
Packit Service c3aa71
Packit Service c3aa71
sub generate_grammar_triangular ($$@)
Packit Service c3aa71
{
Packit Service c3aa71
  my ($base, $max, @directive) = @_;
Packit Service c3aa71
  my $directives = directives ($base, @directive);
Packit Service c3aa71
Packit Service c3aa71
  my $out = new IO::File ">$base.y"
Packit Service c3aa71
    or die;
Packit Service c3aa71
  print $out <
Packit Service c3aa71
%error-verbose
Packit Service c3aa71
%{
Packit Service c3aa71
#include <stdio.h>
Packit Service c3aa71
#include <stdlib.h>
Packit Service c3aa71
Packit Service c3aa71
static int yylex (void);
Packit Service c3aa71
static void yyerror (const char *msg);
Packit Service c3aa71
%}
Packit Service c3aa71
$directives
Packit Service c3aa71
%union
Packit Service c3aa71
{
Packit Service c3aa71
  int val;
Packit Service c3aa71
};
Packit Service c3aa71
Packit Service c3aa71
%token END "end"
Packit Service c3aa71
%type <val> exp input
Packit Service c3aa71
EOF
Packit Service c3aa71
Packit Service c3aa71
  for my $size (1 .. $max)
Packit Service c3aa71
    {
Packit Service c3aa71
      print $out "%token t$size $size \"$size\"\n";
Packit Service c3aa71
    };
Packit Service c3aa71
Packit Service c3aa71
print $out <
Packit Service c3aa71
%%
Packit Service c3aa71
input:
Packit Service c3aa71
  exp        { if (\$1 != 0) abort (); \$\$ = \$1; }
Packit Service c3aa71
| input exp  { if (\$2 != \$1 + 1) abort (); \$\$ = \$2; }
Packit Service c3aa71
;
Packit Service c3aa71
Packit Service c3aa71
exp:
Packit Service c3aa71
  END
Packit Service c3aa71
    { \$\$ = 0; }
Packit Service c3aa71
EOF
Packit Service c3aa71
Packit Service c3aa71
for my $size (1 .. $max)
Packit Service c3aa71
  {
Packit Service c3aa71
    use Text::Wrap;
Packit Service c3aa71
    print $out wrap ("| ", "   ",
Packit Service c3aa71
                     (map { "\"$_\"" } (1 .. $size)),
Packit Service c3aa71
                     " END \n"),
Packit Service c3aa71
               "    { \$\$ = $size; }\n";
Packit Service c3aa71
  };
Packit Service c3aa71
print $out ";\n";
Packit Service c3aa71
Packit Service c3aa71
print $out <
Packit Service c3aa71
%%
Packit Service c3aa71
static int
Packit Service c3aa71
yylex (void)
Packit Service c3aa71
{
Packit Service c3aa71
  static int inner = 1;
Packit Service c3aa71
  static int outer = 0;
Packit Service c3aa71
  if (outer > $max)
Packit Service c3aa71
    return 0;
Packit Service c3aa71
  else if (inner > outer)
Packit Service c3aa71
    {
Packit Service c3aa71
      inner = 1;
Packit Service c3aa71
      ++outer;
Packit Service c3aa71
      return END;
Packit Service c3aa71
    }
Packit Service c3aa71
  return inner++;
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
static void
Packit Service c3aa71
yyerror (const char *msg)
Packit Service c3aa71
{
Packit Service c3aa71
  fprintf (stderr, "%s\\n", msg);
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
int
Packit Service c3aa71
main (void)
Packit Service c3aa71
{
Packit Service c3aa71
#if YYDEBUG
Packit Service c3aa71
  yydebug = !!getenv ("YYDEBUG");
Packit Service c3aa71
#endif
Packit Service c3aa71
  return yyparse ();
Packit Service c3aa71
}
Packit Service c3aa71
EOF
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
##################################################################
Packit Service c3aa71
Packit Service c3aa71
=item C<calc_input ($base, $max)>
Packit Service c3aa71
Packit Service c3aa71
Generate the input file F<$base.input> for the calc parser.  The input
Packit Service c3aa71
is composed of two expressions.  The first one is using left recursion
Packit Service c3aa71
only and consumes no stack.  The second one requires a deep stack.
Packit Service c3aa71
These two expressions are repeated C<$max> times in the output file.
Packit Service c3aa71
Packit Service c3aa71
=cut
Packit Service c3aa71
Packit Service c3aa71
sub calc_input ($$)
Packit Service c3aa71
{
Packit Service c3aa71
  my ($base, $max) = @_;
Packit Service c3aa71
  my $out = new IO::File ">$base.input"
Packit Service c3aa71
    or die;
Packit Service c3aa71
  foreach (1 .. $max)
Packit Service c3aa71
    {
Packit Service c3aa71
      print $out "0+1+2+3+4+5+6+7+8+9+10+11+12+13+14+15+16+17+18+19+20+21+22+23+24+25+26+27+28+29+30+31+32+33+34+35+36+37+38+39+40+41+42+43+44+45+46+47+48+49+50+51+52+53+54+55+56+57+58+59+60+61+62+63+64+65+66+67+68+69+70+71+72+73+74+75+76+77+78+79+80+81+82+83+84+85+86+87+88+89+90+91+92+93+94+95+96+97+98+99\n";
Packit Service c3aa71
      print $out "1+1*(2+2*(3+3*(4+4*(5+5*(6+6*(7+7*(8+8*(9+9*(10+10*(11+11*(12+12*(13+13*(14+14*(15+15*(16+16*(17+17*(18+18*(19+19*(20+20*(21+21*(22+22*(23+23*(24+24*(25+25*(26+26*(27+27*(28+28*(29+29*(30+30*(31+31*(32+32*(33+33*(34+34*(35+35*(36+36*(37+37*(38+38*(39+39*(40+40*(41+41*(42+42*(43+43*(44+44*(45+45*(46+46*(47+47*(48+48*(49+49*(50+50*(51+51*(52+52*(53+53*(54+54*(55+55*(56+56*(57+57*(58+58*(59+59*(60+60*(61+61*(62+62*(63+63*(64+64*(65+65*(66+66*(67+67*(68+68*(69+69*(70+70*(71+71*(72+72*(73+73*(74+74*(75+75*(76+76*(77+77*(78+78*(79+79*(80+80*(81+81*(82+82*(83+83*(84+84*(85+85*(86+86*(87+87*(88+88*(89+89*(90+90*(91+91*(92+92*(93+93*(94+94*(95+95*(96+96*(97+97*(98+98*(99+99*(100+100*(101+101*(102+102*(103+103*(104+104*(105+105*(106+106*(107+107*(108+108*(109+109*(110+110*(111+111*(112+112*(113+113*(114+114*(115+115*(116+116*(117+117*(118+118*(119+119*(120+120*(121+121*(122+122*(123+123*(124+124*(125+125*(126+126*(127+127*(128+128*(129+129*(130+130*(131+131*(132+132*(133+133*(134+134*(135+135*(136+136*(137+137*(138+138*(139+139*(140+140*(141+141*(142+142*(143+143*(144+144*(145+145*(146+146*(147+147*(148+148*(149+149*(150+150*(151+151*(152+152*(153+153*(154+154*(155+155*(156+156*(157+157*(158+158*(159+159*(160+160*(161+161*(162+162*(163+163*(164+164*(165+165*(166+166*(167+167*(168+168*(169+169*(170+170*(171+171*(172+172*(173+173*(174+174*(175+175*(176+176*(177+177*(178+178*(179+179*(180+180*(181+181*(182+182*(183+183*(184+184*(185+185*(186+186*(187+187*(188+188*(189+189*(190+190*(191+191*(192+192*(193+193*(194+194*(195+195*(196+196*(197+197*(198+198*(199+199*(200+200*(201+201*(202+202*(203+203*(204+204*(205+205*(206+206*(207+207*(208+208*(209+209*(210+210*(211+211*(212+212*(213+213*(214+214*(215+215*(216+216*(217+217*(218+218*(219+219*(220+220*(221+221*(222+222*(223+223*(224+224*(225+225*(226+226*(227+227*(228+228*(229+229*(230+230*(231+231*(232+232*(233+233*(234+234*(235+235*(236+236*(237+237*(238+238*(239+239*(240+240*(241+241*(242+242*(243+243*(244+244*(245+245*(246+246*(247+247*(248+248*(249+249*(250+250*(251+251*(252+252*(253+253*(254+254*(255+255*(256+256*(257+257*(258+258*(259+259*(260+260*(261+261*(262+262*(263+263*(264+264*(265+265*(266+266*(267+267*(268+268*(269+269*(270+270*(271+271*(272+272*(273+273*(274+274*(275+275*(276+276*(277+277*(278+278*(279+279*(280+280*(281+281*(282+282*(283+283*(284+284*(285+285*(286+286*(287+287*(288+288*(289+289*(290+290*(291+291*(292+292*(293+293*(294+294*(295+295*(296+296*(297+297*(298+298*(299+299*(300+300*(301+301*(302+302*(303+303*(304+304*(305+305*(306+306*(307+307*(308+308*(309+309*(310+310*(311+311*(312+312*(313+313*(314+314*(315+315*(316+316*(317+317*(318+318*(319+319*(320+320*(321+321*(322+322*(323+323*(324+324*(325+325*(326+326*(327+327*(328+328*(329+329*(330+330*(331+331*(332+332*(333+333*(334+334*(335+335*(336+336*(337+337*(338+338*(339+339*(340+340*(341+341*(342+342*(343+343*(344+344*(345+345*(346+346*(347+347*(348+348*(349+349*(350+350*(351+351*(352+352*(353+353*(354+354*(355+355*(356+356*(357+357*(358+358*(359+359*(360+360*(361+361*(362+362*(363+363*(364+364*(365+365*(366+366*(367+367*(368+368*(369+369*(370+370*(371+371*(372+372*(373+373*(374+374*(375+375*(376+376*(377+377*(378+378*(379+379*(380+380*(381+381*(382+382*(383+383*(384+384*(385+385*(386+386*(387+387*(388+388*(389+389*(390+390*(391+391*(392+392*(393+393*(394+394*(395+395*(396+396*(397+397*(398+398*(399+399*(400+400*(401+401*(402+402*(403+403*(404+404*(405+405*(406+406*(407+407*(408+408*(409+409*(410+410*(411+411*(412+412*(413+413*(414+414*(415+415*(416+416*(417+417*(418+418*(419+419*(420+420*(421+421*(422+422*(423+423*(424+424*(425+425*(426+426*(427+427*(428+428*(429+429*(430+430*(431+431*(432+432*(433+433*(434+434*(435+435*(436+436*(437+437*(438+438*(439+439*(440+440*(441+441*(442+442*(443+443*(444+444*(445+445*(446+446*(447+447*(448+448*(449+449*(450+450*(451+451*(452+452*(453+453*(454+454*(455+455*(456+456*(457+457*(458+458*(459+459*(460+460*(461+461*(462+462*(463+463*(464+464*(465+465*(466+466*(467+467*(468+468*(469+469*(470+470*(471+471*(472+472*(473+473*(474+474*(475+475*(476+476*(477+477*(478+478*(479+479*(480+480*(481+481*(482+482*(483+483*(484+484*(485+485*(486+486*(487+487*(488+488*(489+489*(490+490*(491+491*(492+492*(493+493*(494+494*(495+495*(496+496*(497+497*(498+498*(499+499*(500+500*(501+501*(502+502*(503+503*(504+504*(505+505*(506+506*(507+507*(508+508*(509+509*(510+510*(511+511*(512+512*(513+513*(514+514*(515+515*(516+516*(517+517*(518+518*(519+519*(520+520*(521+521*(522+522*(523+523*(524+524*(525+525*(526+526*(527+527*(528+528*(529+529*(530+530*(531+531*(532+532*(533+533*(534+534*(535+535*(536+536*(537+537*(538+538*(539+539*(540+540*(541+541*(542+542*(543+543*(544+544*(545+545*(546+546*(547+547*(548+548*(549+549*(550+550*(551+551*(552+552*(553+553*(554+554*(555+555*(556+556*(557+557*(558+558*(559+559*(560+560*(561+561*(562+562*(563+563*(564+564*(565+565*(566+566*(567+567*(568+568*(569+569*(570+570*(571+571*(572+572*(573+573*(574+574*(575+575*(576+576*(577+577*(578+578*(579+579*(580+580*(581+581*(582+582*(583+583*(584+584*(585+585*(586+586*(587+587*(588+588*(589+589*(590+590*(591+591*(592+592*(593+593*(594+594*(595+595*(596+596*(597+597*(598+598*(599+599*(600+600*(601+601*(602+602*(603+603*(604+604*(605+605*(606+606*(607+607*(608+608*(609+609*(610+610*(611+611*(612+612*(613+613*(614+614*(615+615*(616+616*(617+617*(618+618*(619+619*(620+620*(621+621*(622+622*(623+623*(624+624*(625+625*(626+626*(627+627*(628+628*(629+629*(630+630*(631+631*(632+632*(633+633*(634+634*(635+635*(636+636*(637+637*(638+638*(639+639*(640+640*(641+641*(642+642*(643+643*(644+644*(645+645*(646+646*(647+647*(648+648*(649+649*(650+650*(651+651*(652+652*(653+653*(654+654*(655+655*(656+656*(657+657*(658+658*(659+659*(660+660*(661+661*(662+662*(663+663*(664+664*(665+665*(666+666*(667+667*(668+668*(669+669*(670+670*(671+671*(672+672*(673+673*(674+674*(675+675*(676+676*(677+677*(678+678*(679+679*(680+680*(681+681*(682+682*(683+683*(684+684*(685+685*(686+686*(687+687*(688+688*(689+689*(690+690*(691+691*(692+692*(693+693*(694+694*(695+695*(696+696*(697+697*(698+698*(699+699*(700+700*(701+701*(702+702*(703+703*(704+704*(705+705*(706+706*(707+707*(708+708*(709+709*(710+710*(711+711*(712+712*(713+713*(714+714*(715+715*(716+716*(717+717*(718+718*(719+719*(720+720*(721+721*(722+722*(723+723*(724+724*(725+725*(726+726*(727+727*(728+728*(729+729*(730+730*(731+731*(732+732*(733+733*(734+734*(735+735*(736+736*(737+737*(738+738*(739+739*(740+740*(741+741*(742+742*(743+743*(744+744*(745+745*(746+746*(747+747*(748+748*(749+749*(750+750*(751+751*(752+752*(753+753*(754+754*(755+755*(756+756*(757+757*(758+758*(759+759*(760+760*(761+761*(762+762*(763+763*(764+764*(765+765*(766+766*(767+767*(768+768*(769+769*(770+770*(771+771*(772+772*(773+773*(774+774*(775+775*(776+776*(777+777*(778+778*(779+779*(780+780*(781+781*(782+782*(783+783*(784+784*(785+785*(786+786*(787+787*(788+788*(789+789*(790+790*(791+791*(792+792*(793+793*(794+794*(795+795*(796+796*(797+797*(798+798*(799+799*(800+800*(801+801*(802+802*(803+803*(804+804*(805+805*(806+806*(807+807*(808+808*(809+809*(810+810*(811+811*(812+812*(813+813*(814+814*(815+815*(816+816*(817+817*(818+818*(819+819*(820+820*(821+821*(822+822*(823+823*(824+824*(825+825*(826+826*(827+827*(828+828*(829+829*(830+830*(831+831*(832+832*(833+833*(834+834*(835+835*(836+836*(837+837*(838+838*(839+839*(840+840*(841+841*(842+842*(843+843*(844+844*(845+845*(846+846*(847+847*(848+848*(849+849*(850+850*(851+851*(852+852*(853+853*(854+854*(855+855*(856+856*(857+857*(858+858*(859+859*(860+860*(861+861*(862+862*(863+863*(864+864*(865+865*(866+866*(867+867*(868+868*(869+869*(870+870*(871+871*(872+872*(873+873*(874+874*(875+875*(876+876*(877+877*(878+878*(879+879*(880+880*(881+881*(882+882*(883+883*(884+884*(885+885*(886+886*(887+887*(888+888*(889+889*(890+890*(891+891*(892+892*(893+893*(894+894*(895+895*(896+896*(897+897*(898+898*(899+899*(900+900*(901+901*(902+902*(903+903*(904+904*(905+905*(906+906*(907+907*(908+908*(909+909*(910+910*(911+911*(912+912*(913+913*(914+914*(915+915*(916+916*(917+917*(918+918*(919+919*(920+920*(921+921*(922+922*(923+923*(924+924*(925+925*(926+926*(927+927*(928+928*(929+929*(930+930*(931+931*(932+932*(933+933*(934+934*(935+935*(936+936*(937+937*(938+938*(939+939*(940+940*(941+941*(942+942*(943+943*(944+944*(945+945*(946+946*(947+947*(948+948*(949+949*(950+950*(951+951*(952+952*(953+953*(954+954*(955+955*(956+956*(957+957*(958+958*(959+959*(960+960*(961+961*(962+962*(963+963*(964+964*(965+965*(966+966*(967+967*(968+968*(969+969*(970+970*(971+971*(972+972*(973+973*(974+974*(975+975*(976+976*(977+977*(978+978*(979+979*(980+980*(981+981*(982+982*(983+983*(984+984*(985+985*(986+986*(987+987*(988+988*(989+989*(990+990*(991+991*(992+992*(993+993*(994+994*(995+995*(996+996*(997+997*(998+998*(999+999*(1000+1000*(1001))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))\n";
Packit Service c3aa71
    }
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
##################################################################
Packit Service c3aa71
Packit Service c3aa71
=item C<generate_grammar_calc ($base, $max, @directive)>
Packit Service c3aa71
Packit Service c3aa71
Generate a Bison file F<$base.y> for a calculator parser in C.  Pass
Packit Service c3aa71
the additional Bison C<@directive>.  C<$max> is ignored, but left to
Packit Service c3aa71
have the same interface as C<triangular_grammar>.
Packit Service c3aa71
Packit Service c3aa71
=cut
Packit Service c3aa71
Packit Service c3aa71
sub generate_grammar_calc ($$@)
Packit Service c3aa71
{
Packit Service c3aa71
  my ($base, $max, @directive) = @_;
Packit Service c3aa71
  my $directives = directives ($base, @directive);
Packit Service c3aa71
Packit Service c3aa71
  # Putting this request here is stupid, since the input will be
Packit Service c3aa71
  # generated each time we generate a grammar.
Packit Service c3aa71
  calc_input ('calc', 200);
Packit Service c3aa71
Packit Service c3aa71
  my $out = new IO::File ">$base.y"
Packit Service c3aa71
    or die;
Packit Service c3aa71
  print $out <
Packit Service c3aa71
%{
Packit Service c3aa71
#include <assert.h>
Packit Service c3aa71
#include <stdio.h>
Packit Service c3aa71
#include <stdlib.h>
Packit Service c3aa71
#include <string.h>
Packit Service c3aa71
#include <ctype.h>
Packit Service c3aa71
#define USE(Var)
Packit Service c3aa71
Packit Service c3aa71
/* Exercise pre-prologue dependency to %union.  */
Packit Service c3aa71
typedef int semantic_value;
Packit Service c3aa71
Packit Service c3aa71
static semantic_value global_result = 0;
Packit Service c3aa71
static int global_count = 0;
Packit Service c3aa71
%}
Packit Service c3aa71
Packit Service c3aa71
$directives
Packit Service c3aa71
%error-verbose
Packit Service c3aa71
/* Exercise %union. */
Packit Service c3aa71
%union
Packit Service c3aa71
{
Packit Service c3aa71
  semantic_value ival;
Packit Service c3aa71
};
Packit Service c3aa71
Packit Service c3aa71
%{
Packit Service c3aa71
static int power (int base, int exponent);
Packit Service c3aa71
/* yyerror receives the location if:
Packit Service c3aa71
   - %location & %pure & %glr
Packit Service c3aa71
   - %location & %pure & %yacc & %parse-param. */
Packit Service c3aa71
static void yyerror (const char *s);
Packit Service c3aa71
#if YYPURE
Packit Service c3aa71
static int yylex (YYSTYPE* yylvalp);
Packit Service c3aa71
#else
Packit Service c3aa71
static int yylex (void);
Packit Service c3aa71
#endif
Packit Service c3aa71
%}
Packit Service c3aa71
Packit Service c3aa71
/* Bison Declarations */
Packit Service c3aa71
%token CALC_EOF 0 "end of input"
Packit Service c3aa71
%token <ival> NUM "number"
Packit Service c3aa71
%type  <ival> exp
Packit Service c3aa71
Packit Service c3aa71
%nonassoc '=' /* comparison            */
Packit Service c3aa71
%left '-' '+'
Packit Service c3aa71
%left '*' '/'
Packit Service c3aa71
%left NEG     /* negation--unary minus */
Packit Service c3aa71
%right '^'    /* exponentiation        */
Packit Service c3aa71
Packit Service c3aa71
/* Grammar follows */
Packit Service c3aa71
%%
Packit Service c3aa71
input:
Packit Service c3aa71
  line
Packit Service c3aa71
| input line
Packit Service c3aa71
;
Packit Service c3aa71
Packit Service c3aa71
line:
Packit Service c3aa71
  '\\n'
Packit Service c3aa71
| exp '\\n'           { USE (\$1); }
Packit Service c3aa71
;
Packit Service c3aa71
Packit Service c3aa71
exp:
Packit Service c3aa71
  NUM                { \$\$ = \$1;             }
Packit Service c3aa71
| exp '=' exp
Packit Service c3aa71
  {
Packit Service c3aa71
    if (\$1 != \$3)
Packit Service c3aa71
      fprintf (stderr, "calc: error: %d != %d\\n", \$1, \$3);
Packit Service c3aa71
    \$\$ = \$1;
Packit Service c3aa71
  }
Packit Service c3aa71
| exp '+' exp        { \$\$ = \$1 + \$3;        }
Packit Service c3aa71
| exp '-' exp        { \$\$ = \$1 - \$3;        }
Packit Service c3aa71
| exp '*' exp        { \$\$ = \$1 * \$3;        }
Packit Service c3aa71
| exp '/' exp        { \$\$ = \$1 / \$3;        }
Packit Service c3aa71
| '-' exp  %prec NEG { \$\$ = -\$2;            }
Packit Service c3aa71
| exp '^' exp        { \$\$ = power (\$1, \$3); }
Packit Service c3aa71
| '(' exp ')'        { \$\$ = \$2;             }
Packit Service c3aa71
| '(' error ')'      { \$\$ = 1111;           }
Packit Service c3aa71
| '!'                { \$\$ = 0; YYERROR;     }
Packit Service c3aa71
| '-' error          { \$\$ = 0; YYERROR;     }
Packit Service c3aa71
;
Packit Service c3aa71
%%
Packit Service c3aa71
/* The input.  */
Packit Service c3aa71
static FILE *input;
Packit Service c3aa71
Packit Service c3aa71
static void
Packit Service c3aa71
yyerror (const char *s)
Packit Service c3aa71
{
Packit Service c3aa71
  fprintf (stderr, "%s\\n", s);
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
static int
Packit Service c3aa71
get_char (void)
Packit Service c3aa71
{
Packit Service c3aa71
  return getc (input);
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
Packit Service c3aa71
static void
Packit Service c3aa71
unget_char ( int c)
Packit Service c3aa71
{
Packit Service c3aa71
  ungetc (c, input);
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
static int
Packit Service c3aa71
read_signed_integer (void)
Packit Service c3aa71
{
Packit Service c3aa71
  int c = get_char ();
Packit Service c3aa71
  int sign = 1;
Packit Service c3aa71
  int n = 0;
Packit Service c3aa71
Packit Service c3aa71
  if (c == '-')
Packit Service c3aa71
    {
Packit Service c3aa71
      c = get_char ();
Packit Service c3aa71
      sign = -1;
Packit Service c3aa71
    }
Packit Service c3aa71
Packit Service c3aa71
  while (isdigit (c))
Packit Service c3aa71
    {
Packit Service c3aa71
      n = 10 * n + (c - '0');
Packit Service c3aa71
      c = get_char ();
Packit Service c3aa71
    }
Packit Service c3aa71
Packit Service c3aa71
  unget_char (c);
Packit Service c3aa71
Packit Service c3aa71
  return sign * n;
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
static int
Packit Service c3aa71
#if YYPURE
Packit Service c3aa71
# define yylval (*yylvalp)
Packit Service c3aa71
yylex (YYSTYPE* yylvalp)
Packit Service c3aa71
#else
Packit Service c3aa71
yylex (void)
Packit Service c3aa71
#endif
Packit Service c3aa71
{
Packit Service c3aa71
  int c;
Packit Service c3aa71
Packit Service c3aa71
  /* Skip white space.  */
Packit Service c3aa71
  while ((c = get_char ()) == ' ' || c == '\t')
Packit Service c3aa71
    continue;
Packit Service c3aa71
Packit Service c3aa71
  /* process numbers   */
Packit Service c3aa71
  if (c == '.' || isdigit (c))
Packit Service c3aa71
    {
Packit Service c3aa71
      unget_char ( c);
Packit Service c3aa71
      yylval.ival = read_signed_integer ();
Packit Service c3aa71
      return NUM;
Packit Service c3aa71
    }
Packit Service c3aa71
Packit Service c3aa71
  /* Return end-of-file.  */
Packit Service c3aa71
  if (c == EOF)
Packit Service c3aa71
    return CALC_EOF;
Packit Service c3aa71
Packit Service c3aa71
  /* Return single chars. */
Packit Service c3aa71
  return c;
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
static int
Packit Service c3aa71
power (int base, int exponent)
Packit Service c3aa71
{
Packit Service c3aa71
  assert (0 <= exponent);
Packit Service c3aa71
  int res = 1;
Packit Service c3aa71
  for (/* Niente */; exponent; --exponent)
Packit Service c3aa71
    res *= base;
Packit Service c3aa71
  return res;
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
Packit Service c3aa71
int
Packit Service c3aa71
main (int argc, const char **argv)
Packit Service c3aa71
{
Packit Service c3aa71
  semantic_value result = 0;
Packit Service c3aa71
  int count = 0;
Packit Service c3aa71
  int status;
Packit Service c3aa71
Packit Service c3aa71
#if YYDEBUG
Packit Service c3aa71
  yydebug = !!getenv ("YYDEBUG");
Packit Service c3aa71
#endif
Packit Service c3aa71
Packit Service c3aa71
  input = fopen ("calc.input", "r");
Packit Service c3aa71
  if (!input)
Packit Service c3aa71
    {
Packit Service c3aa71
      perror ("calc.input");
Packit Service c3aa71
      return 3;
Packit Service c3aa71
    }
Packit Service c3aa71
Packit Service c3aa71
  status = yyparse ();
Packit Service c3aa71
  if (global_result != result)
Packit Service c3aa71
    abort ();
Packit Service c3aa71
  if (global_count != count)
Packit Service c3aa71
    abort ();
Packit Service c3aa71
Packit Service c3aa71
  return status;
Packit Service c3aa71
}
Packit Service c3aa71
EOF
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
##################################################################
Packit Service c3aa71
Packit Service c3aa71
=item C<generate_grammar_list ($base, $max, @directive)>
Packit Service c3aa71
Packit Service c3aa71
Generate a Bison file F<$base.y> for a C++ parser that uses C++
Packit Service c3aa71
objects (std::string, std::list).  Tailored for using %define variant.
Packit Service c3aa71
Packit Service c3aa71
=cut
Packit Service c3aa71
Packit Service c3aa71
sub generate_grammar_list ($$@)
Packit Service c3aa71
{
Packit Service c3aa71
  my ($base, $max, @directive) = @_;
Packit Service c3aa71
  my $directives = directives ($base, @directive);
Packit Service c3aa71
  my $variant = grep { /%define "?variant"?/ } @directive;
Packit Service c3aa71
  my $token_ctor = grep { /%define "?api.token.constructor"?/ } @directive;
Packit Service c3aa71
  my $out = new IO::File ">$base.y"
Packit Service c3aa71
    or die;
Packit Service c3aa71
  print $out <
Packit Service c3aa71
%language "C++"
Packit Service c3aa71
%defines
Packit Service c3aa71
%locations
Packit Service c3aa71
$directives
Packit Service c3aa71
Packit Service c3aa71
%code requires // *.h
Packit Service c3aa71
{
Packit Service c3aa71
#include <string>
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
%code // *.c
Packit Service c3aa71
{
Packit Service c3aa71
#include <algorithm>
Packit Service c3aa71
#include <iostream>
Packit Service c3aa71
#include <sstream>
Packit Service c3aa71
Packit Service c3aa71
#define STAGE_MAX    ($max * 10) // max = $max
Packit Service c3aa71
Packit Service c3aa71
#define USE_TOKEN_CTOR $token_ctor
Packit Service c3aa71
#define USE_VARIANTS $variant
Packit Service c3aa71
Packit Service c3aa71
  // Prototype of the yylex function providing subsequent tokens.
Packit Service c3aa71
  static
Packit Service c3aa71
#if USE_TOKEN_CTOR
Packit Service c3aa71
  yy::parser::symbol_type yylex();
Packit Service c3aa71
#else
Packit Service c3aa71
  yy::parser::token_type yylex(yy::parser::semantic_type* yylvalp,
Packit Service c3aa71
                               yy::parser::location_type* yyllocp);
Packit Service c3aa71
#endif
Packit Service c3aa71
Packit Service c3aa71
  // Conversion to string.
Packit Service c3aa71
  template <typename T>
Packit Service c3aa71
    inline
Packit Service c3aa71
    std::string
Packit Service c3aa71
    string_cast (const T& t)
Packit Service c3aa71
  {
Packit Service c3aa71
    std::ostringstream o;
Packit Service c3aa71
    o << t;
Packit Service c3aa71
    return o.str ();
Packit Service c3aa71
  }
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
%token END_OF_FILE 0
Packit Service c3aa71
EOF
Packit Service c3aa71
Packit Service c3aa71
  if ($variant)
Packit Service c3aa71
    {
Packit Service c3aa71
      print $out <<'EOF';
Packit Service c3aa71
%token <std::string> TEXT
Packit Service c3aa71
%token <int> NUMBER
Packit Service c3aa71
%printer { std::cerr << "Number: " << $$; } <int>
Packit Service c3aa71
%printer { std::cerr << "Text: " << $$; } <std::string>
Packit Service c3aa71
%type <std::string> text result
Packit Service c3aa71
Packit Service c3aa71
%%
Packit Service c3aa71
result:
Packit Service c3aa71
  text                  { /* Throw away the result. */ }
Packit Service c3aa71
;
Packit Service c3aa71
Packit Service c3aa71
text:
Packit Service c3aa71
  /* nothing */         { /* This will generate an empty string */ }
Packit Service c3aa71
| text TEXT             { std::swap ($$, $2); }
Packit Service c3aa71
| text NUMBER           { $$ = string_cast($2); }
Packit Service c3aa71
;
Packit Service c3aa71
EOF
Packit Service c3aa71
    }
Packit Service c3aa71
  else
Packit Service c3aa71
    {
Packit Service c3aa71
      # Not using Bison variants.
Packit Service c3aa71
      print $out <<'EOF';
Packit Service c3aa71
%union {int ival; std::string* sval;}
Packit Service c3aa71
%token <sval> TEXT
Packit Service c3aa71
%token <ival> NUMBER
Packit Service c3aa71
%printer { std::cerr << "Number: " << $$; } <ival>
Packit Service c3aa71
%printer { std::cerr << "Text: " << *$$; } <sval>
Packit Service c3aa71
%type <sval> text result
Packit Service c3aa71
Packit Service c3aa71
%%
Packit Service c3aa71
result:
Packit Service c3aa71
  text                  { delete $1; }
Packit Service c3aa71
;
Packit Service c3aa71
Packit Service c3aa71
text:
Packit Service c3aa71
  /* nothing */         { $$ = new std::string; }
Packit Service c3aa71
| text TEXT             { delete $1; $$ = $2; }
Packit Service c3aa71
| text NUMBER           { delete $1; $$ = new std::string (string_cast ($2)); }
Packit Service c3aa71
;
Packit Service c3aa71
EOF
Packit Service c3aa71
    }
Packit Service c3aa71
Packit Service c3aa71
  print $out <<'EOF';
Packit Service c3aa71
%%
Packit Service c3aa71
#
Packit Service c3aa71
Packit Service c3aa71
static
Packit Service c3aa71
#if USE_TOKEN_CTOR
Packit Service c3aa71
yy::parser::symbol_type yylex()
Packit Service c3aa71
#else
Packit Service c3aa71
yy::parser::token_type yylex(yy::parser::semantic_type* yylvalp,
Packit Service c3aa71
                             yy::parser::location_type* yyllocp)
Packit Service c3aa71
#endif
Packit Service c3aa71
{
Packit Service c3aa71
  typedef yy::parser::location_type location_type;
Packit Service c3aa71
  typedef yy::parser::token token;
Packit Service c3aa71
  static int stage = -1;
Packit Service c3aa71
  ++stage;
Packit Service c3aa71
  if (stage == STAGE_MAX)
Packit Service c3aa71
    {
Packit Service c3aa71
#if USE_TOKEN_CTOR
Packit Service c3aa71
      return yy::parser::make_END_OF_FILE (location_type ());
Packit Service c3aa71
#else
Packit Service c3aa71
      *yyllocp = location_type ();
Packit Service c3aa71
      return token::END_OF_FILE;
Packit Service c3aa71
#endif
Packit Service c3aa71
    }
Packit Service c3aa71
  else if (stage % 2)
Packit Service c3aa71
    {
Packit Service c3aa71
#if USE_TOKEN_CTOR
Packit Service c3aa71
      return yy::parser::make_NUMBER (stage, location_type ());
Packit Service c3aa71
#else
Packit Service c3aa71
# if defined ONE_STAGE_BUILD
Packit Service c3aa71
      yylvalp->build(stage);
Packit Service c3aa71
# elif USE_VARIANTS
Packit Service c3aa71
      yylvalp->build<int>() = stage;
Packit Service c3aa71
# else
Packit Service c3aa71
      yylvalp->ival = stage;
Packit Service c3aa71
# endif
Packit Service c3aa71
      *yyllocp = location_type ();
Packit Service c3aa71
      return token::NUMBER;
Packit Service c3aa71
#endif
Packit Service c3aa71
    }
Packit Service c3aa71
  else
Packit Service c3aa71
    {
Packit Service c3aa71
#if USE_TOKEN_CTOR
Packit Service c3aa71
      return yy::parser::make_TEXT ("A string.", location_type ());
Packit Service c3aa71
#else
Packit Service c3aa71
# if defined ONE_STAGE_BUILD
Packit Service c3aa71
      yylvalp->build(std::string("A string."));
Packit Service c3aa71
# elif USE_VARIANTS
Packit Service c3aa71
      yylvalp->build<std::string>() = std::string("A string.");
Packit Service c3aa71
# else
Packit Service c3aa71
      yylvalp->sval = new std::string("A string.");
Packit Service c3aa71
# endif
Packit Service c3aa71
      *yyllocp = location_type ();
Packit Service c3aa71
      return token::TEXT;
Packit Service c3aa71
#endif
Packit Service c3aa71
    }
Packit Service c3aa71
  abort();
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
// Mandatory error function
Packit Service c3aa71
void
Packit Service c3aa71
yy::parser::error(const yy::parser::location_type& loc, const std::string& msg)
Packit Service c3aa71
{
Packit Service c3aa71
  std::cerr << loc << ": " << msg << std::endl;
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
int main(int argc, char *argv[])
Packit Service c3aa71
{
Packit Service c3aa71
  yy::parser p;
Packit Service c3aa71
#if YYDEBUG
Packit Service c3aa71
  p.set_debug_level(!!getenv("YYDEBUG"));
Packit Service c3aa71
#endif
Packit Service c3aa71
  p.parse();
Packit Service c3aa71
  return 0;
Packit Service c3aa71
}
Packit Service c3aa71
EOF
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
##################################################################
Packit Service c3aa71
Packit Service c3aa71
=item C<generate_grammar ($name, $base, @directive)>
Packit Service c3aa71
Packit Service c3aa71
Generate F<$base.y> by calling C<&generate_grammar_$name>.
Packit Service c3aa71
Packit Service c3aa71
=cut
Packit Service c3aa71
Packit Service c3aa71
sub generate_grammar ($$@)
Packit Service c3aa71
{
Packit Service c3aa71
  my ($name, $base, @directive) = @_;
Packit Service c3aa71
  verbose 3, "Generating $base.y\n";
Packit Service c3aa71
  my %generator =
Packit Service c3aa71
    (
Packit Service c3aa71
      "calc"       => \&generate_grammar_calc,
Packit Service c3aa71
      "list"       => \&generate_grammar_list,
Packit Service c3aa71
      "triangular" => \&generate_grammar_triangular,
Packit Service c3aa71
    );
Packit Service c3aa71
  &{$generator{$name}}($base, 200, @directive);
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
##################################################################
Packit Service c3aa71
Packit Service c3aa71
=item C<run ($command)>
Packit Service c3aa71
Packit Service c3aa71
Run, possibly verbosely, the shell C<$command>.
Packit Service c3aa71
Packit Service c3aa71
=cut
Packit Service c3aa71
Packit Service c3aa71
sub run ($)
Packit Service c3aa71
{
Packit Service c3aa71
  my ($command) = @_;
Packit Service c3aa71
  verbose 3, "$command\n";
Packit Service c3aa71
  system ("$command") == 0
Packit Service c3aa71
    or die "$command failed";
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
##################################################################
Packit Service c3aa71
Packit Service c3aa71
=item C<compile ($base)>
Packit Service c3aa71
Packit Service c3aa71
Compile C<$base.y> to an executable C, Using the C or C++ compiler
Packit Service c3aa71
depending on the %language specification in C<$base.y>.
Packit Service c3aa71
Packit Service c3aa71
=cut
Packit Service c3aa71
Packit Service c3aa71
sub compile ($)
Packit Service c3aa71
{
Packit Service c3aa71
  my ($base) = @_;
Packit Service c3aa71
  my $language = `sed -ne '/%language "\\(.*\\)"/{s//\\1/;p;q;}' $base.y`;
Packit Service c3aa71
  chomp $language;
Packit Service c3aa71
Packit Service c3aa71
  my $compiler = $language eq 'C++' ? $cxx : $cc;
Packit Service c3aa71
Packit Service c3aa71
  my $my_bison = `sed -ne '/%bison "\\(.*\\)"/{s//\\1/;p;q;}' $base.y`;
Packit Service c3aa71
  run ((length $my_bison ? $my_bison : $bison) . " $base.y -o $base.c");
Packit Service c3aa71
  run "$compiler -o $base $cflags $base.c";
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
######################################################################
Packit Service c3aa71
Packit Service c3aa71
=item C<bench ($grammar, @token)>
Packit Service c3aa71
Packit Service c3aa71
Generate benches for the C<$grammar> and the directive specification
Packit Service c3aa71
given in the list of C<@token>.
Packit Service c3aa71
Packit Service c3aa71
=cut
Packit Service c3aa71
Packit Service c3aa71
sub bench ($@)
Packit Service c3aa71
{
Packit Service c3aa71
  my ($grammar, @token) = @_;
Packit Service c3aa71
  use Benchmark qw (:all :hireswallclock);
Packit Service c3aa71
Packit Service c3aa71
  my @directive = parse (@token);
Packit Service c3aa71
Packit Service c3aa71
  # Set up the benches as expected by timethese.
Packit Service c3aa71
  my %bench;
Packit Service c3aa71
  # A counter of directive sets.
Packit Service c3aa71
  my $count = 1;
Packit Service c3aa71
  for my $d (@directive)
Packit Service c3aa71
    {
Packit Service c3aa71
      $bench{$count} = $d;
Packit Service c3aa71
      printf " %2d. %s\n", $count, join (' ', split ("\n", $d));
Packit Service c3aa71
      $count++;
Packit Service c3aa71
    };
Packit Service c3aa71
Packit Service c3aa71
  # For each bench, capture the size.
Packit Service c3aa71
  my %size;
Packit Service c3aa71
Packit Service c3aa71
  while (my ($name, $directives) = each %bench)
Packit Service c3aa71
    {
Packit Service c3aa71
      generate_grammar ($grammar, $name, $directives);
Packit Service c3aa71
      # Compile the executable.
Packit Service c3aa71
      compile ($name);
Packit Service c3aa71
      $bench{$name} = "system ('./$name');";
Packit Service c3aa71
      chop($size{$name} = `wc -c <$name`);
Packit Service c3aa71
    }
Packit Service c3aa71
Packit Service c3aa71
  # Run the benches.
Packit Service c3aa71
  #
Packit Service c3aa71
  # STYLE can be any of 'all', 'none', 'noc', 'nop' or 'auto'.  'all'
Packit Service c3aa71
  # shows each of the 5 times available ('wallclock' time, user time,
Packit Service c3aa71
  # system time, user time of children, and system time of
Packit Service c3aa71
  # children). 'noc' shows all except the two children times. 'nop'
Packit Service c3aa71
  # shows only wallclock and the two children times.  'auto' (the
Packit Service c3aa71
  # default) will act as 'all' unless the children times are both
Packit Service c3aa71
  # zero, in which case it acts as 'noc'.  'none' prevents output.
Packit Service c3aa71
  verbose 3, "Running the benches for $grammar\n";
Packit Service c3aa71
  my $res = timethese ($iterations, \%bench, 'nop');
Packit Service c3aa71
Packit Service c3aa71
  # Output the speed result.
Packit Service c3aa71
  cmpthese ($res, 'nop');
Packit Service c3aa71
Packit Service c3aa71
  # Display the sizes.
Packit Service c3aa71
  print "Sizes (decreasing):\n";
Packit Service c3aa71
  my $width = 10;
Packit Service c3aa71
  for my $bench (keys %size)
Packit Service c3aa71
    {
Packit Service c3aa71
      $width = length $bench
Packit Service c3aa71
        if $width < length $bench;
Packit Service c3aa71
    }
Packit Service c3aa71
  # Benches sorted by decreasing size.
Packit Service c3aa71
  my @benches_per_size = sort {$size{$b} <=> $size{$a}} keys %size;
Packit Service c3aa71
  for my $bench (@benches_per_size)
Packit Service c3aa71
    {
Packit Service c3aa71
      printf "%${width}s: %5.2fkB\n", $bench, $size{$bench} / 1024;
Packit Service c3aa71
    }
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
######################################################################
Packit Service c3aa71
Packit Service c3aa71
=item C<bench_push_parser ()>
Packit Service c3aa71
Packit Service c3aa71
Bench the C push parser against the pull parser, pure and impure
Packit Service c3aa71
interfaces.
Packit Service c3aa71
Packit Service c3aa71
=cut
Packit Service c3aa71
Packit Service c3aa71
sub bench_push_parser ()
Packit Service c3aa71
{
Packit Service c3aa71
  bench ('calc',
Packit Service c3aa71
         qw(
Packit Service c3aa71
            [ %d api.pure ]
Packit Service c3aa71
            &
Packit Service c3aa71
            [ %d api.push-pull=both ]
Packit Service c3aa71
         ));
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
######################################################################
Packit Service c3aa71
Packit Service c3aa71
=item C<bench_variant_parser ()>
Packit Service c3aa71
Packit Service c3aa71
Bench the C++ lalr1.cc parser using variants or %union.
Packit Service c3aa71
Packit Service c3aa71
=cut
Packit Service c3aa71
Packit Service c3aa71
sub bench_variant_parser ()
Packit Service c3aa71
{
Packit Service c3aa71
  bench ('list',
Packit Service c3aa71
         qw(
Packit Service c3aa71
            [
Packit Service c3aa71
              %d variant
Packit Service c3aa71
              &
Packit Service c3aa71
              [ #d ONE_STAGE_BUILD | %d api.token.constructor ]
Packit Service c3aa71
            ]
Packit Service c3aa71
         )
Packit Service c3aa71
    );
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
############################################################################
Packit Service c3aa71
Packit Service c3aa71
sub help ($)
Packit Service c3aa71
{
Packit Service c3aa71
  my ($verbose) = @_;
Packit Service c3aa71
  use Pod::Usage;
Packit Service c3aa71
  # See <URL:http://perldoc.perl.org/pod2man.html#NOTES>.
Packit Service c3aa71
  pod2usage( { -message => "Bench Bison parsers",
Packit Service c3aa71
               -exitval => 0,
Packit Service c3aa71
               -verbose => $verbose,
Packit Service c3aa71
               -output  => \*STDOUT });
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
######################################################################
Packit Service c3aa71
Packit Service c3aa71
# The end of the directives to parse.
Packit Service c3aa71
my $eod = "end of directives";
Packit Service c3aa71
# The list of tokens parsed by the following functions.
Packit Service c3aa71
my @token;
Packit Service c3aa71
Packit Service c3aa71
# eat ($EXPECTED)
Packit Service c3aa71
# ---------------
Packit Service c3aa71
# Check that the current token is $EXPECTED, and move to the next.
Packit Service c3aa71
sub eat ($)
Packit Service c3aa71
{
Packit Service c3aa71
  my ($expected) = @_;
Packit Service c3aa71
  die "expected $expected, unexpected: $token[0] (@token)\n"
Packit Service c3aa71
    unless $token[0] eq $expected;
Packit Service c3aa71
  shift @token;
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
# Parse directive specifications:
Packit Service c3aa71
#   expr: term (| term)*
Packit Service c3aa71
#   term: fact (& fact)*
Packit Service c3aa71
#   fact: ( expr ) | [ expr ] | dirs
Packit Service c3aa71
#   dirs: %s SKELETON | #d NAME[=VALUE] | %d NAME[=VALUE] | directive
Packit Service c3aa71
sub parse (@)
Packit Service c3aa71
{
Packit Service c3aa71
  @token = (@_, $eod);
Packit Service c3aa71
  verbose 3, "Parsing: @token\n";
Packit Service c3aa71
  my @res = parse_expr ();
Packit Service c3aa71
  eat ($eod);
Packit Service c3aa71
  return @res;
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
sub parse_expr ()
Packit Service c3aa71
{
Packit Service c3aa71
  my @res = parse_term ();
Packit Service c3aa71
  while ($token[0] eq '|')
Packit Service c3aa71
    {
Packit Service c3aa71
      eat ('|');
Packit Service c3aa71
      # Alternation.
Packit Service c3aa71
      push @res, parse_term ();
Packit Service c3aa71
    }
Packit Service c3aa71
  return @res;
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
sub parse_term ()
Packit Service c3aa71
{
Packit Service c3aa71
  my @res = parse_fact ();
Packit Service c3aa71
  while ($token[0] eq '&')
Packit Service c3aa71
    {
Packit Service c3aa71
      eat ('&';;
Packit Service c3aa71
      # Cartesian product.
Packit Service c3aa71
      my @lhs = @res;
Packit Service c3aa71
      @res = ();
Packit Service c3aa71
      for my $rhs (parse_fact ())
Packit Service c3aa71
        {
Packit Service c3aa71
          for my $lhs (@lhs)
Packit Service c3aa71
            {
Packit Service c3aa71
              push @res, $lhs . ($lhs && $rhs ? "\n" : "") . $rhs;
Packit Service c3aa71
            }
Packit Service c3aa71
        }
Packit Service c3aa71
    }
Packit Service c3aa71
  return @res;
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
sub parse_fact ()
Packit Service c3aa71
{
Packit Service c3aa71
  my @res;
Packit Service c3aa71
  die "unexpected end of expression"
Packit Service c3aa71
    unless defined $token[0];
Packit Service c3aa71
Packit Service c3aa71
  if ($token[0] eq '(')
Packit Service c3aa71
    {
Packit Service c3aa71
      eat ('(');
Packit Service c3aa71
      @res = parse_expr ();
Packit Service c3aa71
      eat (')');
Packit Service c3aa71
    }
Packit Service c3aa71
  elsif ($token[0] eq '[')
Packit Service c3aa71
    {
Packit Service c3aa71
      eat ('[');
Packit Service c3aa71
      @res = (parse_expr (), '');
Packit Service c3aa71
      eat (']');
Packit Service c3aa71
    }
Packit Service c3aa71
  else
Packit Service c3aa71
    {
Packit Service c3aa71
      @res = parse_dirs ();
Packit Service c3aa71
    }
Packit Service c3aa71
  return @res;
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
sub parse_dirs ()
Packit Service c3aa71
{
Packit Service c3aa71
  my @res;
Packit Service c3aa71
  die "unexpected end of expression"
Packit Service c3aa71
    unless defined $token[0];
Packit Service c3aa71
Packit Service c3aa71
  if ($token[0] eq '#d')
Packit Service c3aa71
    {
Packit Service c3aa71
      eat ('#d');
Packit Service c3aa71
      $token[0] =~ s/(.*?)=(.*)/$1 $2/;
Packit Service c3aa71
      @res = ("%code {\n#define $token[0]\n}");
Packit Service c3aa71
      shift @token;
Packit Service c3aa71
    }
Packit Service c3aa71
  elsif ($token[0] eq '%d')
Packit Service c3aa71
    {
Packit Service c3aa71
      shift @token;
Packit Service c3aa71
      $token[0] =~ s/(.*?)=(.*)/$1 "$2"/;
Packit Service c3aa71
      @res = ("%define $token[0]");
Packit Service c3aa71
      shift @token;
Packit Service c3aa71
    }
Packit Service c3aa71
  elsif ($token[0] eq '%s')
Packit Service c3aa71
    {
Packit Service c3aa71
      shift @token;
Packit Service c3aa71
      @res = ("%skeleton \"$token[0]\"");
Packit Service c3aa71
      shift @token;
Packit Service c3aa71
    }
Packit Service c3aa71
  elsif ($token[0] eq '%b')
Packit Service c3aa71
    {
Packit Service c3aa71
      shift @token;
Packit Service c3aa71
      @res = ("/*\n%bison \"$token[0]\"\\\n*/");
Packit Service c3aa71
      shift @token;
Packit Service c3aa71
    }
Packit Service c3aa71
  else
Packit Service c3aa71
    {
Packit Service c3aa71
      @res = $token[0];
Packit Service c3aa71
      shift @token;
Packit Service c3aa71
    }
Packit Service c3aa71
Packit Service c3aa71
  return @res;
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
######################################################################
Packit Service c3aa71
Packit Service c3aa71
sub getopt ()
Packit Service c3aa71
{
Packit Service c3aa71
  use Getopt::Long;
Packit Service c3aa71
  my %option = (
Packit Service c3aa71
    "b|bench=s"      => \$bench,
Packit Service c3aa71
    "c|cflags=s"     => \$cflags,
Packit Service c3aa71
    "d|directive=s"  => \@directive,
Packit Service c3aa71
    "g|grammar=s"    => \$grammar,
Packit Service c3aa71
    "h|help"         => sub { help ($verbose) },
Packit Service c3aa71
    "i|iterations=i" => \$iterations,
Packit Service c3aa71
    "q|quiet"        => sub { --$verbose },
Packit Service c3aa71
    "v|verbose"      => sub { ++$verbose },
Packit Service c3aa71
    );
Packit Service c3aa71
  Getopt::Long::Configure ("bundling", "pass_through");
Packit Service c3aa71
  GetOptions (%option)
Packit Service c3aa71
    or exit 1;
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
######################################################################
Packit Service c3aa71
Packit Service c3aa71
getopt;
Packit Service c3aa71
Packit Service c3aa71
# Create the directory we work in.
Packit Service c3aa71
mkdir "benches" or die "cannot create benches"
Packit Service c3aa71
  unless -d "benches";
Packit Service c3aa71
my $count = 1;
Packit Service c3aa71
++$count
Packit Service c3aa71
  while -d "benches/$count";
Packit Service c3aa71
my $dir = "benches/$count";
Packit Service c3aa71
mkdir $dir
Packit Service c3aa71
  or die "cannot create $dir";
Packit Service c3aa71
chdir $dir
Packit Service c3aa71
  or die "cannot chdir $dir";
Packit Service c3aa71
Packit Service c3aa71
# The following message is tailored to please Emacs' compilation-mode.
Packit Service c3aa71
verbose 1, "Entering directory `$dir'\n";
Packit Service c3aa71
verbose 1, "Using bison=$bison.\n";
Packit Service c3aa71
verbose 2, "Using cc=$cc.\n";
Packit Service c3aa71
verbose 2, "Using cxx=$cxx.\n";
Packit Service c3aa71
verbose 2, "Using cflags=$cflags.\n";
Packit Service c3aa71
verbose 2, "Grammar: $grammar\n";
Packit Service c3aa71
Packit Service c3aa71
Packit Service c3aa71
# Support -b: predefined benches.
Packit Service c3aa71
my %bench =
Packit Service c3aa71
  (
Packit Service c3aa71
   "push"     => \&bench_push_parser,
Packit Service c3aa71
   "variant"  => \&bench_variant_parser,
Packit Service c3aa71
  );
Packit Service c3aa71
Packit Service c3aa71
if (defined $bench)
Packit Service c3aa71
{
Packit Service c3aa71
  die "invalid argument for --bench: $bench"
Packit Service c3aa71
    unless defined $bench{$bench};
Packit Service c3aa71
  &{$bench{$bench}}();
Packit Service c3aa71
  exit 0;
Packit Service c3aa71
}
Packit Service c3aa71
else
Packit Service c3aa71
{
Packit Service c3aa71
  # Launch the bench marking.
Packit Service c3aa71
  bench ($grammar, @ARGV);
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
### Setup "GNU" style for perl-mode and cperl-mode.
Packit Service c3aa71
## Local Variables:
Packit Service c3aa71
## perl-indent-level: 2
Packit Service c3aa71
## perl-continued-statement-offset: 2
Packit Service c3aa71
## perl-continued-brace-offset: 0
Packit Service c3aa71
## perl-brace-offset: 0
Packit Service c3aa71
## perl-brace-imaginary-offset: 0
Packit Service c3aa71
## perl-label-offset: -2
Packit Service c3aa71
## cperl-indent-level: 2
Packit Service c3aa71
## cperl-brace-offset: 0
Packit Service c3aa71
## cperl-continued-brace-offset: 0
Packit Service c3aa71
## cperl-label-offset: -2
Packit Service c3aa71
## cperl-extra-newline-before-brace: t
Packit Service c3aa71
## cperl-merge-trailing-else: nil
Packit Service c3aa71
## cperl-continued-statement-offset: 2
Packit Service c3aa71
## End: