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


Reply via email to