UNPKG

solidity-antlr4

Version:

Solidity Lang Lexer and Parser by official ANTLR4 grammar

201 lines (159 loc) 6.45 kB
<div align="center"><a name="readme-top"></a> <h1>Solidity ANTLR4</h1> [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 </div> ## Installation ```bash $ npm install solidity-antlr4 ``` > It will be `pnpm/yarn add solidity-antlr4` if you use pnpm or yarn. ## Usage ### Language Parser * `parse(code, [options])`: `parse()` parses the provided code as an entire Solidity source unit. * `options`: * `tolerant`: `boolean`, default is `false`. If `true`, the parser will try to parse as much as possible, even if the input is invalid, and never throw an error. * `selector`: `function`, default is `(p) => p.sourceUnit()`. If provided, the parser will only return the nodes that match the selector. It will be useful when you want to parse a specific node. * `output`: `SyntaxNode`, the root node of the AST. ```js // 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(code, [options])`: `tokenizer()` parses the provided code as tokens. * `options`: * `tolerant`: `boolean`, default is `false`. * `output`: `SyntaxToken[]`. ```js // 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. ```js // 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; }) ``` ```js // 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. ```ts 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](./LICENSE)