├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .gitmodules ├── .npmignore ├── .travis.yml ├── CHANGES.md ├── LICENSE ├── README.md ├── index.d.ts ├── package.json ├── scripts └── antlr4.sh ├── src ├── ASTBuilder.js ├── ErrorListener.js ├── antlr4 │ ├── BufferedTokenStream.js │ ├── CharStreams.js │ ├── CommonTokenFactory.js │ ├── CommonTokenStream.js │ ├── FileStream.js │ ├── InputStream.js │ ├── IntervalSet.js │ ├── LL1Analyzer.js │ ├── Lexer.js │ ├── Parser.js │ ├── ParserRuleContext.js │ ├── PredictionContext.js │ ├── README.md │ ├── Recognizer.js │ ├── RuleContext.js │ ├── Token.js │ ├── Utils.js │ ├── atn │ │ ├── ATN.js │ │ ├── ATNConfig.js │ │ ├── ATNConfigSet.js │ │ ├── ATNDeserializationOptions.js │ │ ├── ATNDeserializer.js │ │ ├── ATNSimulator.js │ │ ├── ATNState.js │ │ ├── ATNType.js │ │ ├── LexerATNSimulator.js │ │ ├── LexerAction.js │ │ ├── LexerActionExecutor.js │ │ ├── ParserATNSimulator.js │ │ ├── PredictionMode.js │ │ ├── SemanticContext.js │ │ ├── Transition.js │ │ └── index.js │ ├── dfa │ │ ├── DFA.js │ │ ├── DFASerializer.js │ │ ├── DFAState.js │ │ └── index.js │ ├── error │ │ ├── DiagnosticErrorListener.js │ │ ├── ErrorListener.js │ │ ├── ErrorStrategy.js │ │ ├── Errors.js │ │ └── index.js │ ├── index.js │ ├── package.json │ ├── polyfills │ │ ├── codepointat.js │ │ └── fromcodepoint.js │ └── tree │ │ ├── Tree.js │ │ ├── Trees.js │ │ └── index.js ├── index.js ├── lib │ ├── Solidity.interp │ ├── Solidity.tokens │ ├── SolidityLexer.interp │ ├── SolidityLexer.js │ ├── SolidityLexer.tokens │ ├── SolidityListener.js │ └── SolidityParser.js └── tokens.js ├── test ├── ast.js ├── index.js ├── test.sol └── utils.js ├── tslint.json └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["env"], 3 | "plugins": [ 4 | ["babel-plugin-inline-import", { 5 | "extensions": [".tokens"] 6 | }] 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | trim_trailing_whitespace = true 8 | 9 | [*.js] 10 | indent_style = space 11 | indent_size = 2 12 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | src/lib 2 | src/antlr4 3 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["eslint:recommended"], 3 | "plugins": [ 4 | "promise" 5 | ], 6 | "rules": { 7 | "no-var": 2, 8 | "object-curly-spacing": [2, "always"], 9 | "object-shorthand": 2, 10 | "prefer-const": 2, 11 | "max-len": 2 12 | }, 13 | "parserOptions": { 14 | "ecmaVersion": 2017, 15 | "sourceType": "module" 16 | }, 17 | "env": { 18 | "es6": true, 19 | "mocha": true, 20 | "node": true 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .nyc_output/ 3 | dist/ 4 | .vscode/settings.json 5 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "solidity-antlr4"] 2 | path = solidity-antlr4 3 | url = https://github.com/consensys/solidity-antlr4 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | test/ 3 | scripts/ 4 | .nyc_output/ 5 | .travis.yml 6 | .gitmodules 7 | .eslintrc 8 | .editorconfig 9 | solidity-antlr4/ 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "8" 4 | -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | ### 0.5.0 (Unreleased) 2 | 3 | * Remove `ParameterList` and `Parameter` node types. Parameters are now always 4 | of type `VariableDeclaration` and lists of parameters are represented as 5 | lists of nodes of type `VariableDeclaration`. This is a breaking change. 6 | 7 | ### 0.4.12 (Unreleased) 8 | 9 | * Fix type name expressions to also support user-defined type names. 10 | 11 | ### 0.4.11 12 | 13 | * Bugfix release 14 | 15 | ### 0.4.9 16 | 17 | * Fix parsing of inheritance specifier with no arguments. 18 | 19 | ### 0.4.8 20 | 21 | * Fix parsing of string literals with escaped characters. 22 | 23 | ### 0.4.7 24 | 25 | * Fix parsing of underscores in number literals. 26 | 27 | ### 0.4.6 28 | 29 | * Add support for the `type` keyword. 30 | * Add support for underscores in number literals. 31 | 32 | ### 0.4.5 33 | 34 | * Improve TypeScript type definitions. 35 | 36 | ### 0.4.4 37 | 38 | * Add missing `storageLocation` to variables in VariableDeclarationStatement. 39 | * Return `null` for `arguments` instead of `[]` when `ModifierInvocation` 40 | contains no arguments and no parentheses to distinguish the two cases. 41 | * Improve TypeScript type definitions. 42 | 43 | ### 0.4.3 44 | 45 | * Improve TypeScript type definitions, thanks @Leeleo3x and @yxliang01. 46 | 47 | ### 0.4.2 48 | 49 | * Fix parsing of assembly function definitions with no args or return args. 50 | 51 | ### 0.4.1 52 | 53 | * Fix parsing of for loops with missing initial and condition statements. 54 | 55 | ### 0.4.0 56 | 57 | * Correctly handle non-existent tuple components. Thanks @maxsam4 58 | * Accept calldata as identifier 59 | 60 | ### 0.3.3 61 | 62 | * Add support for `address payable` typename. 63 | 64 | ### 0.3.2 65 | 66 | * Fix parsing of hex numbers with uppercase X. 67 | 68 | ### 0.3.1 69 | 70 | * Fix parsing of zero-component tuples. 71 | 72 | ### 0.3.0 73 | 74 | * Use `components` for all `TupleExpression` nodes. Earlier versions 75 | incorrectly stored tuple components under the `elements` key. 76 | * Fix parsing of decimal literals without integer part. 77 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-2018 Federico Bond 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [get in touch with Consensys Diligence](https://diligence.consensys.net)
2 | 3 | [[ 🌐 ](https://diligence.consensys.net/?utm_source=github_npm&utm_medium=banner&utm_campaign=solidity-parser-diligence) [ 📩 ](mailto:diligence@consensys.net) [ 🔥 ](https://consensys.github.io/diligence/)] 4 |

5 | 6 | 7 | solidity-parser-diligence 8 | ===================== 9 | 10 | A Solidity parser built on top of a robust [ANTLR4 grammar](https://github.com/consensys/solidity-antlr4). 11 | 12 | Now maintained by the ConsenSys Diligence team! :tada: 13 | 14 | You can find this new package in NPM at `solidity-parser-diligence` (https://www.npmjs.com/package/solidity-parser-diligence). 15 | 16 | ### Usage 17 | 18 | ```javascript 19 | import parser from 'solidity-parser-diligence'; 20 | 21 | var input = ` 22 | contract test { 23 | uint256 a; 24 | function f() {} 25 | } 26 | ` 27 | try { 28 | parser.parse(input) 29 | } catch (e) { 30 | if (e instanceof parser.ParserError) { 31 | console.log(e.errors) 32 | } 33 | } 34 | ``` 35 | 36 | The `parse` method also accepts a second argument which lets you specify the 37 | following options, in a style similar to the _esprima_ API: 38 | 39 | | Key | Type | Default | Description | 40 | |----------|---------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 41 | | tolerant | Boolean | false | When set to `true` it will collect syntax errors and place them in a list under the key `errors` inside the root node of the returned AST. Otherwise, it will raise a `parser.ParserError`. | 42 | | loc | Boolean | false | When set to `true`, it will add location information to each node, with start and stop keys that contain the corresponding line and column numbers. Column numbers start from 0, lines start from 1. | 43 | | range | Boolean | false | When set to `true`, it will add range information to each node, which consists of a two-element array with start and stop character indexes in the input. | 44 | 45 | 46 | #### Example with location information 47 | 48 | ```javascript 49 | parser.parse('contract test { uint a; }', { loc: true }) 50 | 51 | // { type: 'SourceUnit', 52 | // children: 53 | // [ { type: 'ContractDefinition', 54 | // name: 'test', 55 | // baseContracts: [], 56 | // subNodes: [Array], 57 | // kind: 'contract', 58 | // loc: [Object] } ], 59 | // loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 24 } } } 60 | 61 | ``` 62 | 63 | #### Example using a visitor to walk over the AST 64 | 65 | ```javascript 66 | var ast = parser.parse('contract test { uint a; }') 67 | 68 | // output the path of each import found 69 | parser.visit(ast, { 70 | ImportDirective: function(node) { 71 | console.log(node.path) 72 | } 73 | }) 74 | ``` 75 | 76 | ### Authors 77 | 78 | Gonçalo Sá ([@gnsps](https://twitter.com/gnsps)) 79 | 80 | Federico Bond ([@federicobond](https://github.com/federicobond)) 81 | 82 | ### License 83 | 84 | MIT 85 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "solidity-parser-diligence", 3 | "version": "0.4.18", 4 | "description": "A Solidity parser built from a robust ANTLR 4 grammar", 5 | "main": "dist/index.js", 6 | "types": "./index.d.ts", 7 | "scripts": { 8 | "antlr4": "sh scripts/antlr4.sh", 9 | "build": "rm -rf dist && babel --out-dir=dist src --copy-files", 10 | "prepare": "yarn build", 11 | "prettier": "find src -name *.js | egrep -v '^src/(lib|antlr4)/' | xargs prettier --no-semi --single-quote --write", 12 | "eslint": "eslint src", 13 | "pretest": "eslint src && tslint-config-prettier-check ./tslint.json", 14 | "test": "nyc mocha --require babel-register", 15 | "tslint": "tslint-config-prettier-check ./tslint.json" 16 | }, 17 | "author": [ 18 | "Gonçalo Sá ", 19 | "Federico Bond " 20 | ], 21 | "homepage": "https://github.com/consensys/solidity-parser-antlr", 22 | "repository": { 23 | "type": "git", 24 | "url": "https://github.com/consensys/solidity-parser-antlr.git" 25 | }, 26 | "license": "MIT", 27 | "devDependencies": { 28 | "babel-cli": "^6.26.0", 29 | "babel-plugin-inline-import": "^3.0.0", 30 | "babel-preset-env": "^1.7.0", 31 | "chai": "^4.2.0", 32 | "eslint": "^6.2.2", 33 | "eslint-plugin-import": "^2.18.2", 34 | "eslint-plugin-node": "^9.2.0", 35 | "eslint-plugin-promise": "^4.2.1", 36 | "eslint-plugin-standard": "^4.0.1", 37 | "mocha": "^6.2.0", 38 | "nyc": "^14.1.1", 39 | "prettier": "^1.18.2", 40 | "tslint": "5.19.0", 41 | "tslint-config-prettier": "^1.18.0", 42 | "typescript": "3.6.2", 43 | "yarn": "^1.17.3" 44 | }, 45 | "nyc": { 46 | "include": [ 47 | "src/*.js" 48 | ] 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /scripts/antlr4.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | set -o errexit 4 | 5 | ANTLR_JAR="solidity-antlr4/antlr4.jar" 6 | 7 | if [ ! -e "$ANTLR_JAR" ]; then 8 | curl https://www.antlr.org/download/antlr-4.7.2-complete.jar -o "$ANTLR_JAR" 9 | fi 10 | 11 | java -jar $ANTLR_JAR -Dlanguage=JavaScript solidity-antlr4/Solidity.g4 -o lib 12 | 13 | mv lib/solidity-antlr4/* src/lib/ 14 | 15 | rmdir lib/solidity-antlr4 16 | 17 | sed -i.bak -e 's/antlr4\/index/\.\.\/antlr4\/index/g' src/lib/*.js 18 | 19 | find src/lib -name '*.js.bak' -delete 20 | -------------------------------------------------------------------------------- /src/ErrorListener.js: -------------------------------------------------------------------------------- 1 | const antlr4 = require('./antlr4/index') 2 | 3 | function ErrorListener() { 4 | antlr4.error.ErrorListener.call(this) 5 | this._errors = [] 6 | } 7 | 8 | ErrorListener.prototype = Object.create(antlr4.error.ErrorListener.prototype) 9 | ErrorListener.prototype.constructor = ErrorListener 10 | 11 | ErrorListener.prototype.syntaxError = function( 12 | recognizer, 13 | offendingSymbol, 14 | line, 15 | column, 16 | message 17 | ) { 18 | this._errors.push({ message, line, column }) 19 | } 20 | 21 | ErrorListener.prototype.getErrors = function() { 22 | return this._errors 23 | } 24 | 25 | ErrorListener.prototype.hasErrors = function() { 26 | return this._errors.length > 0 27 | } 28 | 29 | module.exports = ErrorListener 30 | -------------------------------------------------------------------------------- /src/antlr4/BufferedTokenStream.js: -------------------------------------------------------------------------------- 1 | // 2 | /* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. 3 | * Use of this file is governed by the BSD 3-clause license that 4 | * can be found in the LICENSE.txt file in the project root. 5 | */ 6 | 7 | // This implementation of {@link TokenStream} loads tokens from a 8 | // {@link TokenSource} on-demand, and places the tokens in a buffer to provide 9 | // access to any previous token by index. 10 | // 11 | //

12 | // This token stream ignores the value of {@link Token//getChannel}. If your 13 | // parser requires the token stream filter tokens to only those on a particular 14 | // channel, such as {@link Token//DEFAULT_CHANNEL} or 15 | // {@link Token//HIDDEN_CHANNEL}, use a filtering token stream such a 16 | // {@link CommonTokenStream}.

17 | 18 | var Token = require('./Token').Token; 19 | var Lexer = require('./Lexer').Lexer; 20 | var Interval = require('./IntervalSet').Interval; 21 | 22 | // this is just to keep meaningful parameter types to Parser 23 | function TokenStream() { 24 | return this; 25 | } 26 | 27 | function BufferedTokenStream(tokenSource) { 28 | 29 | TokenStream.call(this); 30 | // The {@link TokenSource} from which tokens for this stream are fetched. 31 | this.tokenSource = tokenSource; 32 | 33 | // A collection of all tokens fetched from the token source. The list is 34 | // considered a complete view of the input once {@link //fetchedEOF} is set 35 | // to {@code true}. 36 | this.tokens = []; 37 | 38 | // The index into {@link //tokens} of the current token (next token to 39 | // {@link //consume}). {@link //tokens}{@code [}{@link //p}{@code ]} should 40 | // be 41 | // {@link //LT LT(1)}. 42 | // 43 | //

This field is set to -1 when the stream is first constructed or when 44 | // {@link //setTokenSource} is called, indicating that the first token has 45 | // not yet been fetched from the token source. For additional information, 46 | // see the documentation of {@link IntStream} for a description of 47 | // Initializing Methods.

48 | this.index = -1; 49 | 50 | // Indicates whether the {@link Token//EOF} token has been fetched from 51 | // {@link //tokenSource} and added to {@link //tokens}. This field improves 52 | // performance for the following cases: 53 | // 54 | //