1#!/usr/bin/perl 2# 3# yapp -- Front end to the Parse::Yapp module 4# 5# (c) Copyright 1998-2001 Francois Desarmenien, all rights reserved. 6# (see the pod text in Parse::Yapp module for use and distribution rights) 7# 8# 9 10=head1 NAME 11 12yapp - A perl frontend to the Parse::Yapp module 13 14 15=head1 SYNOPSYS 16 17yapp [options] I<grammar>[.yp] 18 19yapp I<-V> 20 21yapp I<-h> 22 23 24=head1 DESCRIPTION 25 26yapp is a frontend to the Parse::Yapp module, which lets you compile 27Parse::Yapp grammar input files into Perl LALR(1) OO parser modules. 28 29 30=head1 OPTIONS 31 32Options, as of today, are all optionals :-) 33 34=over 4 35 36=item I<-v> 37 38Creates a file F<grammar>.output describing your parser. It will 39show you a summary of conflicts, rules, the DFA (Deterministic 40Finite Automaton) states and overall usage of the parser. 41 42=item I<-s> 43 44Create a standalone module in which the driver is included. 45Note that if you have more than one parser module called from 46a program, to have it standalone, you need this option only 47for one of your parser module. 48 49=item I<-n> 50 51Disable source file line numbering embedded in your parser module. 52I don't know why one should need it, but it's there. 53 54=item I<-m module> 55 56Gives your parser module the package name (or name space or module name or 57class name or whatever-you-call-it) of F<module>. It defaults to F<grammar> 58 59=item I<-o outfile> 60 61The compiled output file will be named F<outfile> for your parser module. 62It defaults to F<grammar>.pm or, if you specified the option 63I<-m A::Module::Name> (see below), to F<Name.pm>. 64 65=item I<-t filename> 66 67The I<-t filename> option allows you to specify a file which should be 68used as template for generating the parser output. The default is to 69use the internal template defined in F<Parse::Yapp::Output.pm>. 70For how to write your own template and which substitutions are available, 71have a look to the module F<Parse::Yapp::Output.pm> : it should be obvious. 72 73=item I<-b shebang> 74 75If you work on systems that understand so called I<shebangs>, and your 76generated parser is directly an executable script, you can specifie one 77with the I<-b> option, ie: 78 79 yapp -b '/usr/local/bin/perl -w' -o myscript.pl myscript.yp 80 81This will output a file called F<myscript.pl> whose very first line is: 82 83 #!/usr/local/bin/perl -w 84 85The argument is mandatory, but if you specify an empty string, the value 86of I<$Config{perlpath}> will be used instead. 87 88=item I<grammar> 89 90The input grammar file. If no suffix is given, and the file does not exists, 91an attempt to open the file with a suffix of F<.yp> is tried before exiting. 92 93=item I<-V> 94 95Display current version of Parse::Yapp and gracefully exits. 96 97=item I<-h> 98 99Display the usage screen. 100 101=back 102 103=head1 BUGS 104 105None known now :-) 106 107=head1 AUTHOR 108 109Francois Desarmenien <francois@fdesar.net> 110 111=head1 COPYRIGHT 112 113(c) Copyright 1998-1999 Francois Desarmenien, all rights reserved. 114See Parse::Yapp(3) for legal use and distribution rights 115 116=head1 SEE ALSO 117 118Parse::Yapp(3) Perl(1) yacc(1) bison(1) 119 120 121=cut 122 123require 5.004; 124 125use File::Basename; 126use Getopt::Std; 127use Config; 128use Parse::Yapp; 129 130use strict; 131 132use vars qw ( $opt_n $opt_m $opt_V $opt_v $opt_o $opt_h $opt_s $opt_t $opt_b); 133 134sub Usage { 135 my($prog)=(fileparse($0,'\..*'))[0]; 136 die <<EOF; 137 138Usage: $prog [options] grammar[.yp] 139 or $prog -V 140 or $prog -h 141 142 -m module Give your parser module the name <module> 143 default is <grammar> 144 -v Create a file <grammar>.output describing your parser 145 -s Create a standalone module in which the driver is included 146 -n Disable source file line numbering embedded in your parser 147 -o outfile Create the file <outfile> for your parser module 148 Default is <grammar>.pm or, if -m A::Module::Name is 149 specified, Name.pm 150 -t filename Uses the file <filename> as a template for creating the parser 151 module file. Default is to use internal template defined 152 in Parse::Yapp::Output 153 -b shebang Adds '#!<shebang>' as the very first line of the output file 154 155 grammar The grammar file. If no suffix is given, and the file 156 does not exists, .yp is added 157 158 -V Display current version of Parse::Yapp and gracefully exits 159 -h Display this help screen 160 161EOF 162} 163 164my($nbargs)=@ARGV; 165 166 getopts('Vhvsnb:m:t:o:') 167or Usage; 168 169 ( ($opt_V and $nbargs > 1) 170 or $opt_h) 171and Usage; 172 173 $opt_V 174and do { 175 176 @ARGV == 0 or Usage; 177 178 print "This is Parse::Yapp version $Parse::Yapp::Driver::VERSION.\n"; 179 exit(0); 180 181}; 182 183 184# -t <filename> ($opt_t) option allows a file to be specified which 185# contains a 'template' to be used when generating the parser; 186# if defined, we open and read the file. 187 188 $opt_t 189and do { 190 local $/ = undef; 191 local *TFILE; 192 open(TFILE, $opt_t) 193 or die "Cannot open template file $opt_t: $!\n"; 194 $opt_t = <TFILE>; 195 close(TFILE); 196}; 197 198 @ARGV == 1 199or Usage; 200 201my($filename)=$ARGV[0]; 202my($base,$path,$sfx)=fileparse($filename,'\..*'); 203 204 -r "$filename" 205or do { 206 $sfx eq '.yp' 207 or $filename.='.yp'; 208 209 -r "$filename" 210 or die "Cannot open $filename for reading.\n"; 211}; 212 213my($parser)=new Parse::Yapp(inputfile => $filename); 214 215my($warnings)=$parser->Warnings(); 216 217 $warnings 218and print STDERR $warnings; 219 220 $opt_v 221and do { 222 my($output)="$path$base.output"; 223 my($tmp); 224 225 open(OUT,">$output") 226 or die "Cannot create $base.output for writing.\n"; 227 228 $tmp=$parser->Warnings() 229 and print OUT "Warnings:\n---------\n$tmp\n"; 230 $tmp=$parser->Conflicts() 231 and print OUT "Conflicts:\n----------\n$tmp\n"; 232 print OUT "Rules:\n------\n"; 233 print OUT $parser->ShowRules()."\n"; 234 print OUT "States:\n-------\n"; 235 print OUT $parser->ShowDfa()."\n"; 236 print OUT "Summary:\n--------\n"; 237 print OUT $parser->Summary(); 238 239 close(OUT); 240}; 241 242my($outfile)="$path$base.pm"; 243my($package)="$base"; 244 245 $opt_m 246and do { 247 $package=$opt_m; 248 $package=~/^(?:(?:[^:]|:(?!:))*::)*(.*)$/; 249 $outfile="$1.pm"; 250}; 251 252 $opt_o 253and $outfile=$opt_o; 254 255$opt_s = $opt_s ? 1 : 0; 256 257$opt_n = $opt_n ? 0 : 1; 258 259 open(OUT,">$outfile") 260or die "Cannot open $outfile for writing.\n"; 261 262 defined($opt_b) 263and do { 264 $opt_b 265 or $opt_b = $Config{perlpath}; 266 print OUT "#!$opt_b\n"; 267}; 268 269print OUT $parser->Output(classname => $package, 270 standalone => $opt_s, 271 linenumbers => $opt_n, 272 template => $opt_t, 273 ); 274 275 276close(OUT); 277 278