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 { Language } from "@nomicfoundation/slang/language";
import { NonterminalKind } from "@nomicfoundation/slang/kinds";
import { NonterminalNode } from "@nomicfoundation/slang/cst";
import { FunctionDefinition } from "@nomicfoundation/slang/ast";

const language = new Language("0.8.0");

const parseOutput = language.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() as NonterminalNode);

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

We can also list its parameters:

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

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

Or attributes:

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

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