Here is a preprocessor in perl, primarily for Verilog, SystemVerilog, but may be used for any language.
There are programs with a lot of repetitive text. Language features like functions, objects can reduce typing.
Still, there is scope for putting it in lesser code using a text preprocessor.
Limitations in existing preprocessors prompted in writing a new one that addresses the issues
C preprocessor:
Every define has to be written in a single line.
Escape chars for special chars can make the macro unreadable
Very limited keywords. No loop operations
m4 preprocessor:
No escape characters
Difficult to write macros consisting special characters
Advantages of the new preprocessor:
Written in perl, no CPAN packages used, very portable
Very small – 50 lines of code; Only 7 keywords;
No escape characters. Can be used for any programming language.
Possible to emulate features of C-preprocessor as well as m4
Hook to insert perl keywords – shown in example at end of script.
More usage examples coming-up in later posts.
#!/usr/bin/perl
###### General Purpose Preprocessor (c) A.G.Raja ########
my @lines;
my $code;
my $t=0;
my $e;
sub tokenize {
my $text = shift;
my @spl = split(/(\$get\s*\(\s*\w+)\s*\)/,$text);
my $out = “”;
my $var = “”;
foreach my $s (@spl) {
if($s =~ /\$get\s*\((.*)/) {
$var = $1;
if($var =~ /^\d+/) {
$out .= “\$_[$var]“;
} else { $out .= “\$$var”;
}
} else {
push(@lines,$s);
$out .= “\$lines[$#lines]“;
}
}
return “\”$out\”";
}
while(<DATA>) {
s/\$dnl.*\n//;
if(!length($_)) {
} elsif(/^\s*\$macro\s+(.*)/) {
$code .= “\nsub $1 {\n my \$ret;\n”;
$t=1;
} elsif(/^\s*\$endmacro\s*$/) {
$code .= “return \$ret;\n}\n”;
$t=0;
} elsif(/^\s*\$begin\s+(.*)/) {
$code .= “$1 {\n”;
} elsif(/^\s*\$end\s*$/) {
$code .= “}\n”;
} elsif(/\$set\s+(\$\w+)\s*=(.*)/) {
$code .= “\n$1 = \”\@{[ $2 ]}\”;\n”;
} else {
$e = &tokenize($_);
if($t==1) {
$code .= ” \$ret .= $e;\n”;
} else {
$code .= “print $e;\n”;
}
}
}
eval $code or die print “\n\n### ERROR: PREPROCESSING FAILED ###\n\n”;
############ TEXT after DATA can be edited ############
__DATA__
$macro func $dnl ### This is Start of Macro Definition
$get(0) $dnl $dnl ### $dnl will Delete-till New-Line
$begin foreach $x (@_) $dnl ### $begin will append { to perl code
argument is $get(x) $dnl ##### Substitute perl variable, here $x
$end $dnl ### $end will append } to perl code
$endmacro $dnl ### This is End of Macro Definition
$set $a = func(1,2,3,4,5) $dnl ### Assign return value of a Macro
aa $begin $dnl ### Spaces before keywords not allowed
gadfdasfdas
$dnl this is a comment. newline+space will be printed here
$get(a)
$dnl ############################################
$dnl #### This Script translates TEXT to perl code and executes it.
$dnl #### Following are Keywords for TEXT to be preprocessed:
$dnl #### $dnl $macro $endmacro $begin $end $set $get
$dnl #### Usage of the keywords are explained in above example.
$dnl #### $begin keyword can be exploited to get the power of perl.
$dnl ############################################
Filed under: Shell, SystemVerilog, Verilog Tagged: m4, Preprocessor, SystemVerilog, Verilog, vpp
