Abstract Syntax Trees in JavaScript
Photo by Joan Gamell on Unsplash
An Abstract Syntax Tree (AST), is a powerful concept in computer science. It is something that allows you to do some interesting things, especially in JavaScript, that you may not have thought possible. If you didn't come from a computer science background, then I hope to show you how you might be using this concept today (and not even know it), and how you might be able to use ASTs to your advantage in doing even more interesting things.
From Wikipedia,
Abstract syntax trees are data structures widely used in compilers, due to their property of representing the structure of program code. An AST is usually the result of the syntax analysis phase of a compiler. It often serves as an intermediate representation of the program through several stages that the compiler requires, and has a strong impact on the final output of the compiler.
- (via Abstract_syntax_tree)
Linting in JavaScript
The most common way you're using ASTs is Linting. Linting in Javascript is the process of running your code through a tool, that knows about the syntax of the language you're using, and can notify, or sometimes even automatically fix errors in the code that you've written. This is a type of static analysis, that can catch outright errors in syntax, to depending on what tool you use, enforce style guidelines on your team. Often it's done somewhere in a Frontend Engineer's process, either from the code editor, from the commandline, or in your build process. The amount of things that a linter can catch for you, is awesome. For example take a look at the possible rules you can have ESLint check for you http://eslint.org/docs/rules/.
Today, if you use any kind of linting program on your JavaScript code, which I hope you do, then you're using ASTs. Linters like JSLint, JSHint, eslint use an Abstract Tree Parser. But what else does having the AST of your code file provide?
Code Transformation
If you have the AST, of the code you're working on, then you can do other things besides linting. You can do transformation! (Another way you might be using ASTs and not know it, is minification - see UglifyJS).
Regenerating the code from the syntax tree permits interesting options to those who want to take advantage of it. Let's take a look at a great example that I came across in a JSConf EU 2013 talk about Parsing, Compiling, and Static Metaprogramming by Patrick Dubroy:
With this example, using Esprima, you can insert console.log statments for every function - allowing to more easily debug your program. With this approach you didn't have to manually type console.log() in every function, it is doing that for you automatically, by parsing the AST, then finding functions in that tree, and inserting console log functions, via transformation.
This is a pretty simple example, but it shows the power of Abstract Syntax Trees in JavaScript. Play more with Esprima's AST parser in this online tool:
http://jointjs.com/demos/javascript-ast
More Possibilities with AST
Knowing about what an AST is, and how you can use it in JavaScript is a powerful concept. You could not only do simple things like inserting logging statements in your codebase automatically. What if you needed to migrate your codebase in some way? And in an automated, and controlled fashion. AST opens these kinds of doors, and that's pretty cool.
Another similar article that got me interested in writing about it was Etsy's blog post, Transitioning to SCSS at Scale. Using ReworkCSS, that converts their CSS into an AST, they were able to migrate to using SCSS. Pretty amazing considering it was 400,000+ lines of CSS split over 2000+ files. It took a lot of work for them to change their build workflow to enable this, including diffing the old CSS with the new SCSS using ASTs, but it wouldn't be possible at scale without ASTs.