Constant tree_sitter_solidity::GRAMMAR[][src]

pub const GRAMMAR: &'static str = "// Precedence is used by the parser to determine which rule to apply when there are two rules that can be applied.\n// We use the PREC dict to globally define rule pprecidence\nconst PREC = {\n    COMMENT: 1,\n    STRING: 2,\n    \n    COMMA: -1,\n    OBJECT: -1,\n    USER_TYPE: 1,\n    DECLARATION: 1,\n    ASSIGN: 0,\n    TERNARY: 1,\n    OR: 2,\n    AND: 3,\n    REL: 4,\n    PLUS: 5,\n    TIMES: 6,\n    EXP: 7,\n    TYPEOF: 8,\n    DELETE: 8,\n    VOID: 8,\n    NOT: 9,\n    NEG: 10,\n    INC: 11,\n    CALL: 12,\n    NEW: 13,\n    MEMBER: 14 \n}\n\n// The following is the core grammar for Solidity. It accepts Solidity smart contracts between the versions 0.4.x and 0.7.x.\nmodule.exports = grammar({\n    name: \'solidity\',\n\n    // Extras is an array of tokens that is allowed anywhere in the document.\n    extras: $ => [\n        // Allow comments to be placed anywhere in the file\n        $.comment,\n        // Allow characters such as whitespaces to be placed anywhere in the file\n        /[\\s\\uFEFF\\u2060\\u200B\\u00A0]/\n    ],\n    \n    // The word token allows tree-sitter to appropriately handle scenario\'s where an identifier includes a keyword.\n    // Documentation: https://tree-sitter.github.io/tree-sitter/creating-parsers#keywords\n    word: $ => $.identifier,\n\n    conflicts: $ => [\n        [$._primary_expression, $.type_name],\n        [$._parameter_list, $.fallback_receive_definition],\n        [$._primary_expression, $.type_cast_expression],\n        [$._yul_expression, $.yul_path],\n        [$._yul_expression, $.yul_assignment],\n    ],\n\n    rules: {\n        //  -- [ Program ] --  \n        source_file: $ => seq(\n            repeat($._source_unit),\n        ),\n\n        //  -- [ Source Element ] --  \n        _source_unit: $ =>  choice(\n            $._directive,\n            $._declaration,\n        ),\n\n        //  -- [ Directives ] --  \n        _directive: $ => choice(\n            $.pragma_directive,\n            $.import_directive,\n        ),\n\n        // Pragma\n        pragma_directive: $ => seq(\n            \"pragma\",\n            \"solidity\",\n            repeat(field(\"version_constraint\", $._pragma_version_constraint)),\n            $._semicolon,\n        ),\n\n        _pragma_version_constraint: $ => seq(\n            optional($._solidity_version_comparison_operator),\n            $._solidity_version,\n        ),\n        _solidity_version: $ => /\\d+(.\\d+(.\\d+)?)?/,\n        _solidity_version_comparison_operator: $ => choice(\"<=\", \"<\", \"^\", \">\", \">=\", \"~\", \"=\"),\n\n        // Import\n        import_directive: $ => seq(\n            \'import\',\n            choice(\n                $._source_import,\n                seq($._import_clause, $._from_clause)\n            ),\n            $._semicolon,\n        ),\n\n        _source_import: $ => seq(\n            field(\'source\', $.string),\n            optional(seq(\"as\", $.identifier))\n        ),\n\n        _import_clause: $ => choice(\n            $._single_import,\n            $._multiple_import,\n        ),\n\n        _from_clause: $ => seq(\n            \"from\", field(\'source\', $.string)\n        ),\n    \n        _single_import: $ => seq(\n            \"*\",\n            optional(\n                seq(\n                    \"as\",\n                    field(\"import_alias\", $.identifier)\n                )\n            )\n        ),\n    \n        _multiple_import: $ => seq(\n            \'{\',\n            commaSep($._import_declaration),\n            \'}\'\n        ),\n\n        _import_declaration: $  => seq(\n            field(\"import_origin\", $.identifier),\n            optional(\n                seq(\n                    \"as\",\n                    field(\"import_alias\", $.identifier)\n                )\n            )\n        ),\n\n        //  -- [ Declarations ] --  \n        _declaration: $ => choice(\n            $.contract_declaration,\n            $.interface_declaration,\n            $.library_declaration,\n            $.struct_declaration,\n            $.enum_declaration,\n            $.function_definition,\n            $.constant_variable_declaration,\n        ),\n\n        constant_variable_declaration: $ => seq(\n            field(\"type\", $.type_name),\n            $.constant,\n            field(\"name\", $.identifier),\n            \'=\', \n            field(\"value\", $._expression),\n            $._semicolon\n        ),\n        \n        // Contract Declarations\n        contract_declaration: $ => seq(\n            optional(\'abstract\'),\n            \'contract\',\n            field(\"name\", $.identifier),\n            optional($._class_heritage),\n            field(\'body\', $.contract_body),\n        ),\n\n        interface_declaration: $ => seq(\n            \'interface\',\n            field(\"name\", $.identifier),\n            optional($._class_heritage),\n            field(\'body\', $.contract_body),\n        ),\n\n        library_declaration: $ => seq(\n            \'library\',\n            field(\"name\", $.identifier),\n            field(\'body\', $.contract_body),\n        ),\n\n        _class_heritage: $ => seq(\n            \"is\", \n            commaSep1($.inheritance_specifier)\n        ),\n\n        inheritance_specifier: $ => seq(\n            field(\"ancestor\", $._user_defined_type),\n            optional(field(\"ancestor_arguments\", $._call_arguments)),\n        ),\n\n        contract_body: $  => seq(\n            \"{\",\n            repeat(choice(\n                $.function_definition,\n                $.modifier_definition,\n                $.state_variable_declaration,\n                $.struct_declaration,\n                $.enum_declaration,\n                $.event_definition,\n                $.using_directive,\n                $.constructor_definition,\n                $.fallback_receive_definition,\n            )),\n            \"}\",\n        ),\n\n        struct_declaration: $ =>  seq(\n            \'struct\',\n            field(\"struct_name\", $.identifier),\n            \'{\', \n            repeat1($.struct_member),\n            \'}\',\n        ),\n\n        struct_member: $ => seq(\n            field(\"type\", $.type_name),\n            field(\"name\", $.identifier),\n            $._semicolon\n        ),\n\n        enum_declaration: $ =>  seq(\n            \'enum\',\n            field(\"enum_type_name\", $.identifier),\n            \'{\',\n            commaSep(alias($.identifier, $.enum_value)),\n            \'}\',\n        ),\n            \n\n        event_definition: $ => seq(\n            \'event\',  field(\'name\', $.identifier), $._event_parameter_list ,  optional(\'anonymous\'), $._semicolon\n        ),\n\n        _event_parameter_list: $ => seq(\n            \"(\",\n            commaSep($.event_paramater),\n            \")\"\n        ),\n\n        event_paramater: $ => seq(\n            field(\"type\", $.type_name),\n            optional(\"indexed\"),\n            optional(field(\"name\", $.identifier)),\n        ),\n\n        using_directive: $ => seq(\n            \'using\', \n            alias($._user_defined_type, $.type_alias),\n            \'for\',\n            field(\"source\", choice($.any_source_type, $.type_name)),\n            $._semicolon\n        ),\n\n        any_source_type: $ => \'*\',\n\n        // -- [ Statements ] --\n        _statement: $ => choice(\n            $.block_statement,\n            $.expression_statement,\n            $.variable_declaration_statement,\n            $.if_statement,\n            $.for_statement,\n            $.while_statement,\n            $.do_while_statement,\n            $.continue_statement,\n            $.break_statement,\n            $.try_statement,\n            $.return_statement,\n            $.emit_statement,\n            $.assembly_statement\n        ),\n\n        assembly_statement: $ => seq(\n            \'assembly\',\n            optional(\'\"evmasm\"\'),\n            \"{\",\n            repeat($._yul_statement),\n            \"}\"\n        ),\n\n        // -- [ Yul ] --\n        _yul_statement: $ => choice(\n            $.yul_block,\n            $.yul_variable_declaration,\n            $.yul_assignment,\n            $.yul_function_call,\n            $.yul_if_statement,\n            $.yul_for_statement,\n            $.yul_switch_statement,\n            $.yul_leave,\n            $.yul_break,\n            $.yul_continue,\n            $.yul_function_definition\n        ),\n        \n        yul_leave: $ => \"leave\",\n        yul_break: $ => \"break\",\n        yul_continue: $ => \"continue\",\n\n        yul_identifier: $ => /[a-zA-Z$_]+/,\n        _yul_expression: $ => choice($.yul_path, $.yul_function_call, $._yul_literal),\n        yul_path: $ => prec.left(dotSep1($.yul_identifier)),\n        \n        // -- Yul Literals --\n        _yul_literal: $ =>  choice(\n            $.yul_decimal_number,\n            $.yul_string_literal,\n            $.yul_hex_number,\n            $.yul_boolean,\n        ),\n        yul_decimal_number: $ => /0|([1-9][0-9]*)/,\n        yul_string_literal: $ => $.string,\n        yul_hex_number: $ => /0x[0-9A-Fa-f]*/,\n        yul_boolean: $ => choice(\'true\', \'false\'),\n\n        // -- Yul Statements --\n        yul_block: $ => seq(\'{\', repeat($._yul_statement), \'}\'),\n        yul_variable_declaration: $ => prec.left(PREC.DECLARATION, choice(\n            seq(\'let\', field(\"left\", $.yul_identifier), optional(seq(\':=\', field(\"right\", $._yul_expression)))),\n            seq(\n                \'let\', field(\"left\", choice(\n                    commaSep1($.yul_identifier),\n                    seq(\'(\', commaSep1($.yul_identifier), \')\')\n                )), \n                optional(seq(\':=\', field(\"right\", $.yul_function_call)))),\n        )),\n        yul_assignment: $ => prec.left(PREC.ASSIGN, choice(\n            seq($.yul_path, \':=\', $._yul_expression),\n            seq(commaSep1($.yul_path), optional(seq(\':=\', $.yul_function_call))),\n        )),\n        yul_function_call: $ => seq(\n            field(\"function\", choice($.yul_identifier, $.yul_evm_builtin)), \'(\', commaSep($._yul_expression), \')\'\n        ),\n        yul_if_statement: $ => seq(\'if\', $._yul_expression, $.yul_block),\n        yul_for_statement: $ => seq(\'for\', $.yul_block, $._yul_expression, $.yul_block, $.yul_block),\n        yul_switch_statement: $ => seq(\n            \'switch\', $._yul_expression,\n            choice(\n                seq(\'default\', $.yul_block),\n                seq(\n                    repeat1(seq(\'case\', $._yul_literal, $.yul_block)),\n                    optional(seq(\'default\', $.yul_block)),\n                )\n            ),\n        ),\n        yul_function_definition: $ => seq(\n            \'function\', $.yul_identifier, \'(\', commaSep($.yul_identifier), \')\',\n            optional(seq(\'->\', commaSep1($.yul_identifier))),\n            $.yul_block\n        ),\n\n        yul_evm_builtin: $ => prec(1, choice(\n            \'stop\',\n            \'add\',\n            \'sub\',\n            \'mul\',\n            \'div\',\n            \'sdiv\',\n            \'mod\',\n            \'smod\',\n            \'exp\',\n            \'not\',\n            \'lt\',\n            \'gt\',\n            \'slt\',\n            \'sgt\',\n            \'eq\',\n            \'iszero\',\n            \'and\',\n            \'or\',\n            \'xor\',\n            \'byte\',\n            \'shl\',\n            \'shr\',\n            \'sar\',\n            \'addmod\',\n            \'mulmod\',\n            \'signextend\',\n            \'keccak256\',\n            \'pop\',\n            \'mload\',\n            \'mstore\',\n            \'mstore8\',\n            \'sload\',\n            \'sstore\',\n            \'msize\',\n            \'gas\',\n            \'address\',\n            \'balance\',\n            \'selfbalance\',\n            \'caller\',\n            \'callvalue\',\n            \'calldataload\',\n            \'calldatasize\',\n            \'calldatacopy\',\n            \'extcodesize\',\n            \'extcodecopy\',\n            \'returndatasize\',\n            \'returndatacopy\',\n            \'extcodehash\',\n            \'create\',\n            \'create2\',\n            \'call\',\n            \'callcode\',\n            \'delegatecall\',\n            \'staticcall\',\n            \'return\',\n            \'revert\',\n            \'selfdestruct\',\n            \'invalid\',\n            \'log0\',\n            \'log1\',\n            \'log2\',\n            \'log3\',\n            \'log4\',\n            \'chainid\',\n            \'origin\',\n            \'gasprice\',\n            \'blockhash\',\n            \'coinbase\',\n            \'timestamp\',\n            \'number\',\n            \'difficulty\',\n            \'gaslimit\',\n        )),\n\n        // -- [ Statements ] --\n        block_statement: $ => seq(\'{\', repeat($._statement), \"}\"),\n        variable_declaration_statement: $ => prec(3,seq(\n                choice(\n                    seq($.variable_declaration, optional(seq(\'=\', $._expression))),\n                    seq($.variable_declaration_tuple, \'=\', $._expression),\n                ),\n                $._semicolon\n        )),\n\n        // var_variable_decartion: $ => prec.left(seq(\n        //     \'var\',\n        //     choice(\n        //         $.identifier,\n        //         seq(\n        //             \'(\', \n        //             optional($.identifier),\n        //             repeat(\n        //                 seq(\n        //                     \',\',\n        //                     optional($.identifier),\n        //                 )\n        //             ),\n        //         \')\')\n        //     ),\n        //     \'=\',\n        //      $._expression,\n        //      $._semicolon,\n        // )),\n\n        variable_declaration: $ => seq(\n            $.type_name,\n            optional(choice(\'memory\', \'storage\', \'calldata\')),\n            field(\'name\', $.identifier)\n        ),\n\n        variable_declaration_tuple: $ => prec(3, choice(\n            seq(\n                \'(\', \n                commaSep($.variable_declaration),\n                \')\'\n            ),\n            seq(\'var\',\n                \'(\', \n                optional($.identifier),\n                repeat(\n                    seq(\n                        \',\',\n                        optional($.identifier),\n                    )\n                ),\n                \')\'\n            )\n        )),\n\n        expression_statement: $ => seq($._expression, $._semicolon),\n\n        if_statement: $ => prec.left(seq(\n            \'if\', \'(\',$._expression, \')\', $._statement, optional(seq(\'else\', $._statement)),\n        )),\n        \n        for_statement: $ => seq(\n            \'for\', \'(\', \n            choice($.variable_declaration_statement, $.expression_statement, $._semicolon),\n            choice($.expression_statement, $._semicolon),\n            optional($._expression),\n            \')\', $._statement,\n        ),\n\n        while_statement: $ => seq(\n            \'while\', \'(\',$._expression, \')\', $._statement,\n        ),\n        do_while_statement: $ => seq(\n            \'do\', $._statement, \'while\', \'(\',$._expression, \')\',\n        ),        \n        continue_statement: $ => seq(\'continue\', $._semicolon),\n        break_statement: $ => seq(\'break\', $._semicolon),\n        \n        try_statement: $ => seq(\n            \'try\', $._expression, optional(seq(\'returns\', $._parameter_list)), $.block_statement, repeat1($.catch_clause),\n        ),\n\n        catch_clause: $ => seq(\n            \'catch\', optional(seq(optional($.identifier), $._parameter_list)), $.block_statement,\n        ),\n\n        return_statement: $ => seq(\n            \'return\', optional($._expression), $._semicolon\n        ),\n        emit_statement: $ => seq(\n            \'emit\',  $._expression, $._call_arguments, $._semicolon\n        ),\n\n\n        //  -- [ Definitions ] --  \n        \n        // Definitions\n        state_variable_declaration: $ => seq(\n            field(\"type\", $.type_name),\n            repeat(choice(\n                field(\'visibility\', $.visibility), // FIXME: this also allows external\n                $.constant,\n                $.override_specifier,\n                $.immutable,\n            )),\n            field(\"name\", $.identifier),\n            optional(seq(\n                \'=\', field(\"value\", $._expression)\n            )),\n            $._semicolon\n        ),\n        constant: $ => \"constant\",\n        visibility: $ => choice(\n            \'public\',\n            \'internal\',\n            \'private\',\n            \'external\',\n        ),\n\n        state_mutability: $ => choice(\n            \'pure\',\n            \'view\',\n            \'payable\'\n        ),\n\n        immutable: $ => \'immutable\',\n        _override: $ => \'override\',\n\n        override_specifier: $ => seq(\n            \'override\',\n            optional(seq(\n                \'(\',\n                commaSep1($._user_defined_type),\n                \')\',\n            ))\n        ),\n\n        modifier_definition: $ => seq(\n            \"modifier\",\n            field(\"name\", $.identifier),\n            optional($._parameter_list),\n            repeat(choice(\n                $.virtual,\n                $.override_specifier,\n            )),\n            choice($._semicolon, field(\"body\", $.function_body)),\n        ),\n\n        constructor_definition: $ => seq(\n            \'constructor\',\n            $._parameter_list,\n            repeat(choice(\n                $.modifier_invocation,\n                \'payable\',\n                choice(\'internal\', \'public\'),\n            )),\n            field(\'body\', $.function_body),\n        ),\n\n        fallback_receive_definition: $ => seq(\n            choice(seq(\n                optional(\"function\"),\n                choice(\'fallback\', \'receive\'),\n                ),\n                \"function\"\n            ),\n            \'(\', \')\',\n            // FIXME: We use repeat to allow for unorderedness. However, this means that the parser \n            // accepts more than just the solidity language. The same problem exists for other definition rules.\n            repeat(choice(\n                $.visibility,      \n                $.modifier_invocation,\n                $.state_mutability,\n                $.virtual,\n                $.override_specifier,\n            )),\n            choice($._semicolon, field(\'body\', $.function_body))\n        ),\n\n        function_definition: $ => seq(\n            \"function\",\n            field(\"function_name\", $.identifier),\n            $._parameter_list,\n            repeat(choice(\n                $.modifier_invocation,\n                $.visibility,\n                $.state_mutability,\n                $.virtual,\n                $.override_specifier,\n            )),\n            field(\"return_type\", optional($.return_type_definition)),\n            choice($._semicolon, field(\'body\', $.function_body))\n        ),\n\n        return_type_definition: $ => seq(     \n            \'returns\',\n            $._parameter_list,\n        ),\n\n        virtual: $ => \"virtual\",\n        modifier_invocation: $ => seq($.identifier, optional($._call_arguments)),\n        \n        _call_arguments: $ => prec(4,\n            seq(\n                \'(\',\n                commaSep(choice(\n                    $._expression,\n                    seq(\"{\", commaSep($.identifier, \":\", $._expression), \"}\"),\n                )),\n                \')\'\n            ),\n        ),\n\n        function_body: $ => seq(\n            \"{\", \n            // TODO: make sure this is correct\n                repeat($._statement),\n            \"}\",\n        ),\n\n        // Expressions\n        _expression: $ => choice(\n            $.binary_expression,\n            $.unary_expression,\n            $.update_expression,\n            $.call_expression,\n            // TODO: $.function_call_options_expression,\n            $.payable_conversion_expression,\n            $.meta_type_expression,\n            $._primary_expression,\n            $.struct_expression,\n            $.ternary_expression,\n            $.type_cast_expression,\n        ),\n\n        // TODO: make primary expression anonymous\n        _primary_expression: $ => choice(\n            $.parenthesized_expression,\n            $.member_expression,\n            $.array_access,\n            $.slice_access,\n            $.primitive_type,\n            $.assignment_expression,\n            $.augmented_assignment_expression,\n            $._user_defined_type,\n            $.tuple_expression,\n            $.inline_array_expression,\n            $.identifier,\n            $._literal,\n            $.new_expression,\n        ),\n\n        // TODO: back this up with official documentation\n        type_cast_expression: $ => prec.left(seq($.primitive_type, \'(\', $._expression,\')\')),\n\n        ternary_expression: $ => prec.left(seq($._expression, \"?\", $._expression, \':\', $._expression)),\n\n        // TODO: make sure call arguments are part of solidity\n        new_expression: $ => prec.left(seq(\'new\', $.type_name, optional($._call_arguments))),\n\n        tuple_expression: $ => prec(1, seq(\n            \'(\', \n            optional($._expression),\n            repeat(\n                seq(\n                    \',\',\n                    optional($._expression),\n                )\n            ),\n            \')\'\n        )),\n\n        inline_array_expression: $ => seq(\n            \'[\', \n            commaSep($._expression),\n            \']\'\n        ),\n\n        binary_expression: $ => choice(\n            ...[\n            [\'&&\', PREC.AND],\n            [\'||\', PREC.OR],\n            [\'>>\', PREC.TIMES],\n            [\'>>>\', PREC.TIMES],\n            [\'<<\', PREC.TIMES],\n            [\'&\', PREC.AND],\n            [\'^\', PREC.OR],\n            [\'|\', PREC.OR],\n            [\'+\', PREC.PLUS],\n            [\'-\', PREC.PLUS],\n            [\'*\', PREC.TIMES],\n            [\'/\', PREC.TIMES],\n            [\'%\', PREC.TIMES],\n            [\'**\', PREC.EXP],\n            [\'<\', PREC.REL],\n            [\'<=\', PREC.REL],\n            [\'==\', PREC.REL],\n            [\'!=\', PREC.REL],\n            [\'!==\', PREC.REL],\n            [\'>=\', PREC.REL],\n            [\'>\', PREC.REL],\n            ].map(([operator, precedence]) =>\n                prec.left(precedence, seq(\n                    field(\'left\', $._expression),\n                    field(\'operator\', operator),\n                    field(\'right\', $._expression)\n                ))\n            )\n        ),\n\n        unary_expression: $ => choice(...[\n                [\'!\', PREC.NOT],\n                [\'~\', PREC.NOT],\n                [\'-\', PREC.NEG],\n                [\'+\', PREC.NEG],\n                [\'delete\', PREC.DELETE],\n            ].map(([operator, precedence]) =>\n                prec.left(precedence, seq(\n                    field(\'operator\', operator),\n                    field(\'argument\', $._expression)\n                ))\n        )),\n\n        update_expression: $ => prec.left(PREC.INC, choice(\n            seq(\n                field(\'argument\', $._expression),\n                field(\'operator\', choice(\'++\', \'--\'))\n            ),\n            seq(\n                field(\'operator\', choice(\'++\', \'--\')),\n                field(\'argument\', $._expression)\n            ),\n        )),\n\n        member_expression: $ => prec(PREC.MEMBER, seq(\n            field(\'object\', choice(\n                $._expression,\n                $.identifier,\n            )),\n            \'.\',\n            field(\'property\', alias($.identifier, $.property_identifier))\n        )),\n\n        array_access: $ => prec.right(14,seq(\n            field(\'base\', $._expression),\n            \'[\',\n            field(\'index\', $._expression), \n            \']\'\n        )),\n\n        slice_access: $ => prec(PREC.MEMBER, seq(\n            field(\'base\', $._expression),\n            \'[\',\n            field(\'from\', $._expression), \n            \':\',\n            field(\'to\', $._expression), \n            \']\'\n        )),\n\n        struct_expression: $ => seq(\n            $._expression,\n            \"{\",\n            commaSep(seq(\n                $.identifier,\n                \":\",\n                $._expression,\n            )),\n            \"}\"\n        ),\n        \n        _lhs_expression: $ => choice(\n            $.member_expression,\n            $.array_access,\n            $.identifier,\n            $.tuple_expression,\n            // $._destructuring_pattern\n        ),\n        parenthesized_expression: $ => prec(2, seq(\'(\', $._expression, \')\')),\n\n        assignment_expression: $ => prec.right(PREC.ASSIGN, seq(\n            field(\'left\', choice($.parenthesized_expression, $._lhs_expression)),\n            \'=\',\n            field(\'right\', $._expression)\n        )),\n      \n        augmented_assignment_expression: $ => prec.right(PREC.ASSIGN, seq(\n            field(\'left\', $._lhs_expression),\n            choice(\'+=\', \'-=\', \'*=\', \'/=\', \'%=\', \'^=\', \'&=\', \'|=\', \'>>=\', \'>>>=\',\n                \'<<=\',),\n            field(\'right\', $._expression)\n        )),\n          \n        call_expression: $ => seq(\n            seq($._expression, $._call_arguments),\n        ),\n\n        payable_conversion_expression: $ => seq(\'payable\', $._call_arguments),\n        meta_type_expression: $ => seq(\'type\', \'(\', $.type_name, \')\'),\n        \n        type_name: $ => prec(0, choice(\n            $.primitive_type,\n            $._user_defined_type,\n            $._mapping,\n            $._array_type,\n            $._function_type,\n        )),\n\n        _array_type: $ => prec(1, seq($.type_name, \'[\', optional($._expression), \']\')),\n        \n        _function_type: $ => prec.right(seq(\n            \'function\', $._parameter_list, optional($._return_parameters),\n        )),\n\n        _parameter_list: $ => seq(\n            \'(\', commaSep($.parameter), \')\'\n        ),\n\n        _return_parameters: $ => seq(\n            \'(\', commaSep1($._nameless_parameter), \')\'\n        ),\n\n        _nameless_parameter: $ =>  seq(\n            $.type_name,\n            optional($._storage_location),\n        ),\n\n        parameter: $ =>  seq(\n            field(\"type\", $.type_name),\n            optional(field(\"storage_location\", $._storage_location)),\n            optional(field(\"name\", $.identifier)),\n        ),\n\n        _storage_location: $ => choice(\n            \'memory\',\n            \'storage\',\n            \'calldata\'\n        ),\n\n        // TODO: make visible type\n        _user_defined_type: $ => prec.left(PREC. USER_TYPE, seq(\n            $.identifier,\n            repeat(seq(\n                \'.\',\n                $.identifier,\n            ))\n        )),\n\n        _mapping: $ => seq(\n            \'mapping\', \'(\', $._mapping_key, \'=>\', $.type_name, \')\',\n        ),\n\n        _mapping_key: $ => choice(\n            $.primitive_type,\n            $._user_defined_type\n        ),\n\n        primitive_type: $ => prec.left(choice(\n            seq(\'address\', optional(\'payable\')),\n            \'bool\',\n            \'string\',\n            \'var\',\n            $._int,\n            $._uint,\n            $._bytes,\n            $._fixed,\n            $._ufixed,\n        )),\n\n        _int: $ => choice (\n            \'int\', \'int8\', \'int16\', \'int24\', \'int32\', \'int40\', \'int48\', \'int56\', \'int64\', \'int72\', \'int80\', \'int88\', \'int96\', \'int104\', \'int112\', \'int120\', \'int128\', \'int136\', \'int144\', \'int152\', \'int160\', \'int168\', \'int176\', \'int184\', \'int192\', \'int200\', \'int208\', \'int216\', \'int224\', \'int232\', \'int240\', \'int248\', \'int256\'\n        ),\n        _uint: $ => choice (\n            \'uint\', \'uint8\', \'uint16\', \'uint24\', \'uint32\', \'uint40\', \'uint48\', \'uint56\', \'uint64\', \'uint72\', \'uint80\', \'uint88\', \'uint96\', \'uint104\', \'uint112\', \'uint120\', \'uint128\', \'uint136\', \'uint144\', \'uint152\', \'uint160\', \'uint168\', \'uint176\', \'uint184\', \'uint192\', \'uint200\', \'uint208\', \'uint216\', \'uint224\', \'uint232\', \'uint240\', \'uint248\', \'uint256\' \n        ),\n        _bytes: $ => choice (\n            \'byte\', \'bytes\', \'bytes1\', \'bytes2\', \'bytes3\', \'bytes4\', \'bytes5\', \'bytes6\', \'bytes7\', \'bytes8\', \'bytes9\', \'bytes10\', \'bytes11\', \'bytes12\', \'bytes13\', \'bytes14\', \'bytes15\', \'bytes16\', \'bytes17\', \'bytes18\', \'bytes19\', \'bytes20\', \'bytes21\', \'bytes22\', \'bytes23\', \'bytes24\', \'bytes25\', \'bytes26\', \'bytes27\', \'bytes28\', \'bytes29\', \'bytes30\', \'bytes31\', \'bytes32\'\n        ),\n\n        _fixed: $ => choice (\n            \'fixed\',\n            /fixed([0-9]+)x([0-9]+)/\n        ),\n        _ufixed: $ => choice (\n            \'ufixed\',\n            /ufixed([0-9]+)x([0-9]+)/\n        ),\n\n        _semicolon: $ => \';\',\n\n        identifier: $ => /[a-zA-Z$_][a-zA-Z0-9$_]*/,\n\n        number: $ => /\\d+/,\n\n        _literal: $ => choice(\n            $.string_literal,\n            $.number_literal,\n            $.boolean_literal,\n            $.hex_string_literal,\n            $.unicode_string_literal,\n        ),\n\n        string_literal: $ => prec.left(repeat1($.string)),\n        number_literal: $ => seq(choice($._decimal_number, $._hex_number), optional($.number_unit)),\n        _decimal_number: $ =>  choice(\n            /\\d+(\\.\\d+)?([eE](-)?\\d+)?/,\n            /\\.\\d+([eE](-)?\\d+)?/,\n        ),\n        _hex_number: $ => seq(/0[xX]/, optional(optionalDashSeparation($._hex_digit))),\n        _hex_digit: $ => /([a-fA-F0-9][a-fA-F0-9])/, \n        number_unit: $ => choice(\n            \'wei\',\'szabo\', \'finney\', \'gwei\', \'ether\', \'seconds\', \'minutes\', \'hours\', \'days\', \'weeks\', \'years\'\n        ),\n        true: $ => \"true\",\n        false: $ => \"false\",\n        boolean_literal: $ => choice($.true, $.false),\n        hex_string_literal: $ => prec.left(repeat1(seq(\n            \'hex\',\n            choice(\n                seq(\'\"\', optional(optionalDashSeparation($._hex_digit)), \'\"\'),\n                seq(\"\'\", optional(optionalDashSeparation($._hex_digit)), \"\'\"),\n            )))),\n        _escape_sequence: $ => seq(\'\\\\\', choice(\n            // TODO: it might be allowed to escape non special characters\n            /\"\'\\\\bfnrtv\\n\\r/,\n            /u([a-fA-F0-9]{4})/,\n            /x([a-fA-F0-9]{2})/,\n        )),\n        _escape_sequence: $ => token.immediate(seq(\n            \'\\\\\',\n            choice(\n              /[^xu0-7]/,\n              /[0-7]{1,3}/,\n              /x[0-9a-fA-F]{2}/,\n              /u[0-9a-fA-F]{4}/,\n              /u{[0-9a-fA-F]+}/\n            )\n        )),\n        _single_quoted_unicode_char: $ => choice(/[^\'\\r\\n\\\\]/, $._escape_sequence),\n        _double_quoted_unicode_char: $ => choice(/[^\"\\r\\n\\\\]/, $._escape_sequence),\n        unicode_string_literal: $ => prec.left(repeat1(seq(\n            \'unicode\',\n            choice(\n                seq(\'\"\', repeat($._double_quoted_unicode_char), \'\"\'),\n                seq(\"\'\", repeat($._single_quoted_unicode_char), \"\'\"),\n        )))),\n\n        string: $ => choice(\n            seq(\n            \'\"\',\n            repeat(choice(\n                token.immediate(prec(PREC.STRING, /[^\"\\\\\\n]+|\\\\\\r?\\n/)),\n                $._escape_sequence\n            )),\n            \'\"\'\n            ),\n            seq(\n            \"\'\",\n            repeat(choice(\n                token.immediate(prec(PREC.STRING, /[^\'\\\\\\n]+|\\\\\\r?\\n/)),\n                $._escape_sequence\n            )),\n            \"\'\"\n            )\n        ),\n        \n\n        // Based on: https://github.com/tree-sitter/tree-sitter-c/blob/master/grammar.js#L965\n        comment: $ => token(\n            prec(PREC.COMMENT,\n                choice(\n                    seq(\'//\', /(\\\\(.|\\r?\\n)|[^\\\\\\n])*/),\n                    seq(\n                        \'/*\',\n                        /[^*]*\\*+([^/*][^*]*\\*+)*/,\n                        \'/\'\n                    )\n                )\n            )\n        ),\n    }\n  }\n);\n\nfunction dotSep1(rule) {\n    return seq(\n        rule,\n        repeat(\n            seq(\n                \'.\',\n                rule\n            )\n        ),\n    );  \n}\n\nfunction dotSep(rule) {\n    return optional(dotSep1(rule))\n}\n\nfunction commaSep1(rule) {\n    return seq(\n        rule,\n        repeat(\n            seq(\n                \',\',\n                rule\n            )\n        ),\n        optional(\',\'),\n    );  \n}\n  \nfunction commaSep(rule) {\n    return optional(commaSep1(rule));\n}\n\nfunction optionalDashSeparation(rule) {\n    return seq(\n        rule,\n        repeat(\n            seq(\n                optional(\'_\'),\n                rule\n            )\n        ),\n    );  \n}\n  \n";
Expand description

The source of the Solidity tree-sitter grammar description.