Re: return from action [Version 2.0]

[email protected] ("Ron D. Smith") Fri, 28 May 2004 10:40:14 -0700
Newsgroups perl.recdescent
Message-ID <[email protected]>
Oops.


On Friday, May 28, 2004 "Ron D. Smith" said:

> 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(?) ...!sectionorkeyword {
	# 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 keyword
path:	/"[^"]*"/ | ...!sectionorkeyword /\S+/
sectionorkeyword: section | keyword
keyword: /(IGNORE|MANUAL|SUPPORT)\b/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
> 

--
 Intel, Corp.
 5000 W. Chandler Blvd.
 Chandler, AZ 85226

-- 
 Intel, Corp.
 5000 W. Chandler Blvd.
 Chandler, AZ  85226