FAQ
Hi,

I'm almost finished with the script (the stripped down test case
is on the bottom of this mail) which parses cpp-preprocessed output.

The pecularity of parsing cpp-output is that if the cpp-processed
file #includes a file, then cpp prints a linemarker line, like:

# 1 "..\\mmstorageiface\\group\\bld.inf" 1

In my script I keep track of the current working directory and
update it (in the updateCurdir() below) whenever a linemarker
rule (with flags 1 or 2) triggers. The script works fine for
the most of my input files, but there are few that break it.

There are 5 kind of sections started by the "section" terminal.
And the problem comes when the input file #includes another
file, while being in the middle of one section, like here:

PRJ_MMPFILES
MMSTORAGEIFACE.MMP
..\GROUP\PNMSG.MMP
# 72 "bld.inf" 2
makefile ..\group\convcolor.mk

The section above is started by the "PRJ_MMPFILES" terminal,
then 2 paths to .mmp files are coming and then (unexpected)
the cpp-linemarker comes before the last path.

What could I do now to solve this problem, please?

I can't just skip the linemarker comments as in P::RD::FAQ.

I also don't want to prepend the linemarker subrule to each
of the 5 section rules, like here:

prj_mmpfile: /PRJ_MMPFILES\b/i
(linemarker | mmpfile[\%::prj_mmpfiles])(s?)

because that would make my script really unreadable and
because I'll have to add an if-statement into each of the
5 actions in order to distinguish if it was triggered by
another linemarker or by the normal section entry.

Any advices please?

Regards
Alex


#!/usr/bin/perl

use strict;
use vars qw($parser $text %prj_platforms %prj_exports
%prj_testexports %prj_mmpfiles %prj_testmmpfiles);
use Parse::RecDescent;
# platforms to use when 'DEFAULT' has been specified
use constant DEFPLATS => qw(ARMI ARM4 THUMB WINS WINSCW);
#$RD_WARN = 1;
#$RD_HINT = 1;
#$RD_TRACE = 120;
use constant GRAMMAR => q(

inffile: chunk(s) /^\Z/
chunk: linemarker |
prj_platform |
prj_export |
prj_testexport |
prj_mmpfile |
prj_testmmpfile |
<error>

# cpp linemarker, as described in cpp manual "Preprocessor output"
linemarker: '#' <skip: '[ \t]+'> linenum path flag(s?) {
::updateCurdir($item{path}, $item[-1]);
}
linenum: /\d+/
flag: '1' | '2' | '3' | '4'

prj_platform: /PRJ_PLATFORMS\b/i platform(s?) {
# go through all specified platforms
for my $p (@{$item[-1]}) {
if ($p =~ /^DEFAULT$/i) {
# store the names of 5 default platforms
@::prj_platforms{::DEFPLATS} = (1) x 5;
} else {
$::prj_platforms{uc $p} = 1;
}
}
}
# TODO: make these terminals ignore filenames like TOOLS.mk
platform:
/ARM4\b/i |
/ARMI\b/i |
/DEFAULT\b/i |
/MCOT\b/i |
/MCOY\b/i |
/MEIG\b/i |
/MHELEN\b/i |
/MINT\b/i |
/MISA\b/i |
/MLNK\b/i |
/MTEMPLATE\b/i |
/MWD2\b/i |
/THUMB\b/i |
# don't match TOOLS.mk
/TOOLS(?=(?:\s|\Z))/i |
/WINC\b/i |
/WINSCW\b/i |
/WINS\b/i

# the rules prj_export and prj_testexport below are similar, so they
# just pass a reference to the corresponding hash down to the export rule
prj_export: /PRJ_EXPORTS\b/i export[\%::prj_exports](s?)
prj_testexport: /PRJ_TESTEXPORTS\b/i export[\%::prj_testexports](s?)
# export statements are terminated by newlines, so don't skip newlines
export: path <skip: '[ \t]+'> path(?) {
::storeExpPath($arg[0], $item[1], $item[-1]->[0]);
}

# the rules prj_mmpfile and prj_testmmpfile below are similar, so they
# just pass a reference to the corresponding hash down to the mmpfile rule
prj_mmpfile: /PRJ_MMPFILES\b/i mmpfile[\%::prj_mmpfiles](s?)
prj_testmmpfile: /PRJ_TESTMMPFILES\b/i mmpfile[\%::prj_testmmpfiles](s?)
mmpfile: makefile(?) path special(?) {
::storeMmpPath($arg[0], $item[1]->[0], $item{path}, $item[-1]->[0]);
}

path: /"([^"]*)"/ {
::unixifyPath($1);
}
...!section ...!platform ...!linemarker /\S+/ {
::unixifyPath($item[-1]);
}
section:
/PRJ_EXPORTS\b/i |
/PRJ_MMPFILES\b/i |
/PRJ_PLATFORMS\b/i |
/PRJ_TESTEXPORTS\b/i |
/PRJ_TESTMMPFILES\b/i
makefile:
/GNUMAKEFILE\b/i |
/MAKEFILE\b/i |
/NMAKEFILE\b/i
special:
/TIDY\b/i |
/IGNORE\b/i |
/MANUAL\b/i |
/SUPPORT\b/i
);

# the actual functions are larger, but I've skipped them here
sub unixifyPath($) { return 1; }
sub updateCurdir($$) { return 1; }
sub storeExpPath($$$) { return 1; }
sub storeMmpPath($$$$) { return 1; }

$parser = Parse::RecDescent->new(GRAMMAR) or die 'Bad grammar';
$text .= $_ while (<DATA>);
defined $parser->inffile($text) or die 'Bad text';

__DATA__
PRJ_PLATFORMS
DEFAULT WINC

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

# 1 "..\\mmstorageiface\\group\\bld.inf" 1

PRJ_MMPFILES
MMSTORAGEIFACE.MMP
..\GROUP\PNMSG.MMP
# 72 "bld.inf" 2
makefile ..\group\convcolor.mk

PRJ_TESTMMPFILES

Search Discussions

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouprecdescent @
categoriesperl
postedJun 3, '04 at 1:55p
activeJun 3, '04 at 1:55p
posts1
users1
websitemetacpan.org...

1 user in discussion

Alexander Farber: 1 post

People

Translate

site design / logo © 2018 Grokbase