Constant tree_sitter_ruby::GRAMMAR [−][src]
pub const GRAMMAR: &'static str = "const PREC = {\n COMMENT: -2,\n CURLY_BLOCK: 1,\n DO_BLOCK: -1,\n\n AND: -2,\n OR: -2,\n NOT: 5,\n DEFINED: 10,\n ALIAS: 11,\n ASSIGN: 15,\n RESCUE: 16,\n CONDITIONAL: 20,\n RANGE: 25,\n BOOLEAN_OR: 30,\n BOOLEAN_AND: 35,\n RELATIONAL: 40,\n COMPARISON: 45,\n BITWISE_OR: 50,\n BITWISE_AND: 55,\n CALL: 56,\n SHIFT: 60,\n ADDITIVE: 65,\n MULTIPLICATIVE: 70,\n UNARY_MINUS: 75,\n EXPONENTIAL: 80,\n COMPLEMENT: 85,\n};\n\nconst IDENTIFIER_CHARS = /[^\\x00-\\x1F\\s:;`\"\'@$#.,|^&<=>+\\-*/\\\\%?!~()\\[\\]{}]*/;\nconst LOWER_ALPHA_CHAR = /[^\\x00-\\x1F\\sA-Z0-9:;`\"\'@$#.,|^&<=>+\\-*/\\\\%?!~()\\[\\]{}]/;\nconst ALPHA_CHAR = /[^\\x00-\\x1F\\s0-9:;`\"\'@$#.,|^&<=>+\\-*/\\\\%?!~()\\[\\]{}]/;\n\nmodule.exports = grammar({\n name: \'ruby\',\n\n externals: $ => [\n $._line_break,\n\n // Delimited literals\n $.simple_symbol,\n $._string_start,\n $._symbol_start,\n $._subshell_start,\n $._regex_start,\n $._string_array_start,\n $._symbol_array_start,\n $._heredoc_body_start,\n $.string_content,\n $.heredoc_content,\n $._string_end,\n $.heredoc_end,\n $.heredoc_beginning,\n\n // Tokens that require lookahead\n \'/\',\n $._block_ampersand,\n $._splat_star,\n $._unary_minus,\n $._binary_minus,\n $._binary_star,\n $._singleton_class_left_angle_left_langle,\n $.hash_key_symbol,\n $._hash_splat_star_star,\n $._binary_star_star,\n $._element_reference_bracket,\n ],\n\n extras: $ => [\n $.comment,\n $.heredoc_body,\n /\\s|\\\\\\n/\n ],\n\n word: $ => $.identifier,\n\n supertypes: $ => [\n $._statement,\n $._arg,\n $._method_name,\n $._variable,\n $._primary,\n $._lhs,\n ],\n\n rules: {\n program: $ => seq(\n optional($._statements),\n optional(seq(\n \'__END__\',\n $._line_break,\n $.uninterpreted)\n )\n ),\n\n uninterpreted: $ => /(.|\\s)*/,\n\n _statements: $ => choice(\n seq(\n repeat1(choice(\n seq($._statement, $._terminator),\n $.empty_statement\n )),\n optional($._statement)\n ),\n $._statement\n ),\n\n begin_block: $ => seq(\"BEGIN\", \"{\", optional($._statements), \"}\"),\n end_block: $ => seq(\"END\", \"{\", optional($._statements), \"}\"),\n\n _statement: $ => choice(\n $.undef,\n $.alias,\n $.if_modifier,\n $.unless_modifier,\n $.while_modifier,\n $.until_modifier,\n $.rescue_modifier,\n $.begin_block,\n $.end_block,\n $._expression\n ),\n\n method: $ => seq(\'def\', $._method_rest),\n\n singleton_method: $ => seq(\n \'def\',\n seq(\n choice(\n field(\'object\', $._variable),\n seq(\'(\', field(\'object\', $._arg), \')\')\n ),\n choice(\'.\', \'::\')\n ),\n $._method_rest\n ),\n\n _method_rest: $ => seq(\n field(\'name\', $._method_name),\n choice(\n seq(\n field(\'parameters\', alias($.parameters, $.method_parameters)),\n optional($._terminator)\n ),\n seq(\n optional(\n field(\'parameters\', alias($.bare_parameters, $.method_parameters))\n ),\n $._terminator\n ),\n ),\n $._body_statement\n ),\n\n parameters: $ => seq(\n \'(\',\n commaSep($._formal_parameter),\n \')\'\n ),\n\n bare_parameters: $ => seq(\n $._simple_formal_parameter,\n repeat(seq(\',\', $._formal_parameter))\n ),\n\n block_parameters: $ => seq(\n \'|\',\n seq(commaSep($._formal_parameter), optional(\',\')),\n optional(seq(\';\', sep1($.identifier, \',\'))), // Block shadow args e.g. {|; a, b| ...}\n \'|\'\n ),\n\n _formal_parameter: $ => choice(\n $._simple_formal_parameter,\n alias($.parameters, $.destructured_parameter)\n ),\n\n _simple_formal_parameter: $ => choice(\n $.identifier,\n $.splat_parameter,\n $.hash_splat_parameter,\n $.block_parameter,\n $.keyword_parameter,\n $.optional_parameter\n ),\n\n splat_parameter: $ => seq(\n \'*\',\n field(\'name\', optional($.identifier))\n ),\n hash_splat_parameter: $ => seq(\n \'**\',\n field(\'name\', optional($.identifier))\n ),\n block_parameter: $ => seq(\n \'&\',\n field(\'name\', $.identifier)\n ),\n keyword_parameter: $ => prec.right(PREC.BITWISE_OR + 1, seq(\n field(\'name\', $.identifier),\n token.immediate(\':\'),\n field(\'value\', optional($._arg))\n )),\n optional_parameter: $ => prec(PREC.BITWISE_OR + 1, seq(\n field(\'name\', $.identifier),\n \'=\',\n field(\'value\', $._arg)\n )),\n\n class: $ => seq(\n \'class\',\n field(\'name\', choice($.constant, $.scope_resolution)),\n field(\'superclass\', optional($.superclass)),\n $._terminator,\n $._body_statement\n ),\n\n superclass: $ => seq(\'<\', $._expression),\n\n singleton_class: $ => seq(\n \'class\',\n alias($._singleton_class_left_angle_left_langle, \'<<\'),\n field(\'value\', $._arg),\n $._terminator,\n $._body_statement\n ),\n\n module: $ => seq(\n \'module\',\n field(\'name\', choice($.constant, $.scope_resolution)),\n choice(\n seq($._terminator, $._body_statement),\n \'end\'\n )\n ),\n\n return_command: $ => prec.left(seq(\'return\', alias($.command_argument_list, $.argument_list))),\n yield_command: $ => prec.left(seq(\'yield\', alias($.command_argument_list, $.argument_list))),\n break_command: $ => prec.left(seq(\'break\', alias($.command_argument_list, $.argument_list))),\n next_command: $ => prec.left(seq(\'next\', alias($.command_argument_list, $.argument_list))),\n return: $ => prec.left(seq(\'return\', optional($.argument_list))),\n yield: $ => prec.left(seq(\'yield\', optional($.argument_list))),\n break: $ => prec.left(seq(\'break\', optional($.argument_list))),\n next: $ => prec.left(seq(\'next\', optional($.argument_list))),\n redo: $ => prec.left(seq(\'redo\', optional($.argument_list))),\n retry: $ => prec.left(seq(\'retry\', optional($.argument_list))),\n\n if_modifier: $ => prec(PREC.RESCUE, seq(\n field(\'body\', $._statement),\n \'if\',\n field(\'condition\', $._expression)\n )),\n\n unless_modifier: $ => prec(PREC.RESCUE, seq(\n field(\'body\', $._statement),\n \'unless\',\n field(\'condition\', $._expression)\n )),\n\n while_modifier: $ => prec(PREC.RESCUE, seq(\n field(\'body\', $._statement),\n \'while\',\n field(\'condition\', $._expression)\n )),\n\n until_modifier: $ => prec(PREC.RESCUE, seq(\n field(\'body\', $._statement),\n \'until\',\n field(\'condition\', $._expression)\n )),\n\n rescue_modifier: $ => prec(PREC.RESCUE, seq(\n field(\'body\', $._statement),\n \'rescue\',\n field(\'handler\', $._expression)\n )),\n\n while: $ => seq(\n \'while\',\n field(\'condition\', $._statement),\n field(\'body\', $.do)\n ),\n\n until: $ => seq(\n \'until\',\n field(\'condition\', $._statement),\n field(\'body\', $.do)\n ),\n\n for: $ => seq(\n \'for\',\n field(\'pattern\', choice($._lhs, $.left_assignment_list)),\n field(\'value\', $.in),\n field(\'body\', $.do)\n ),\n\n in: $ => seq(\'in\', $._arg),\n do: $ => seq(\n choice(\'do\', $._terminator),\n optional($._statements),\n \'end\'\n ),\n\n case: $ => seq(\n \'case\',\n field(\'value\', optional($._statement)),\n optional($._terminator),\n repeat($.when),\n optional($.else),\n \'end\'\n ),\n\n when: $ => seq(\n \'when\',\n commaSep1(field(\'pattern\', $.pattern)),\n choice($._terminator, field(\'body\', $.then))\n ),\n\n pattern: $ => choice($._arg, $.splat_argument),\n\n if: $ => seq(\n \'if\',\n field(\'condition\', $._statement),\n choice($._terminator, field(\'consequence\', $.then)),\n field(\'alternative\', optional(choice($.else, $.elsif))),\n \'end\'\n ),\n\n unless: $ => seq(\n \'unless\',\n field(\'condition\', $._statement),\n choice($._terminator, field(\'consequence\', $.then)),\n field(\'alternative\', optional(choice($.else, $.elsif))),\n \'end\'\n ),\n\n elsif: $ => seq(\n \'elsif\',\n field(\'condition\', $._statement),\n choice($._terminator, field(\'consequence\', $.then)),\n field(\'alternative\', optional(choice($.else, $.elsif)))\n ),\n\n else: $ => seq(\n \'else\',\n optional($._terminator),\n optional($._statements)\n ),\n\n then: $ => choice(\n seq(\n $._terminator,\n $._statements\n ),\n seq(\n optional($._terminator),\n \'then\',\n optional($._statements)\n )\n ),\n\n begin: $ => seq(\'begin\', optional($._terminator), $._body_statement),\n\n ensure: $ => seq(\'ensure\', optional($._statements)),\n\n rescue: $ => seq(\n \'rescue\',\n field(\'exceptions\', optional($.exceptions)),\n field(\'variable\', optional($.exception_variable)),\n choice(\n $._terminator,\n field(\'body\', $.then)\n )\n ),\n\n exceptions: $ => commaSep1(choice($._arg, $.splat_argument)),\n\n exception_variable: $ => seq(\'=>\', $._lhs),\n\n _body_statement: $ => seq(\n optional($._statements),\n repeat(choice($.rescue, $.else, $.ensure)),\n \'end\'\n ),\n\n // Method calls without parentheses (aka \"command calls\") are only allowed\n // in certain positions, like the top-level of a statement, the condition\n // of a postfix control-flow operator like `if`, or as the value of a\n // control-flow statement like `return`. In many other places, they\'re not\n // allowed.\n //\n // Because of this distinction, a lot of rules have two variants: the\n // normal variant, which can appear anywhere that an expression is valid,\n // and the \"command\" varaint, which is only valid in a more limited set of\n // positions, because it can contain \"command calls\".\n //\n // The `_expression` rule can appear in relatively few places, but can\n // contain command calls. The `_arg` rule can appear in many more places,\n // but cannot contain command calls (unless they are wrapped in parens).\n // This naming convention is based on Ruby\'s standard grammar.\n _expression: $ => choice(\n alias($.command_binary, $.binary),\n alias($.command_unary, $.unary),\n alias($.command_assignment, $.assignment),\n alias($.command_operator_assignment, $.operator_assignment),\n alias($.command_call, $.call),\n alias($.command_call_with_block, $.call),\n prec.left(alias($._chained_command_call, $.call)),\n alias($.return_command, $.return),\n alias($.yield_command, $.yield),\n alias($.break_command, $.break),\n alias($.next_command, $.next),\n $._arg\n ),\n\n _arg: $ => choice(\n $._primary,\n $.assignment,\n $.operator_assignment,\n $.conditional,\n $.range,\n $.binary,\n $.unary\n ),\n\n _primary: $ => choice(\n $.parenthesized_statements,\n $._lhs,\n $.array,\n $.string_array,\n $.symbol_array,\n $.hash,\n $.subshell,\n $.simple_symbol,\n $.delimited_symbol,\n $.integer,\n $.float,\n $.complex,\n $.rational,\n $.string,\n $.character,\n $.chained_string,\n $.regex,\n $.lambda,\n $.method,\n $.singleton_method,\n $.class,\n $.singleton_class,\n $.module,\n $.begin,\n $.while,\n $.until,\n $.if,\n $.unless,\n $.for,\n $.case,\n $.return,\n $.yield,\n $.break,\n $.next,\n $.redo,\n $.retry,\n alias($.parenthesized_unary, $.unary),\n alias($.unary_literal, $.unary),\n $.heredoc_beginning\n ),\n\n parenthesized_statements: $ => seq(\'(\', optional($._statements), \')\'),\n\n element_reference: $ => prec.left(1, seq(\n field(\'object\', $._primary),\n alias($._element_reference_bracket, \'[\'),\n optional($._argument_list_with_trailing_comma),\n \']\'\n )),\n\n scope_resolution: $ => prec.left(1, seq(\n choice(\n \'::\',\n seq(field(\'scope\', $._primary), token.immediate(\'::\'))\n ),\n field(\'name\', choice($.identifier, $.constant))\n )),\n\n _call: $ => prec.left(PREC.CALL, seq(\n field(\'receiver\', $._primary),\n choice(\'.\', \'&.\'),\n field(\'method\', choice($.identifier, $.operator, $.constant, $.argument_list))\n )),\n\n command_call: $ => seq(\n choice(\n $._call,\n $._chained_command_call,\n field(\'method\', choice(\n $._variable,\n $.scope_resolution\n )),\n ),\n field(\'arguments\', alias($.command_argument_list, $.argument_list))\n ),\n\n command_call_with_block: $ => {\n const receiver = choice(\n $._call,\n field(\'method\', choice($._variable, $.scope_resolution))\n )\n const arguments = field(\'arguments\', alias($.command_argument_list, $.argument_list))\n const block = field(\'block\', $.block)\n const doBlock = field(\'block\', $.do_block)\n return choice(\n seq(receiver, prec(PREC.CURLY_BLOCK, seq(arguments, block))),\n seq(receiver, prec(PREC.DO_BLOCK, seq(arguments, doBlock))),\n )\n },\n\n _chained_command_call: $ => seq(\n field(\'receiver\', alias($.command_call_with_block, $.call)),\n choice(\'.\', \'&.\'),\n field(\'method\', choice($.identifier, $.operator, $.constant, $.argument_list))\n ),\n\n call: $ => {\n const receiver = choice(\n $._call,\n field(\'method\', choice(\n $._variable,\n $.scope_resolution\n ))\n )\n const arguments = field(\'arguments\', $.argument_list)\n const block = field(\'block\', $.block)\n const doBlock = field(\'block\', $.do_block)\n return choice(\n seq(receiver, arguments),\n seq(receiver, prec(PREC.CURLY_BLOCK, seq(arguments, block))),\n seq(receiver, prec(PREC.DO_BLOCK, seq(arguments, doBlock))),\n prec(PREC.CURLY_BLOCK, seq(receiver, block)),\n prec(PREC.DO_BLOCK, seq(receiver, doBlock))\n )\n },\n\n command_argument_list: $ => prec.right(commaSep1($._argument)),\n\n argument_list: $ => prec.right(seq(\n token.immediate(\'(\'),\n optional($._argument_list_with_trailing_comma),\n \')\'\n )),\n\n _argument_list_with_trailing_comma: $ => prec.right(seq(\n commaSep1($._argument),\n optional(\',\')\n )),\n\n _argument: $ => prec.left(choice(\n $._expression,\n $.splat_argument,\n $.hash_splat_argument,\n $.block_argument,\n $.pair\n )),\n\n splat_argument: $ => seq(alias($._splat_star, \'*\'), $._arg),\n hash_splat_argument: $ => seq(alias($._hash_splat_star_star, \'**\'), $._arg),\n block_argument: $ => seq(alias($._block_ampersand, \'&\'), $._arg),\n\n do_block: $ => seq(\n \'do\',\n optional($._terminator),\n optional(seq(\n field(\'parameters\', $.block_parameters),\n optional($._terminator)\n )),\n $._body_statement\n ),\n\n block: $ => prec(PREC.CURLY_BLOCK, seq(\n \'{\',\n field(\'parameters\', optional($.block_parameters)),\n optional($._statements),\n \'}\'\n )),\n\n assignment: $ => prec.right(PREC.ASSIGN, choice(\n seq(\n field(\'left\', choice($._lhs, $.left_assignment_list)),\n \'=\',\n field(\'right\', choice(\n $._arg,\n $.splat_argument,\n $.right_assignment_list\n ))\n )\n )),\n\n command_assignment: $ => prec.right(PREC.ASSIGN, choice(\n seq(\n field(\'left\', choice($._lhs, $.left_assignment_list)),\n \'=\',\n field(\'right\', $._expression)\n )\n )),\n\n operator_assignment: $ => prec.right(PREC.ASSIGN, seq(\n field(\'left\', $._lhs),\n field(\'operator\', choice(\'+=\', \'-=\', \'*=\', \'**=\', \'/=\', \'||=\', \'|=\', \'&&=\', \'&=\', \'%=\', \'>>=\', \'<<=\', \'^=\')),\n field(\'right\', $._arg)\n )),\n\n command_operator_assignment: $ => prec.right(PREC.ASSIGN, seq(\n field(\'left\', $._lhs),\n field(\'operator\', choice(\'+=\', \'-=\', \'*=\', \'**=\', \'/=\', \'||=\', \'|=\', \'&&=\', \'&=\', \'%=\', \'>>=\', \'<<=\', \'^=\')),\n field(\'right\', $._expression)\n )),\n\n conditional: $ => prec.right(PREC.CONDITIONAL, seq(\n field(\'condition\', $._arg),\n \'?\',\n field(\'consequence\', $._arg),\n \':\',\n field(\'alternative\', $._arg)\n )),\n\n range: $ => {\n const begin = field(\'begin\', $._arg);\n const end = field(\'end\', $._arg);\n const operator = field(\'operator\', choice(\'..\', \'...\'));\n return prec.right(PREC.RANGE, choice(\n seq(begin, operator, end),\n seq(operator, end),\n seq(begin, operator)\n ));\n },\n\n binary: $ => {\n const operators = [\n [prec.left, PREC.AND, \'and\'],\n [prec.left, PREC.OR, \'or\'],\n [prec.left, PREC.BOOLEAN_OR, \'||\'],\n [prec.left, PREC.BOOLEAN_OR, \'&&\'],\n [prec.left, PREC.SHIFT, choice(\'<<\', \'>>\')],\n [prec.left, PREC.COMPARISON, choice(\'<\', \'<=\', \'>\', \'>=\')],\n [prec.left, PREC.BITWISE_AND, \'&\'],\n [prec.left, PREC.BITWISE_OR, choice(\'^\', \'|\')],\n [prec.left, PREC.ADDITIVE, choice(\'+\', alias($._binary_minus, \'-\'))],\n [prec.left, PREC.MULTIPLICATIVE, choice(\'/\', \'%\', alias($._binary_star, \'*\'))],\n [prec.right, PREC.RELATIONAL, choice(\'==\', \'!=\', \'===\', \'<=>\', \'=~\', \'!~\')],\n [prec.right, PREC.EXPONENTIAL, alias($._binary_star_star, \'**\')],\n ];\n\n return choice(...operators.map(([fn, precedence, operator]) => fn(precedence, seq(\n field(\'left\', $._arg),\n field(\'operator\', operator),\n field(\'right\', $._arg)\n ))));\n },\n\n command_binary: $ => prec.left(seq(\n field(\'left\', $._expression),\n field(\'operator\', choice(\'or\', \'and\')),\n field(\'right\', $._expression)\n )),\n\n unary: $ => {\n const operators = [\n [prec, PREC.DEFINED, \'defined?\'],\n [prec.right, PREC.NOT, \'not\'],\n [prec.right, PREC.UNARY_MINUS, choice(alias($._unary_minus, \'-\'), \'+\')],\n [prec.right, PREC.COMPLEMENT, choice(\'!\', \'~\')]\n ];\n return choice(...operators.map(([fn, precedence, operator]) => fn(precedence, seq(\n field(\'operator\', operator),\n field(\'operand\', $._arg)\n ))));\n },\n\n command_unary: $ => {\n const operators = [\n [prec, PREC.DEFINED, \'defined?\'],\n [prec.right, PREC.NOT, \'not\'],\n [prec.right, PREC.UNARY_MINUS, choice(alias($._unary_minus, \'-\'), \'+\')],\n [prec.right, PREC.COMPLEMENT, choice(\'!\', \'~\')]\n ];\n return choice(...operators.map(([fn, precedence, operator]) => fn(precedence, seq(\n field(\'operator\', operator),\n field(\'operand\', $._expression)\n ))));\n },\n\n parenthesized_unary: $ => prec(PREC.CALL, seq(\n field(\'operator\', choice(\'defined?\', \'not\')),\n field(\'operand\', $.parenthesized_statements)\n )),\n\n unary_literal: $ => prec.right(PREC.UNARY_MINUS, seq(\n field(\'operator\', choice(alias($._unary_minus, \'-\'), \'+\')),\n field(\'operand\', choice($.integer, $.float))\n )),\n\n right_assignment_list: $ => prec(-1, commaSep1(choice($._arg, $.splat_argument))),\n\n left_assignment_list: $ => $._mlhs,\n _mlhs: $ => prec.left(-1, seq(\n commaSep1(choice($._lhs, $.rest_assignment, $.destructured_left_assignment)),\n optional(\',\')\n )),\n destructured_left_assignment: $ => prec(-1, seq(\'(\', $._mlhs, \')\')),\n\n rest_assignment: $ => prec(-1, seq(\'*\', optional($._lhs))),\n\n _lhs: $ => prec.left(choice(\n $._variable,\n $.true,\n $.false,\n $.nil,\n $.scope_resolution,\n $.element_reference,\n alias($._call, $.call),\n $.call\n )),\n\n _variable: $ => prec.right(choice(\n $.self,\n $.super,\n $.instance_variable,\n $.class_variable,\n $.global_variable,\n $.identifier,\n $.constant\n )),\n\n operator: $ => choice(\n \'..\', \'|\', \'^\', \'&\', \'<=>\', \'==\', \'===\', \'=~\', \'>\', \'>=\', \'<\', \'<=\', \'+\',\n \'-\', \'*\', \'/\', \'%\', \'!\', \'!~\', \'**\', \'<<\', \'>>\', \'~\', \'+@\', \'-@\', \'[]\', \'[]=\', \'`\'\n ),\n\n _method_name: $ => choice(\n $.identifier,\n $.constant,\n $.setter,\n $.simple_symbol,\n $.delimited_symbol,\n $.operator,\n $.instance_variable,\n $.class_variable,\n $.global_variable\n ),\n setter: $ => seq(field(\'name\', $.identifier), \'=\'),\n\n undef: $ => seq(\'undef\', commaSep1($._method_name)),\n alias: $ => seq(\n \'alias\',\n field(\'name\', $._method_name),\n field(\'alias\', $._method_name)\n ),\n\n comment: $ => token(prec(PREC.COMMENT, choice(\n seq(\'#\', /.*/),\n seq(\n /=begin.*\\r?\\n/,\n repeat(choice(\n /[^=]/,\n /=[^e]/,\n /=e[^n]/,\n /=en[^d]/\n )),\n /=end/\n )\n ))),\n\n integer: $ => /0[bB][01](_?[01])*|0[oO]?[0-7](_?[0-7])*|(0[dD])?\\d(_?\\d)*|0[xX][0-9a-fA-F](_?[0-9a-fA-F])*/,\n\n float: $ => /\\d(_?\\d)*(\\.\\d)?(_?\\d)*([eE][\\+-]?\\d(_?\\d)*)?/,\n complex: $ => /(\\d+)?(\\+|-)?(\\d+)i/,\n rational: $ => seq(choice($.integer, $.float), \'r\'),\n super: $ => \'super\',\n self: $ => \'self\',\n true: $ => token(choice(\'true\', \'TRUE\')),\n false: $ => token(choice(\'false\', \'FALSE\')),\n nil: $ => token(choice(\'nil\', \'NIL\')),\n\n constant: $ => token(seq(/[A-Z]/, IDENTIFIER_CHARS, /(\\?|\\!)?/)),\n identifier: $ => token(seq(LOWER_ALPHA_CHAR, IDENTIFIER_CHARS, /(\\?|\\!)?/)),\n instance_variable: $ => token(seq(\'@\', ALPHA_CHAR, IDENTIFIER_CHARS)),\n class_variable: $ => token(seq(\'@@\', ALPHA_CHAR, IDENTIFIER_CHARS)),\n\n global_variable: $ => /\\$-?(([!@&`\'+~=/\\\\,;.<>*$?:\"])|([0-9]*)|([a-zA-Z_][a-zA-Z0-9_]*))/,\n\n chained_string: $ => seq($.string, repeat1($.string)),\n\n character: $ => /\\?(\\\\\\S({[0-9A-Fa-f]*}|[0-9A-Fa-f]*|-\\S([MC]-\\S)?)?|\\S)/,\n\n interpolation: $ => seq(\n \'#{\', optional($._statements),\'}\'\n ),\n\n string: $ => seq(\n alias($._string_start, \'\"\'),\n optional($._literal_contents),\n alias($._string_end, \'\"\')\n ),\n\n subshell: $ => seq(\n alias($._subshell_start, \'`\'),\n optional($._literal_contents),\n alias($._string_end, \'`\')\n ),\n\n string_array: $ => seq(\n alias($._string_array_start, \'%w(\'),\n optional(/\\s+/),\n sep(alias($._literal_contents, $.bare_string), /\\s+/),\n optional(/\\s+/),\n alias($._string_end, \')\')\n ),\n\n symbol_array: $ => seq(\n alias($._symbol_array_start, \'%i(\'),\n optional(/\\s+/),\n sep(alias($._literal_contents, $.bare_symbol), /\\s+/),\n optional(/\\s+/),\n alias($._string_end, \')\')\n ),\n\n delimited_symbol: $ => seq(\n alias($._symbol_start, \':\"\'),\n optional($._literal_contents),\n alias($._string_end, \'\"\')\n ),\n\n regex: $ => seq(\n alias($._regex_start, \'/\'),\n optional($._literal_contents),\n alias($._string_end, \'/\')\n ),\n\n heredoc_body: $ => seq(\n $._heredoc_body_start,\n repeat(choice(\n $.heredoc_content,\n $.interpolation,\n $.escape_sequence\n )),\n $.heredoc_end\n ),\n\n _literal_contents: $ => repeat1(choice(\n $.string_content,\n $.interpolation,\n $.escape_sequence\n )),\n\n // https://ruby-doc.org/core-2.5.0/doc/syntax/literals_rdoc.html#label-Strings\n escape_sequence: $ => token(seq(\n \'\\\\\',\n choice(\n /[^ux0-7]/, // single character\n /x[0-9a-fA-F]{1,2}/, // hex code\n /[0-7]{1,3}/, // octal\n /u[0-9a-fA-F]{4}/, // single unicode\n /u{[0-9a-fA-F ]+}/, // multiple unicode\n )\n )),\n\n array: $ => seq(\n \'[\',\n optional($._argument_list_with_trailing_comma),\n \']\'\n ),\n\n hash: $ => seq(\n \'{\',\n optional(seq(\n commaSep1(choice($.pair, $.hash_splat_argument)),\n optional(\',\')\n )),\n \'}\'\n ),\n\n pair: $ => choice(\n seq(\n field(\'key\', $._arg),\n \'=>\',\n field(\'value\', $._arg)\n ),\n seq(\n field(\'key\', choice(\n $.hash_key_symbol,\n alias($.identifier, $.hash_key_symbol),\n alias($.constant, $.hash_key_symbol),\n $.string\n )),\n token.immediate(\':\'),\n field(\'value\', $._arg)\n )\n ),\n\n lambda: $ => seq(\n \'->\',\n field(\'parameters\', optional(choice(\n alias($.parameters, $.lambda_parameters),\n alias($.bare_parameters, $.lambda_parameters)\n ))),\n field(\'body\', choice($.block, $.do_block))\n ),\n\n empty_statement: $ => prec(-1, \';\'),\n\n _terminator: $ => choice(\n $._line_break,\n \';\'\n ),\n }\n});\n\nfunction sep (rule, separator) {\n return optional(sep1(rule, separator));\n}\n\nfunction sep1 (rule, separator) {\n return seq(rule, repeat(seq(separator, rule)));\n}\n\nfunction commaSep1 (rule) {\n return sep1(rule, \',\');\n}\n\nfunction commaSep (rule) {\n return optional(commaSep1(rule));\n}\n";
Expand description
The source of the Ruby tree-sitter grammar description.