On Friday, May 28, 2004 [EMAIL PROTECTED] said: > Hi, > > I have a not-so-important, cosmetic question. > > I'm trying to convert some weird Windows based build system > to GNU Makefiles on Unix. The script at the bottom of this > mail works for me, but I do appreciate any comments on that. > > My question is: first I've written this action which didn't work: > > export: path <skip: '[ \t]+'> path(?) { > # ignore if a special keyword has been used as destination > return 1 if $item[-1]->[0] =~ /^(IGNORE|MANUAL|SUPPORT)$/i; > # rest of the action, pretty long > }
Which does not work because you subvert the rest of the "hidden" code put in there for you by PR::D. > > So I had to remove the "return 1" above and use this instead > > export: path <skip: '[ \t]+'> path(?) { > # ignore if a special keyword has been used as destination > if ($item[-1]->[0] =~ /^(IGNORE|MANUAL|SUPPORT)$/i) { > 1; > } else { > # rest of the action, pretty long > } > > which feels a bit awkward to me. Is there a nicer way? Only to set the value of the "$return" variable. Remember what is happening here, PR::D is *really* a compiler. It takes your description and produces a full stand-alone code stream. Any action is actually part of a whole subroutine that PR::D creates. To create the action you have to stick within the semantics of the environment just as if you were programming in 'C'. To show you what I mean, turn on $::RD_TRACE and then look at the code it produces (called, oddly enough "RD_TRACE"). When you look for the code in your action you will get a lot of "extra" stuff that you did not define. This is being put there by the PR::D 'compiler' to make the resulting code stream self consistent according to the internal structure of PR::D. Alternative plan 'B' is a look-ahead: export: path <skip: '[ \t]+'> path(?) { blah blah } path /"[^"]*"/ | ...!sectionorkeyword /\S+/ sectionorkeyword: section | /^(IGNORE|MANUAL|SUPPORT)$/i Here export will fail because path fails, and path fails because it contains your magic keyword. For example try this: use strict; use vars qw($parser $text %prj_exports %prj_testexports); use Data::Dumper; use Parse::RecDescent; use File::Spec; use File::Spec::Win32; use File::Spec::Unix; use Getopt::Std; # where to copy the exported files by default use constant DEFINCDIR => 'epoc32/include'; #$RD_WARN = 1; #$RD_HINT = 1; #$RD_TRACE = 120; $parser = Parse::RecDescent->new(q( inffile: chunk(s) /^\Z/ chunk: prj_export | prj_testexport | <error> prj_export: /PRJ_EXPORTS\b/i export[\%::prj_exports](s?) prj_testexport: /PRJ_TESTEXPORTS\b/i export[\%::prj_testexports](s?) export: path <skip: '[ \t]+'> path(?) { # ignore if a special keyword has been used as destination # reference to the %prj_exports or %prj_testexports my $href = $arg[0]; # the 1st "path" above is source the 2nd - destination. # split the both paths into drive (unused) + dir + filename my ($srcdrive, $srcdir, $srcfile) = File::Spec::Win32->splitpath($item[1]); my ($dstdrive, $dstdir, $dstfile) = File::Spec::Win32->splitpath($item[-1]->[0]); # replace backslashes through slashes in both dirs $srcdir =~ y|\\\\|/|; $dstdir =~ y|\\\\|/|; # the full paths, consisting of dir + filename my ($srcpath, $dstpath); # if no destination specified, use default dir + source file if (not $dstdir) { $dstdir = ::DEFINCDIR; $dstfile = $srcfile; # if destination is just a dir, use the source filename } elsif (not $dstfile) { $dstfile = $srcfile; } # a source file can go to several destinations, so use # the latter as the hash keys, because they are unique $srcpath = File::Spec::Unix->catfile($srcdir, $srcfile); $dstpath = File::Spec::Unix->catfile($dstdir, $dstfile); $href->{$dstpath} = $srcpath; } path: /"[^"]*"/ | ...!sectionorkeyword /\S+/ sectionorkeyword: section | /^(IGNORE|MANUAL|SUPPORT)$/i section: /PRJ_EXPORTS\b/i | /PRJ_TESTEXPORTS\b/i )) or die 'Bad grammar'; $text .= $_ while (<DATA>); defined $parser->inffile($text) or die 'Bad text'; print STDERR Data::Dumper->Dump([\%prj_exports, \%prj_testexports], [qw(prj_exports prj_testexports)]); __DATA__ PRJ_EXPORTS ..\inc\cmmphonebookstoreextinterface.h \tcf\cmmphonebookstoreextinterface.h ..\inc\cmmphonebookstoremesshandler.h \tcf ..\inc\cmmonstoremesshandler.h MANUAL ..\inc\cmmonstoreextinterface.h ignore PRJ_TESTEXPORTS ..\inc\cmmenstoreextinterface.h \tcf\cmmenstoreextinterface.h ..\inc\cmmenstoremesshandler.h mmstorageiface.iby \epoc32\rom\include\mmstorageiface.iby > > Regards > Alex > > #!/usr/bin/perl > > use strict; > use vars qw($parser $text %prj_exports %prj_testexports); > use Data::Dumper; > use Parse::RecDescent; > use File::Spec; > use File::Spec::Win32; > use File::Spec::Unix; > use Getopt::Std; > # where to copy the exported files by default > use constant DEFINCDIR => 'epoc32/include'; > #$RD_WARN = 1; > #$RD_HINT = 1; > #$RD_TRACE = 120; > $parser = Parse::RecDescent->new(q( > > inffile: chunk(s) /^\Z/ > chunk: prj_export | > prj_testexport | > <error> > prj_export: /PRJ_EXPORTS\b/i export[\%::prj_exports](s?) > prj_testexport: /PRJ_TESTEXPORTS\b/i export[\%::prj_testexports](s?) > export: path <skip: '[ \t]+'> path(?) { > # ignore if a special keyword has been used as destination > if ($item[-1]->[0] =~ /^(IGNORE|MANUAL|SUPPORT)$/i) { > 1; > } else { > # reference to the %prj_exports or %prj_testexports > my $href = $arg[0]; > # the 1st "path" above is source the 2nd - destination. > # split the both paths into drive (unused) + dir + filename > my ($srcdrive, $srcdir, $srcfile) = > File::Spec::Win32->splitpath($item[1]); > my ($dstdrive, $dstdir, $dstfile) = > File::Spec::Win32->splitpath($item[-1]->[0]); > # replace backslashes through slashes in both dirs > $srcdir =~ y|\\\\|/|; > $dstdir =~ y|\\\\|/|; > # the full paths, consisting of dir + filename > my ($srcpath, $dstpath); > # if no destination specified, use default dir + source file > if (not $dstdir) { > $dstdir = ::DEFINCDIR; > $dstfile = $srcfile; > # if destination is just a dir, use the source filename > } elsif (not $dstfile) { > $dstfile = $srcfile; > } > # a source file can go to several destinations, so use > # the latter as the hash keys, because they are unique > $srcpath = File::Spec::Unix->catfile($srcdir, $srcfile); > $dstpath = File::Spec::Unix->catfile($dstdir, $dstfile); > $href->{$dstpath} = $srcpath; > } > } > path: /"[^"]*"/ | ...!section /\S+/ > section: > /PRJ_EXPORTS\b/i | > /PRJ_TESTEXPORTS\b/i > > )) or die 'Bad grammar'; > $text .= $_ while (<DATA>); > defined $parser->inffile($text) or die 'Bad text'; > print STDERR Data::Dumper->Dump([\%prj_exports, \%prj_testexports], > [qw(prj_exports prj_testexports)]); > __DATA__ > PRJ_EXPORTS > ..\inc\cmmphonebookstoreextinterface.h \tcf\cmmphonebookstoreextinterface.h > ..\inc\cmmphonebookstoremesshandler.h \tcf > > ..\inc\cmmonstoremesshandler.h MANUAL > ..\inc\cmmonstoreextinterface.h ignore > > PRJ_TESTEXPORTS > ..\inc\cmmenstoreextinterface.h \tcf\cmmenstoreextinterface.h > ..\inc\cmmenstoremesshandler.h > > mmstorageiface.iby \epoc32\rom\include\mmstorageiface.iby > -- Intel, Corp. 5000 W. Chandler Blvd. Chandler, AZ 85226 -- Intel, Corp. 5000 W. Chandler Blvd. Chandler, AZ 85226