A while ago, I had to implement some Abstract Syntax Tree (AST) manipulation as part of some PowerShell module. Although I was familiar with AST from my university days, this was the first time I got the chance to do something with the AST in PowerShell. So, I told myself: why not blog about what you are learning? :).
Primer on AST #
Before diving into how to leverage the AST in PowerShell, let's cover some of its basic concepts.
What is an AST? #
An Abstract Syntax Tree is a data structure that represents source code written in a programming language. Nodes in the AST represent different contructs available in the language and present in the source code under parsing. The most usual application of AST is being usually the result of the syntax analysis phase done by a compiler as part of the compilation process of a given program.
Basic AST generated for expression
(5 + 3) * (10 / 2)
Advantages of ASTs #
An AST has multiple advantages that can facilitate different use cases:
- Can be edited and enhanced without affecting the original source code
- It can contain extra information about each contructs, such as position in the source code.
AST in PowerShell #
The AST classes in PowerShell are located under the namespace System.Management.Automation.Language. The main objects to start interacting with the AST are:
- Parser class: The methods on this class parse PowerShell scripts and returns a ScriptBlockAst, tokens, and error messages if the script cannot be parsed successfullly. It can either parse PowerShell code from a file or using a string as input.
- ScriptBlockAst class: It is the root ast node for a PowerShell script.
- Ast class: Base class for all ast node definitions. Contains common methods such as
AST manipulation examples #
Properties and methods #
An AST object provides a wealth of information to interact with. Common properties to be used are:
- Extent: Contains the extent in the source that this particular AST node represents. From this object, we can extract information such as the filename, start and end line and column positions.
- Parent: Returns the parent AST node (if any) for the current node.
Common methods are:
- Find: Its purpose is to find the first node in the tree for which the predicate returns true.
- FindAll: Its purpose is to find all nodes in the tree for which the predicate returns true.
- Visit: Allows to visit each node (or a subset) in the tree.
Accessing the AST #
There are 2 main ways of accessing an AST in PowerShell. The first one is using the Ast property of a
ScriptBlock instance and the second one is by calling the ParseFile or ParseInput methods of the
Parser class. This can be achieved as as shown below.
> $code = Get-Content -Path U:\script.ps1 -Raw > $block = [scriptblock]::Create($code) > $block.Ast # Provides access to Ast methods and properties
# Using ParseInput method > $code = Get-Content -Path U:\script.ps1 -Raw > $ast = [System.Management.Automation.Language.Parser]::ParseInput($code, [ref]$null, [ref]$null)
# Using ParseFile method > $filePath = U:\script.ps1 -Raw > $ast = [System.Management.Automation.Language.Parser]::ParseFile($filePath, [ref]$null, [ref]$null)
PSScriptAnalyzer is probably the best example of AST's applications in PowerShell. The module's purpose is to act as a static code checker by running a configurable set of rules. The implementation of the rules leverages the AST of the source code under check to validate their conditions without any need for executing the given code. Everything is resolved by just analyzing the structure and component parts of the code in question.
Other resources #
Looking to go deeper on your understanding of AST in PowerShell. Great! Below is a small list of links that can help you improve your abilities with ASTs in PowerShell:
- Learning about the PowerShell abstract syntax tree ast (series) by Mike F. Robbins
- Learn How IT Pros Can Use the PowerShell AST by Bartek Bielawski
- How to Use PowerShell's Abstract Syntax Tree to Your Advantage by Adam Bertram
In this post, we first did a walkthrough over what an AST is and some of its advantages. Then we mentioned the AST namespace provided by PowerShell and its corresponding classes and how AST properties and method can be accessed in different ways. We briefly described PSScriptAnalyzer, the source code checker for PowerShell and finally we closed with a list of posts and docs that can help you dive deeper on the AST in PowerShell.
To conclude, thanks you so much for reading this post. Hope you liked reading it as much as I did writing it. See you soon and stay tuned for more!!