Peter Stuifzand

DIY refactoring

Yesterday I released a piece of code the includes a parser, a rewriter and serializer for a small expression language.

The code is an example how you can parse source code and build a tree, rewrite the tree using two expressions and serialize the tree back to a piece of ‘code’.

The idea that I used here was to improve the language by adding a way to specify structural variables. The variables start with a colon :, but are otherwise like variables.

The actual source code shouldn’t contain these structural variables. You should only use them in the transformation specification. I wrote a function replace(source, from, to) that find and replaces the structure from in source to the structure to. Let’s start with an example.

my $source = <<'SOURCE';
print(power(10, 2));
print(power(10, 3))
SOURCE

print replace($source, 'power(:b, 2)', 'twice(:b)') . "\n";

In this example we replace the power function with the twice function, but only if the exponent equals 2. The power call with exponent 3 is not replaced.

The function replace parses all three arguments $source, $from and $to. It searches for the $from structure using the _expr_match function, which returns the matching structural variables in the third parameter.

To play with this you should git clone the gist and run the test.pl program. Changing the $source, $from and $to allows you to try different things.

© 2023 Peter Stuifzand