NAME
POE::Preprocessor - a macro/const/enum preprocessor
SYNOPSIS
use POE::Preprocessor;
macro max (one,two) {
((one) > (two) ? (one) : (two))
}
print {% max $one, $two %}, "\n";
const PI 3.14159265359
print "PI\n"; # Substitutions don't grok Perl!
enum ZERO ONE TWO
enum 12 TWELVE THIRTEEN FOURTEEN
enum + FIFTEEN SIXTEEN SEVENTEEN
print "ZERO ONE TWO TWELVE THIRTEEN FOURTEEN FIFTEEN SIXTEEN SEVENTEEN\n";
if ($expression) { # include
... lines of code ...
} # include
unless ($expression) { # include
... lines of code ...
} elsif ($expression) { # include
... lines of code ...
} else { # include
... lines of code ...
} # include
DESCRIPTION
POE::Preprocessor is a Perl source filter that implements a simple macro substitution language. Think of it like compile-time code templates.
Macros
Macros are defined with the macro
statement. The syntax is similar to Perl subs:
macro macro_name (parameter_0, parameter_1) {
macro code ... parameter_0 ... parameter_1 ...
}
The open brace is required to be on the same line as the macro
statement. The Preprocessor doesn't analyze macro bodies. Instead, it assumes that any closing brace in the leftmost column ends an open macro.
The parameter list is optional for macros that don't accept parameters.
macro macro_name {
macro code;
}
Macros are substituted into a program with a syntax borrowed from Iaijutsu and altered slightly to jive with Perl's native syntax.
{% macro_name $param_1, 'param two' %}
This is the code the first macro would generate:
macro code ... $param_1 ... 'param two' ...
It's very simplistic. See POE::Kernel for extensive macro use.
Constants and Enumerations
The const
command defines a constant.
const CONSTANT_NAME 'constant value'
const ANOTHER_CONSTANT 23
Enumerations are defined with the emun
command. Enumerations start from zero by default:
enum ZEROTH FIRST SECOND ...
If the first parameter of an enumeration is a number, then the enumerated constants will start with that value:
enum 10 TENTH ELEVENTH TWELFTH
enum
statements may not span lines. If the first enumeration parameter is a plus sign, the constants will start where a previous enum
left off.
enum 13 THIRTEENTH FOURTEENTH FIFTEENTH
enum + SIXTEENTH SEVENTEENTH EIGHTEENTH
Conditional Code Inclusion (#ifdef)
The preprocessor supports something like cpp's #if/#else/#endif by usurping a bit of Perl's conditional syntax. The following conditional statements will be evaluated at compile time if they are followed by the comment # include
:
if (EXPRESSION) { # include
BLOCK;
} elsif (EXPRESSION) { # include
BLOCK;
} else { # include
BLOCK;
} # include
unless (EXPRESSION) { # include
BLOCK;
} # include
The code in each conditional statement's BLOCK will be included or excluded in the compiled code depending on the outcome of its EXPRESSION.
Conditional includes are nestable, but else and elsif must be on the same line as the previous block's closing brace, as they are in the previous example.
Conditional includes are experimental pending a decision on how useful they are.
DEBUGGING
POE::Preprocessor has three debugging constants which may be defined before the first time POE::Preprocessor is used.
To trace source filtering in general, and to see the resulting code and operations performed on each line:
sub POE::Preprocessor::DEBUG () { 1 }
To trace macro invocations as they happen:
sub POE::Preprocessor::DEBUG_INVOKE () { 1 }
To see macro, constant, and enum definitions:
sub POE::Preprocessor::DEBUG_DEFINE () { 1 }
BUGS
Source filters are line-based, and so is the macro language. The only constructs that may span lines are macro definitions, and those *must* span lines.
The regular expressions that detect and replace code are simplistic and may not do the right things when given challenging Perl syntax to parse. For example, constants are replaced within strings.
Substitution is done in two phases: macros first, then constants. It would be nicer (and more dangerous) if the phases looped around and around until no more substitutions occurred.
The regexp builder makes silly subexpressions like /(?:|m)/. That could be done better as /m?/ or /(?:jklm)?/ if the literal is longer than a single character.
SEE ALSO
The regexp optimizer is based on code in Ilya Zakharevich's Text::Trie.
AUTHOR & COPYRIGHT
POE::Preprocessor is Copyright 2000 Rocco Caputo. All rights reserved. POE::Preprocessor is free software; you may redistribute it and/or modify it under the same terms as Perl itself.