CodeTree
CodeTree is an ES6 library (written in TypeScript) that helps transform code easily.
Transforming TypeScript or JavaScript code
; // This is the JavaScript (or TypeScript) code we want to transform.let code = ` function sayHelloWorld() { console.log("Hello, World!"); }`; // Convert the source code to a parse tree.let tree = codeTreetypescript; // Create a mutated tree.let mutatedTree = codeTree; // Convert the mutated tree back into source code.// Your comments and formatting will not be lost. Yay!console;
Give it a try yourself here: https://runkit.com/fwouts/using-codetree-to-mutate-javascript
Transforming any other language
Any language that can be parsed with ANTLR4 can be transformed with CodeTree. That is, virtually any language since open-source contributors have been kind enough to provide an extensive library of grammars in the grammars-v4 repo.
Creating the parser and lexer
After downloading the ANTLR grammar for your language (one combined or two parser + lexer files ending with the .g4
extension), you'll need to generate the TypeScript lexer and parser before you can use CodeTree.
Here is an example using the Java grammar:
$ npm install -g antlr4ts-cli$ antlr4ts -no-listener -no-visitor *.g4Generating file '/Users/work/GitHub/abc/./JavaLexer.ts'
This will generate two new files: JavaLexer.ts
and JavaParser.ts
. You can ignore the .token
files and even delete them. They're not necessary.
If you work with JavaScript and not TypeScript, convert these files to ES6 using:
$ npm install -g typescript$ npm install antlr4ts$ tsc *.ts --target es6 --experimentalDecorators --moduleResolution node$ mv *.js path/to/src/
Using the parser and lexer
Now, all you need to do is:
; ;; // This is the Java code we want to transform.let code = ` package example; public class Example { public static void main() { System.out.println("Hello, World!"); } }`; // Convert the source code to a parse tree.let tree = codeTreeantlr;// Just making sure we got a tree and not a terminal node.if !tree instanceof codeTreenodesTree throw ; // Create the mutated tree.let mutatedTree = codeTree; // Convert the mutated tree back into source code.console;