General Purpose Preprocessor in Perl

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 ############################################

Leave a comment