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.