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.