Rinchi-Fortran-Preprocessor
view release on metacpan or search on metacpan
lib/Rinchi/Fortran/Preprocessor.pm view on Meta::CPAN
Rinchi::Fortran::Preprocessor - An Fortran to XML preprocessor extension for
preprocessing Fortran files producing XML SAX parser events for the tokens
scanned.
=head1 SYNOPSIS
use Rinchi::Fortran::Preprocessor;
my @args = (
'test.pl',
'-I/usr/include',
'-Uccc',
);
my $closed = 0;
my $fpp = new Rinchi::Fortran::Preprocessor;
$fpp->setHandlers('Start' => \&startElementHandler,
'End' => \&endElementHandler,
'Char' => \&characterDataHandler,
'Proc' => \&processingInstructionHandler,
'Comment' => \&commentHandler,
'CdataStart' => \&startCdataHandler,
'CdataEnd' => \&endCdataHandler,
'XMLDecl' => \&xmlDeclHandler,
);
$fpp->process_file('test_src/include_test_1.h',\@args);
sub startElementHandler() {
my ($tag, $hasChild, %attrs) = @_;
print "<$tag";
foreach my $attr (sort keys %attrs) {
my $val = $attrs{$attr};
$val =~ s/&/&/g;
$val =~ s/</</g;
$val =~ s/>/>/g;
$val =~ s/\"/"/g;
$val =~ s/\'/'/g;
print " $attr=\"$val\"";
}
if ($hasChild == 0) {
print " />";
$closed = 1;
} else {
print ">";
$closed = 0;
}
}
sub endElementHandler() {
my ($tag) = @_;
if ($closed == 0) {
print "</$tag>\n";
} else {
$closed = 0;
}
}
sub characterDataHandler() {
my ($cdata) = @_;
print $cdata;
}
sub processingInstructionHandler() {
my ($target,$data) = @_;
print "<?$target $data?>\n";
}
sub commentHandler() {
my ($string) = @_;
print "<!-- $string -->\n";
}
sub startCdataHandler() {
print "<![CDATA[";
}
sub endCdataHandler() {
print "]]>";
}
sub xmlDeclHandler() {
my ($version, $encoding, $standalone) = @_;
print "<?xml version=\"$version\" encoding=\"$encoding\" standalone=\"$standalone\"?>\n";
}
=head1 DESCRIPTION
This module provides an interface to a Fortran preprocessor.
=head2 EXPORT
None by default.
=head1 METHODS
=over 4
=item new
Constructor for Fortran::Preprocessor. Options are TBD.
=cut
sub new {
my ($class, %args) = @_;
my $self = bless \%args, $class;
$args{'_State_'} = 0;
$args{'Context'} = [];
$args{'ErrorMessage'} ||= '';
$args{'_Setters'} = \%Handler_Setters;
# $args{Parser} = ParserCreate($self, $args{ProtocolEncoding},
# $args{Namespaces});
$self;
}
=item setHandlers(TYPE, HANDLER [, TYPE, HANDLER [...]])
This method registers handlers for the various events.
Setting a handler to something that evaluates to false unsets that
handler.
This method returns a list of type, handler pairs corresponding to the
input. The handlers returned are the ones that were in effect before the
call to setHandlers.
The recognized events and the parameters passed to the corresponding
handlers are:
=over 4
=item * Start (tagname, hasChild [, attrName, attrValue [,...]])
my ($tag, $hasChild, %attrs) = @_;
print "<$tag";
foreach my $attr (sort keys %attrs) {
my $val = $attrs{$attr};
$val =~ s/&/&/g;
$val =~ s/</</g;
$val =~ s/>/>/g;
$val =~ s/\"/"/g;
$val =~ s/\'/'/g;
print " $attr=\"$val\"";
}
print ">\n";
This event is generated when an XML start tag is recognized. Parameter tagname
is the name of the XML element that is opened with the start tag. Parameter
hasChild indicates the presence of contained nodes. The attrName
and attrValue pairs are generated for each attribute in the start tag.
=item * End (tagname)
my ($tag) = @_;
print "</$tag>\n";
This event is generated when an XML end tag is recognized. Note that
an XML empty tag (<tagname/>) generates both a start and an end event.
=item * Char (String)
my ($cdata) = @_;
print $cdata;
This event is generated when non-markup is recognized. The non-markup
sequence of characters is in String. A single non-markup sequence of
characters may generate multiple calls to this handler. Whatever the
encoding of the string in the original document, this is given to the
handler in UTF-8.
=item * Proc (target, data)
my ($target,$data) = @_;
print "<?$target $data?>\n";
This event is generated when a processing instruction is created. Processing
instructions are used to convey locations and error messages.
=item * Comment (String)
my ($string) = @_;
print "<!-- $string -->\n";
This event is generated when a comment is recognized.
=item * CdataStart ()
print "<![CDATA[";
This is called at the start of a CDATA section.
=item * CdataEnd ()
print "]]>";
This is called at the end of a CDATA section.
=item * XMLDecl (Version, Encoding, Standalone)
This handler is called for XML declarations. Version is a string containing
the version. Encoding is either undefined or contains an encoding string.
Standalone is either undefined, or true or false. Undefined indicates
that no standalone parameter was given in the XML declaration. True or
false indicates "yes" or "no" respectively.
=back
=cut
sub setHandlers {
my ($self, @handler_pairs) = @_;
croak("Uneven number of arguments to setHandlers method")
if (int(@handler_pairs) & 1);
my @ret;
while (@handler_pairs) {
my $type = shift @handler_pairs;
my $handler = shift @handler_pairs;
croak "Handler for $type not a Code ref"
unless (! defined($handler) or ! $handler or ref($handler) eq 'CODE');
lib/Rinchi/Fortran/Preprocessor.pm view on Meta::CPAN
return undef;
}
=item startElementHandler()
Default start Element handler.
=cut
sub startElementHandler() {
my ($tag, $hasChild, %attrs) = @_;
print "<$tag";
foreach my $attr (sort keys %attrs) {
my $val = $attrs{$attr};
$val =~ s/&/&/g;
$val =~ s/</</g;
$val =~ s/>/>/g;
$val =~ s/\"/"/g;
$val =~ s/\'/'/g;
print " $attr=\"$val\"";
}
if ($hasChild == 0) {
print " />";
$closed = 1;
# if($new_line{$tag} & 1) {
# print "\n";
# }
} else {
print ">";
$closed = 0;
# if($new_line{$tag} & 2) {
# print "\n";
# }
}
}
=item endElementHandler()
Default end Element handler.
=cut
sub endElementHandler() {
my ($tag) = @_;
if ($closed == 0) {
print "</$tag>";
} else {
$closed = 0;
}
}
=item characterDataHandler()
Default Character Data handler.
=cut
sub characterDataHandler() {
my ($cdata) = @_;
print $cdata;
}
=item processingInstructionHandler()
Default Processing Instruction handler.
=cut
sub processingInstructionHandler() {
my ($target,$data) = @_;
print "\n<?$target $data?>\n";
}
=item commentHandler()
Default Comment handler.
=cut
sub commentHandler() {
my ($string) = @_;
print "<!-- $string -->\n";
}
=item startCdataHandler()
Default start CDATA handler.
=cut
sub startCdataHandler() {
print "<![CDATA[";
}
=item endCdataHandler()
Default end CDATA handler.
=cut
sub endCdataHandler() {
print "]]>";
}
=item xmlDeclHandler()
Default XML Declaration handler.
=cut
sub xmlDeclHandler() {
my ($version, $encoding, $standalone) = @_;
print "<?xml version=\"$version\" encoding=\"$encoding\" standalone=\"$standalone\"?>\n";
}
=item sub xml_outpute($path, [\@args])
$fpp->xml_output('some_file.fpp' ,\@args);
Where $path is the path to the file to be parsed and $args is an optional
lib/Rinchi/Fortran/Preprocessor.pm view on Meta::CPAN
'XMLDecl' => \&xmlDeclHandler,
);
if (defined($args) and ref($args) eq 'ARRAY') {
$fpp->process_file($path,$args);
} else {
$fpp->process_file($path);
}
}
# source_out handlers
sub _startElementHandler() {
my ($tag, $hasChild, %attrs) = @_;
my $keyword = Rinchi::Fortran::Preprocessor->keyword_for_tag($tag);
if (defined($keyword)) {
print "$keyword";
return;
} elsif ($tag eq 'identifier') {
print $attrs{'identifier'};
return;
} elsif ($tag eq 'white_space') {
print $attrs{'value'};
return;
} elsif ($tag eq 'float_lit') {
print $attrs{'value'};
return;
} elsif ($tag eq 'char_lit') {
print "'$attrs{'value'}'";
return;
} elsif ($tag eq 'comment') {
print '! ';
return;
} else {
my $delim = Rinchi::Fortran::Preprocessor->delimiter_for_open_tag($tag);
if (defined($delim)) {
print "$delim";
return;
} else {
my $op_punc = Rinchi::Fortran::Preprocessor->op_or_punc_for_tag($tag);
if (defined($op_punc)) {
print "$op_punc";
return;
}
}
}
}
sub _endElementHandler() {
my ($tag) = @_;
my $delim = Rinchi::Fortran::Preprocessor->delimiter_for_close_tag($tag);
if (defined($delim)) {
print "$delim";
}
}
sub _characterDataHandler() {
my ($cdata) = @_;
print $cdata;
}
sub _processingInstructionHandler() {
my ($target,$data) = @_;
print "\n";
}
sub _commentHandler() {
my ($string) = @_;
}
sub _startCdataHandler() {
}
sub _endCdataHandler() {
}
sub _xmlDeclHandler() {
my ($version, $encoding, $standalone) = @_;
}
=item sub new_source($path, [\@args])
$fpp->new_source('some_file.fpp' ,\@args);
Where $path is the path to the file to be parsed and $args is an optional
reference to an array of arguments.
Parse the given file after passing the arguments if given. Print the new source
to standard output.
=cut
sub new_source($$) {
my ($self, $path, $args) = @_;
my $fpp = new Rinchi::Fortran::Preprocessor;
$fpp->setHandlers('Start' => \&_startElementHandler,
'End' => \&_endElementHandler,
'Char' => \&_characterDataHandler,
'Proc' => \&_processingInstructionHandler,
'Comment' => \&_commentHandler,
'CdataStart' => \&_startCdataHandler,
'CdataEnd' => \&_endCdataHandler,
'XMLDecl' => \&_xmlDeclHandler,
);
if (defined($args) and ref($args) eq 'ARRAY') {
$fpp->process_file($path,$args);
} else {
$fpp->process_file($path);
}
}
# Preloaded methods go here.
1;
__END__
( run in 0.780 second using v1.01-cache-2.11-cpan-7fcb06a456a )