Skip to content

Using the AST#

Let's try to analyze the following Solidity source file, containing a simple function:

input.sol
function add(uint256 a, uint256 b) public pure returns (uint256) {
    return a + b;
}

We start as usual by parsing the input, and then we can use the ParseOutput root to create the CST type. Since it is a node of kind FunctionDefinition, we are using the AST type of the same name to analyze it:

import assert from "node:assert";
import { Parser } from "@nomicfoundation/slang/parser";
import { NonterminalKind } from "@nomicfoundation/slang/cst";
import { FunctionDefinition } from "@nomicfoundation/slang/ast";

const parser = Parser.create("0.8.0");

const parseOutput = parser.parse(NonterminalKind.FunctionDefinition, source);

The FunctionDefinition type has named fields to access all its children. For example, we can check the name of the function:

const $function = new FunctionDefinition(parseOutput.tree.asNonterminalNode()!);

assert.equal($function.name.variant.unparse(), "add");

We can also list its parameters:

const parameters = $function.parameters.parameters.items.map((parameter) => {
  return parameter.name!.unparse();
});

assert.deepEqual(parameters, ["a", "b"]);

Or attributes:

const attributes = $function.attributes.items.map((attribute) => {
  return attribute.cst.unparse().trim();
});

assert.deepEqual(attributes, ["public", "pure"]);