jeasonstudio / solidity-antlr4

✨ Solidity Language Lexer and Parser, generated by official ANTLR4 grammar.
https://solidity-antlr4.vercel.app/
MIT License
18 stars 1 forks source link
antlr4-grammar ast parser solidity

Solidity ANTLR4

[Solidity](https://soliditylang.org/) Language Lexer and Parser, generated by official ANTLR4 grammar. [![NPM version][npm-image]][npm-url] [![NPM downloads][download-image]][download-url] [![CI status][github-action-image]][github-action-url] [![codecov][codecov-image]][codecov-url] [![MIT License][license-shield]][license-url] [![Contributors][contributors-shield]][contributors-url] [![Issues][issues-shield]][issues-url] [![Stargazers][stars-shield]][stars-url] [![Follow Twitter][twitter-image]][twitter-url] [Change Log](./CHANGELOG.md) · [Report Bug](https://github.com/jeasonstudio/solidity-antlr4/issues/new) · [Pull Request](https://github.com/jeasonstudio/solidity-antlr4/compare) ![](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png) [npm-image]: https://img.shields.io/npm/v/solidity-antlr4?style=for-the-badge [npm-url]: http://npmjs.org/package/solidity-antlr4 [download-image]: https://img.shields.io/npm/dm/solidity-antlr4.svg?style=for-the-badge [download-url]: https://npmjs.org/package/solidity-antlr4 [github-action-image]: https://img.shields.io/github/actions/workflow/status/jeasonstudio/solidity-antlr4/test.yml?style=for-the-badge [github-action-url]: https://github.com/jeasonstudio/solidity-antlr4/actions?query=workflow=%22test%22 [codecov-image]: https://img.shields.io/codecov/c/github/jeasonstudio/solidity-antlr4/master.svg?style=for-the-badge [codecov-url]: https://codecov.io/gh/jeasonstudio/solidity-antlr4/branch/master [license-shield]: https://img.shields.io/github/license/jeasonstudio/solidity-antlr4.svg?style=for-the-badge [license-url]: https://github.com/jeasonstudio/solidity-antlr4/blob/master/LICENSE [contributors-shield]: https://img.shields.io/github/contributors/jeasonstudio/solidity-antlr4.svg?style=for-the-badge [contributors-url]: https://github.com/jeasonstudio/solidity-antlr4/graphs/contributors [stars-shield]: https://img.shields.io/github/stars/jeasonstudio/solidity-antlr4.svg?style=for-the-badge [stars-url]: https://github.com/jeasonstudio/solidity-antlr4/stargazers [issues-shield]: https://img.shields.io/github/issues/jeasonstudio/solidity-antlr4.svg?style=for-the-badge [issues-url]: https://github.com/jeasonstudio/solidity-antlr4/issues [twitter-image]: https://img.shields.io/twitter/follow/jeasonstudio?style=for-the-badge&logo=x [twitter-url]: https://twitter.com/jeasonstudio

Installation

$ npm install solidity-antlr4

It will be pnpm/yarn add solidity-antlr4 if you use pnpm or yarn.

Usage

Language Parser

// parse.mjs
import { parse } from 'solidity-antlr4';

const code = `// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract HelloWorld {
  string public greet = "Hello World!";
}
`;

const ast = parse(code, { tolerant: true, selector: (p) => p.sourceUnit() });
// SourceUnit {
//   type: 'SourceUnit',
//   src: '32:88',
//   range: [ 32, 120 ],
//   location: Location {
//     start: Position { line: 2, column: 0 },
//     end: Position { line: 6, column: 0 }
//   },
//   context: SourceUnitContext {...},
//   nodes: [
//     PragmaDirective {
//       type: 'PragmaDirective',
//       literals: [Array]
//     },
//     ContractDefinition {
//       type: 'ContractDefinition',
//       name: [Identifier],
//       contractKind: 'contract',
//       abstract: false,
//       baseContracts: [],
//       nodes: [Array]
//     }
//   ]
// }

Tokenizer

// tokenizer.mjs
import { tokenizer } from 'solidity-antlr4';

const tokens = tokenizer(code, { tolerant: true });
// [
//   {
//     type: 'SourceUnit',
//     src: '32:88',
//     range: [ 32, 120 ],
//     location: Location {
//       start: Position { line: 2, column: 0 },
//       end: Position { line: 6, column: 0 }
//     }
//   },
//   ...
// ]

Traverse AST

We can use it alongside the parser to traverse nodes.

// visit.mjs
import { parse, visit, serialize } from 'solidity-antlr4';

const ast = parse(code);

// Use `visit` to traverse ast by enter/exit node type.
visit(ast, {
  enter: ({ node, parent }) => {
    console.log(node.type, parent?.type); // print node type
  },
  exit: () => {}, // will call when exit node
  Identifier: ({ node: identifierNode }) => {
    console.log(identifierNode.name); // print identifier name
  },
  exitContractDefinition: ({ node: contractDefinitionNode }) => {
    // will call when exit ContractDefinition node
  }
});

// Use `serialize` to modify ast.
const newAST = serialize(ast, ({ node }) => {
  // do something
  if (node.type === 'Identifier') {
    return node.name;
  }
  return node;
})
// traverse.mjs
import { parse, traverse } from 'solidity-antlr4';

const ast = parse(code);

const newAST = traverse(ast, (path) => {
  // path.path => `SourceUnit.ContractDefinition.FunctionDefinition` ...
  // path.node => current node
  // path.parentPath => parent node path
  // path.depth => current node depth
  // path.stop(); => stop traverse
  // path.rewrite({...}); => rewrite current node
  // path.matches({ type: 'xxx' }); => check if current node matches the given filter
  // return () => {}; => will call when exit node
});

Low-level API

Not recommended, but you can use it if you want.

import { SolidityLexer, SolidityParser, CharStreams, CommonTokenStream } from 'solidity-antlr4';

const code = `...`; // code here

const input = CharStreams.fromString(code);
const lexer = new SolidityLexer(input);
const tokens = new CommonTokenStream(lexer);
const parser = new SolidityParser(tokens);

const parseTree = parser.sourceUnit();

// do something with parseTree

License

MIT