pub const GRAMMAR: &str = "/**\n * @file JavaScript grammar for tree-sitter\n * @author Max Brunsfeld <maxbrunsfeld@gmail.com>\n * @license MIT\n */\n\n/* eslint-disable arrow-parens */\n/* eslint-disable camelcase */\n/* eslint-disable-next-line spaced-comment */\n/// <reference types=\"tree-sitter-cli/dsl\" />\n// @ts-check\n\nmodule.exports = grammar({\n  name: \'javascript\',\n\n  externals: $ => [\n    $._automatic_semicolon,\n    $._template_chars,\n    $._ternary_qmark,\n    $.html_comment,\n    \'||\',\n    // We use escape sequence and regex pattern to tell the scanner if we\'re currently inside a string or template string, in which case\n    // it should NOT parse html comments.\n    $.escape_sequence,\n    $.regex_pattern,\n  ],\n\n  extras: $ => [\n    $.comment,\n    $.html_comment,\n    /[\\s\\p{Zs}\\uFEFF\\u2028\\u2029\\u2060\\u200B]/,\n  ],\n\n  supertypes: $ => [\n    $.statement,\n    $.declaration,\n    $.expression,\n    $.primary_expression,\n    $.pattern,\n  ],\n\n  inline: $ => [\n    $._call_signature,\n    $._formal_parameter,\n    $.statement,\n    $._expressions,\n    $._semicolon,\n    $._identifier,\n    $._reserved_identifier,\n    $._jsx_attribute,\n    $._jsx_element_name,\n    $._jsx_child,\n    $._jsx_element,\n    $._jsx_attribute_name,\n    $._jsx_attribute_value,\n    $._jsx_identifier,\n    $._lhs_expression,\n  ],\n\n  precedences: $ => [\n    [\n      \'member\',\n      \'call\',\n      $.update_expression,\n      \'unary_void\',\n      \'binary_exp\',\n      \'binary_times\',\n      \'binary_plus\',\n      \'binary_shift\',\n      \'binary_compare\',\n      \'binary_relation\',\n      \'binary_equality\',\n      \'bitwise_and\',\n      \'bitwise_xor\',\n      \'bitwise_or\',\n      \'logical_and\',\n      \'logical_or\',\n      \'ternary\',\n      $.sequence_expression,\n      $.arrow_function,\n    ],\n    [\'assign\', $.primary_expression],\n    [\'member\', \'new\', \'call\', $.expression],\n    [\'declaration\', \'literal\'],\n    [$.primary_expression, $.statement_block, \'object\'],\n    [$.import_statement, $.import],\n    [$.export_statement, $.primary_expression],\n    [$.lexical_declaration, $.primary_expression],\n  ],\n\n  conflicts: $ => [\n    [$.primary_expression, $._property_name],\n    [$.primary_expression, $._property_name, $.arrow_function],\n    [$.primary_expression, $.arrow_function],\n    [$.primary_expression, $.method_definition],\n    [$.primary_expression, $.rest_pattern],\n    [$.primary_expression, $.pattern],\n    [$.primary_expression, $._for_header],\n    [$.array, $.array_pattern],\n    [$.object, $.object_pattern],\n    [$.assignment_expression, $.pattern],\n    [$.assignment_expression, $.object_assignment_pattern],\n    [$.labeled_statement, $._property_name],\n    [$.computed_property_name, $.array],\n    [$.binary_expression, $._initializer],\n  ],\n\n  word: $ => $.identifier,\n\n  rules: {\n    program: $ => seq(\n      optional($.hash_bang_line),\n      repeat($.statement),\n    ),\n\n    hash_bang_line: _ => /#!.*/,\n\n    //\n    // Export declarations\n    //\n\n    export_statement: $ => choice(\n      seq(\n        \'export\',\n        choice(\n          seq(\'*\', $._from_clause),\n          seq($.namespace_export, $._from_clause),\n          seq($.export_clause, $._from_clause),\n          $.export_clause,\n        ),\n        $._semicolon,\n      ),\n      seq(\n        repeat(field(\'decorator\', $.decorator)),\n        \'export\',\n        choice(\n          field(\'declaration\', $.declaration),\n          seq(\n            \'default\',\n            choice(\n              field(\'declaration\', $.declaration),\n              seq(\n                field(\'value\', $.expression),\n                $._semicolon,\n              ),\n            ),\n          ),\n        ),\n      ),\n    ),\n\n    namespace_export: $ => seq(\n      \'*\', \'as\', $._module_export_name,\n    ),\n\n    export_clause: $ => seq(\n      \'{\',\n      commaSep($.export_specifier),\n      optional(\',\'),\n      \'}\',\n    ),\n\n    export_specifier: $ => seq(\n      field(\'name\', $._module_export_name),\n      optional(seq(\n        \'as\',\n        field(\'alias\', $._module_export_name),\n      )),\n    ),\n\n    _module_export_name: $ => choice(\n      $.identifier,\n      $.string,\n    ),\n\n    declaration: $ => choice(\n      $.function_declaration,\n      $.generator_function_declaration,\n      $.class_declaration,\n      $.lexical_declaration,\n      $.variable_declaration,\n    ),\n\n    //\n    // Import declarations\n    //\n\n    import: _ => token(\'import\'),\n\n    import_statement: $ => seq(\n      \'import\',\n      choice(\n        seq($.import_clause, $._from_clause),\n        field(\'source\', $.string),\n      ),\n      optional($.import_attribute),\n      $._semicolon,\n    ),\n\n    import_clause: $ => choice(\n      $.namespace_import,\n      $.named_imports,\n      seq(\n        $.identifier,\n        optional(seq(\n          \',\',\n          choice(\n            $.namespace_import,\n            $.named_imports,\n          ),\n        )),\n      ),\n    ),\n\n    _from_clause: $ => seq(\n      \'from\', field(\'source\', $.string),\n    ),\n\n    namespace_import: $ => seq(\n      \'*\', \'as\', $.identifier,\n    ),\n\n    named_imports: $ => seq(\n      \'{\',\n      commaSep($.import_specifier),\n      optional(\',\'),\n      \'}\',\n    ),\n\n    import_specifier: $ => choice(\n      field(\'name\', $.identifier),\n      seq(\n        field(\'name\', $._module_export_name),\n        \'as\',\n        field(\'alias\', $.identifier),\n      ),\n    ),\n\n    import_attribute: $ => seq(\'with\', $.object),\n\n    //\n    // Statements\n    //\n\n    statement: $ => choice(\n      $.export_statement,\n      $.import_statement,\n      $.debugger_statement,\n      $.expression_statement,\n      $.declaration,\n      $.statement_block,\n\n      $.if_statement,\n      $.switch_statement,\n      $.for_statement,\n      $.for_in_statement,\n      $.while_statement,\n      $.do_statement,\n      $.try_statement,\n      $.with_statement,\n\n      $.break_statement,\n      $.continue_statement,\n      $.return_statement,\n      $.throw_statement,\n      $.empty_statement,\n      $.labeled_statement,\n    ),\n\n    expression_statement: $ => seq(\n      $._expressions,\n      $._semicolon,\n    ),\n\n    variable_declaration: $ => seq(\n      \'var\',\n      commaSep1($.variable_declarator),\n      $._semicolon,\n    ),\n\n    lexical_declaration: $ => seq(\n      field(\'kind\', choice(\'let\', \'const\')),\n      commaSep1($.variable_declarator),\n      $._semicolon,\n    ),\n\n    variable_declarator: $ => seq(\n      field(\'name\', choice($.identifier, $._destructuring_pattern)),\n      optional($._initializer),\n    ),\n\n    statement_block: $ => prec.right(seq(\n      \'{\',\n      repeat($.statement),\n      \'}\',\n      optional($._automatic_semicolon),\n    )),\n\n    else_clause: $ => seq(\'else\', $.statement),\n\n    if_statement: $ => prec.right(seq(\n      \'if\',\n      field(\'condition\', $.parenthesized_expression),\n      field(\'consequence\', $.statement),\n      optional(field(\'alternative\', $.else_clause)),\n    )),\n\n    switch_statement: $ => seq(\n      \'switch\',\n      field(\'value\', $.parenthesized_expression),\n      field(\'body\', $.switch_body),\n    ),\n\n    for_statement: $ => seq(\n      \'for\',\n      \'(\',\n      field(\'initializer\', choice(\n        $.lexical_declaration,\n        $.variable_declaration,\n        $.expression_statement,\n        $.empty_statement,\n      )),\n      field(\'condition\', choice(\n        $.expression_statement,\n        $.empty_statement,\n      )),\n      field(\'increment\', optional($._expressions)),\n      \')\',\n      field(\'body\', $.statement),\n    ),\n\n    for_in_statement: $ => seq(\n      \'for\',\n      optional(\'await\'),\n      $._for_header,\n      field(\'body\', $.statement),\n    ),\n\n    _for_header: $ => seq(\n      \'(\',\n      choice(\n        field(\'left\', choice(\n          $._lhs_expression,\n          $.parenthesized_expression,\n        )),\n        seq(\n          field(\'kind\', \'var\'),\n          field(\'left\', choice(\n            $.identifier,\n            $._destructuring_pattern,\n          )),\n          optional($._initializer),\n        ),\n        seq(\n          field(\'kind\', choice(\'let\', \'const\')),\n          field(\'left\', choice(\n            $.identifier,\n            $._destructuring_pattern,\n          )),\n        ),\n      ),\n      field(\'operator\', choice(\'in\', \'of\')),\n      field(\'right\', $._expressions),\n      \')\',\n    ),\n\n    while_statement: $ => seq(\n      \'while\',\n      field(\'condition\', $.parenthesized_expression),\n      field(\'body\', $.statement),\n    ),\n\n    do_statement: $ => prec.right(seq(\n      \'do\',\n      field(\'body\', $.statement),\n      \'while\',\n      field(\'condition\', $.parenthesized_expression),\n      optional($._semicolon),\n    )),\n\n    try_statement: $ => seq(\n      \'try\',\n      field(\'body\', $.statement_block),\n      optional(field(\'handler\', $.catch_clause)),\n      optional(field(\'finalizer\', $.finally_clause)),\n    ),\n\n    with_statement: $ => seq(\n      \'with\',\n      field(\'object\', $.parenthesized_expression),\n      field(\'body\', $.statement),\n    ),\n\n    break_statement: $ => seq(\n      \'break\',\n      field(\'label\', optional(alias($.identifier, $.statement_identifier))),\n      $._semicolon,\n    ),\n\n    continue_statement: $ => seq(\n      \'continue\',\n      field(\'label\', optional(alias($.identifier, $.statement_identifier))),\n      $._semicolon,\n    ),\n\n    debugger_statement: $ => seq(\n      \'debugger\',\n      $._semicolon,\n    ),\n\n    return_statement: $ => seq(\n      \'return\',\n      optional($._expressions),\n      $._semicolon,\n    ),\n\n    throw_statement: $ => seq(\n      \'throw\',\n      $._expressions,\n      $._semicolon,\n    ),\n\n    empty_statement: _ => \';\',\n\n    labeled_statement: $ => prec.dynamic(-1, seq(\n      field(\'label\', alias(choice($.identifier, $._reserved_identifier), $.statement_identifier)),\n      \':\',\n      field(\'body\', $.statement),\n    )),\n\n    //\n    // Statement components\n    //\n\n    switch_body: $ => seq(\n      \'{\',\n      repeat(choice($.switch_case, $.switch_default)),\n      \'}\',\n    ),\n\n    switch_case: $ => seq(\n      \'case\',\n      field(\'value\', $._expressions),\n      \':\',\n      field(\'body\', repeat($.statement)),\n    ),\n\n    switch_default: $ => seq(\n      \'default\',\n      \':\',\n      field(\'body\', repeat($.statement)),\n    ),\n\n    catch_clause: $ => seq(\n      \'catch\',\n      optional(seq(\'(\', field(\'parameter\', choice($.identifier, $._destructuring_pattern)), \')\')),\n      field(\'body\', $.statement_block),\n    ),\n\n    finally_clause: $ => seq(\n      \'finally\',\n      field(\'body\', $.statement_block),\n    ),\n\n    parenthesized_expression: $ => seq(\n      \'(\',\n      $._expressions,\n      \')\',\n    ),\n\n    //\n    // Expressions\n    //\n    _expressions: $ => choice(\n      $.expression,\n      $.sequence_expression,\n    ),\n\n    expression: $ => choice(\n      $.primary_expression,\n      $.glimmer_template,\n      $._jsx_element,\n      $.assignment_expression,\n      $.augmented_assignment_expression,\n      $.await_expression,\n      $.unary_expression,\n      $.binary_expression,\n      $.ternary_expression,\n      $.update_expression,\n      $.new_expression,\n      $.yield_expression,\n    ),\n\n    primary_expression: $ => choice(\n      $.subscript_expression,\n      $.member_expression,\n      $.parenthesized_expression,\n      $._identifier,\n      alias($._reserved_identifier, $.identifier),\n      $.this,\n      $.super,\n      $.number,\n      $.string,\n      $.template_string,\n      $.regex,\n      $.true,\n      $.false,\n      $.null,\n      $.object,\n      $.array,\n      $.function_expression,\n      $.arrow_function,\n      $.generator_function,\n      $.class,\n      $.meta_property,\n      $.call_expression,\n    ),\n\n    yield_expression: $ => prec.right(seq(\n      \'yield\',\n      choice(\n        seq(\'*\', $.expression),\n        optional($.expression),\n      ))),\n\n    object: $ => prec(\'object\', seq(\n      \'{\',\n      commaSep(optional(choice(\n        $.pair,\n        $.spread_element,\n        $.method_definition,\n        alias(\n          choice($.identifier, $._reserved_identifier),\n          $.shorthand_property_identifier,\n        ),\n      ))),\n      \'}\',\n    )),\n\n    object_pattern: $ => prec(\'object\', seq(\n      \'{\',\n      commaSep(optional(choice(\n        $.pair_pattern,\n        $.rest_pattern,\n        $.object_assignment_pattern,\n        alias(\n          choice($.identifier, $._reserved_identifier),\n          $.shorthand_property_identifier_pattern,\n        ),\n      ))),\n      \'}\',\n    )),\n\n    assignment_pattern: $ => seq(\n      field(\'left\', $.pattern),\n      \'=\',\n      field(\'right\', $.expression),\n    ),\n\n    object_assignment_pattern: $ => seq(\n      field(\'left\', choice(\n        alias(choice($._reserved_identifier, $.identifier), $.shorthand_property_identifier_pattern),\n        $._destructuring_pattern,\n      )),\n      \'=\',\n      field(\'right\', $.expression),\n    ),\n\n    array: $ => seq(\n      \'[\',\n      commaSep(optional(choice(\n        $.expression,\n        $.spread_element,\n      ))),\n      \']\',\n    ),\n\n    array_pattern: $ => seq(\n      \'[\',\n      commaSep(optional(choice(\n        $.pattern,\n        $.assignment_pattern,\n      ))),\n      \']\',\n    ),\n\n    glimmer_template: $ => choice(\n      seq(\n        field(\'open_tag\', $.glimmer_opening_tag),\n        field(\'content\', repeat($._glimmer_template_content)),\n        field(\'close_tag\', $.glimmer_closing_tag),\n      ),\n      // empty template has no content\n      // <template></template>\n      seq(\n        field(\'open_tag\', $.glimmer_opening_tag),\n        field(\'close_tag\', $.glimmer_closing_tag),\n      ),\n    ),\n\n    _glimmer_template_content: _ => /.{1,}/,\n    glimmer_opening_tag: _ => seq(\'<template>\'),\n    glimmer_closing_tag: _ => seq(\'</template>\'),\n\n    _jsx_element: $ => choice($.jsx_element, $.jsx_self_closing_element),\n\n    jsx_element: $ => seq(\n      field(\'open_tag\', $.jsx_opening_element),\n      repeat($._jsx_child),\n      field(\'close_tag\', $.jsx_closing_element),\n    ),\n\n    // Should not contain new lines and should not start or end with a space\n    jsx_text: _ => choice(\n      /[^{}<>\\n& ]([^{}<>\\n&]*[^{}<>\\n& ])?/,\n      /\\/\\/[^\\n]*/,\n    ),\n\n    // An entity can be named, numeric (decimal), or numeric (hexadecimal). The\n    // longest entity name is 29 characters long, and the HTML spec says that\n    // no more will ever be added.\n    html_character_reference: _ => /&(#([xX][0-9a-fA-F]{1,6}|[0-9]{1,5})|[A-Za-z]{1,30});/,\n\n    jsx_expression: $ => seq(\n      \'{\',\n      optional(choice(\n        $.expression,\n        $.sequence_expression,\n        $.spread_element,\n      )),\n      \'}\',\n    ),\n\n    _jsx_child: $ => choice(\n      $.jsx_text,\n      $.html_character_reference,\n      $._jsx_element,\n      $.jsx_expression,\n    ),\n\n    jsx_opening_element: $ => prec.dynamic(-1, seq(\n      \'<\',\n      optional(seq(\n        field(\'name\', $._jsx_element_name),\n        repeat(field(\'attribute\', $._jsx_attribute)),\n      )),\n      \'>\',\n    )),\n\n    jsx_identifier: _ => /[a-zA-Z_$][a-zA-Z\\d_$]*-[a-zA-Z\\d_$\\-]*/,\n\n    _jsx_identifier: $ => choice(\n      alias($.jsx_identifier, $.identifier),\n      $.identifier,\n    ),\n\n    nested_identifier: $ => prec(\'member\', seq(\n      field(\'object\', choice($.identifier, alias($.nested_identifier, $.member_expression))),\n      \'.\',\n      field(\'property\', alias($.identifier, $.property_identifier)),\n    )),\n\n    jsx_namespace_name: $ => seq($._jsx_identifier, \':\', $._jsx_identifier),\n\n    _jsx_element_name: $ => choice(\n      $._jsx_identifier,\n      alias($.nested_identifier, $.member_expression),\n      $.jsx_namespace_name,\n    ),\n\n    jsx_closing_element: $ => seq(\n      \'</\',\n      optional(field(\'name\', $._jsx_element_name)),\n      \'>\',\n    ),\n\n    jsx_self_closing_element: $ => seq(\n      \'<\',\n      field(\'name\', $._jsx_element_name),\n      repeat(field(\'attribute\', $._jsx_attribute)),\n      \'/>\',\n    ),\n\n    _jsx_attribute: $ => choice($.jsx_attribute, $.jsx_expression),\n\n    _jsx_attribute_name: $ => choice(alias($._jsx_identifier, $.property_identifier), $.jsx_namespace_name),\n\n    jsx_attribute: $ => seq(\n      $._jsx_attribute_name,\n      optional(seq(\n        \'=\',\n        $._jsx_attribute_value,\n      )),\n    ),\n\n    _jsx_string: $ => choice(\n      seq(\n        \'\"\',\n        repeat(choice(\n          alias($.unescaped_double_jsx_string_fragment, $.string_fragment),\n          $.html_character_reference,\n        )),\n        \'\"\',\n      ),\n      seq(\n        \'\\\'\',\n        repeat(choice(\n          alias($.unescaped_single_jsx_string_fragment, $.string_fragment),\n          $.html_character_reference,\n        )),\n        \'\\\'\',\n      ),\n    ),\n\n    // Workaround to https://github.com/tree-sitter/tree-sitter/issues/1156\n    // We give names to the token() constructs containing a regexp\n    // so as to obtain a node in the CST.\n    //\n    unescaped_double_jsx_string_fragment: _ => token.immediate(prec(1, /([^\"&]|&[^#A-Za-z])+/)),\n\n    // same here\n    unescaped_single_jsx_string_fragment: _ => token.immediate(prec(1, /([^\'&]|&[^#A-Za-z])+/)),\n\n    _jsx_attribute_value: $ => choice(\n      alias($._jsx_string, $.string),\n      $.jsx_expression,\n      $._jsx_element,\n    ),\n\n    class: $ => prec(\'literal\', seq(\n      repeat(field(\'decorator\', $.decorator)),\n      \'class\',\n      field(\'name\', optional($.identifier)),\n      optional($.class_heritage),\n      field(\'body\', $.class_body),\n    )),\n\n    class_declaration: $ => prec(\'declaration\', seq(\n      repeat(field(\'decorator\', $.decorator)),\n      \'class\',\n      field(\'name\', $.identifier),\n      optional($.class_heritage),\n      field(\'body\', $.class_body),\n      optional($._automatic_semicolon),\n    )),\n\n    class_heritage: $ => seq(\'extends\', $.expression),\n\n    function_expression: $ => prec(\'literal\', seq(\n      optional(\'async\'),\n      \'function\',\n      field(\'name\', optional($.identifier)),\n      $._call_signature,\n      field(\'body\', $.statement_block),\n    )),\n\n    function_declaration: $ => prec.right(\'declaration\', seq(\n      optional(\'async\'),\n      \'function\',\n      field(\'name\', $.identifier),\n      $._call_signature,\n      field(\'body\', $.statement_block),\n      optional($._automatic_semicolon),\n    )),\n\n    generator_function: $ => prec(\'literal\', seq(\n      optional(\'async\'),\n      \'function\',\n      \'*\',\n      field(\'name\', optional($.identifier)),\n      $._call_signature,\n      field(\'body\', $.statement_block),\n    )),\n\n    generator_function_declaration: $ => prec.right(\'declaration\', seq(\n      optional(\'async\'),\n      \'function\',\n      \'*\',\n      field(\'name\', $.identifier),\n      $._call_signature,\n      field(\'body\', $.statement_block),\n      optional($._automatic_semicolon),\n    )),\n\n    arrow_function: $ => seq(\n      optional(\'async\'),\n      choice(\n        field(\'parameter\', choice(\n          alias($._reserved_identifier, $.identifier),\n          $.identifier,\n        )),\n        $._call_signature,\n      ),\n      \'=>\',\n      field(\'body\', choice(\n        $.expression,\n        $.statement_block,\n      )),\n    ),\n\n    // Override\n    _call_signature: $ => field(\'parameters\', $.formal_parameters),\n    _formal_parameter: $ => choice($.pattern, $.assignment_pattern),\n\n    optional_chain: _ => \'?.\',\n\n    call_expression: $ => choice(\n      prec(\'call\', seq(\n        field(\'function\', choice($.expression, $.import)),\n        field(\'arguments\', choice($.arguments, $.template_string)),\n      )),\n      prec(\'member\', seq(\n        field(\'function\', $.primary_expression),\n        field(\'optional_chain\', $.optional_chain),\n        field(\'arguments\', $.arguments),\n      )),\n    ),\n\n    new_expression: $ => prec.right(\'new\', seq(\n      \'new\',\n      field(\'constructor\', choice($.primary_expression, $.new_expression)),\n      field(\'arguments\', optional(prec.dynamic(1, $.arguments))),\n    )),\n\n    await_expression: $ => prec(\'unary_void\', seq(\n      \'await\',\n      $.expression,\n    )),\n\n    member_expression: $ => prec(\'member\', seq(\n      field(\'object\', choice($.expression, $.primary_expression, $.import)),\n      choice(\'.\', field(\'optional_chain\', $.optional_chain)),\n      field(\'property\', choice(\n        $.private_property_identifier,\n        alias($.identifier, $.property_identifier))),\n    )),\n\n    subscript_expression: $ => prec.right(\'member\', seq(\n      field(\'object\', choice($.expression, $.primary_expression)),\n      optional(field(\'optional_chain\', $.optional_chain)),\n      \'[\', field(\'index\', $._expressions), \']\',\n    )),\n\n    _lhs_expression: $ => choice(\n      $.member_expression,\n      $.subscript_expression,\n      $._identifier,\n      alias($._reserved_identifier, $.identifier),\n      $._destructuring_pattern,\n    ),\n\n    assignment_expression: $ => prec.right(\'assign\', seq(\n      field(\'left\', choice($.parenthesized_expression, $._lhs_expression)),\n      \'=\',\n      field(\'right\', $.expression),\n    )),\n\n    _augmented_assignment_lhs: $ => choice(\n      $.member_expression,\n      $.subscript_expression,\n      alias($._reserved_identifier, $.identifier),\n      $.identifier,\n      $.parenthesized_expression,\n    ),\n\n    augmented_assignment_expression: $ => prec.right(\'assign\', seq(\n      field(\'left\', $._augmented_assignment_lhs),\n      field(\'operator\', choice(\'+=\', \'-=\', \'*=\', \'/=\', \'%=\', \'^=\', \'&=\', \'|=\', \'>>=\', \'>>>=\',\n        \'<<=\', \'**=\', \'&&=\', \'||=\', \'??=\')),\n      field(\'right\', $.expression),\n    )),\n\n    _initializer: $ => seq(\n      \'=\',\n      field(\'value\', $.expression),\n    ),\n\n    _destructuring_pattern: $ => choice(\n      $.object_pattern,\n      $.array_pattern,\n    ),\n\n    spread_element: $ => seq(\'...\', $.expression),\n\n    ternary_expression: $ => prec.right(\'ternary\', seq(\n      field(\'condition\', $.expression),\n      alias($._ternary_qmark, \'?\'),\n      field(\'consequence\', $.expression),\n      \':\',\n      field(\'alternative\', $.expression),\n    )),\n\n    binary_expression: $ => choice(\n      ...[\n        [\'&&\', \'logical_and\'],\n        [\'||\', \'logical_or\'],\n        [\'>>\', \'binary_shift\'],\n        [\'>>>\', \'binary_shift\'],\n        [\'<<\', \'binary_shift\'],\n        [\'&\', \'bitwise_and\'],\n        [\'^\', \'bitwise_xor\'],\n        [\'|\', \'bitwise_or\'],\n        [\'+\', \'binary_plus\'],\n        [\'-\', \'binary_plus\'],\n        [\'*\', \'binary_times\'],\n        [\'/\', \'binary_times\'],\n        [\'%\', \'binary_times\'],\n        [\'**\', \'binary_exp\', \'right\'],\n        [\'<\', \'binary_relation\'],\n        [\'<=\', \'binary_relation\'],\n        [\'==\', \'binary_equality\'],\n        [\'===\', \'binary_equality\'],\n        [\'!=\', \'binary_equality\'],\n        [\'!==\', \'binary_equality\'],\n        [\'>=\', \'binary_relation\'],\n        [\'>\', \'binary_relation\'],\n        [\'??\', \'ternary\'],\n        [\'instanceof\', \'binary_relation\'],\n        [\'in\', \'binary_relation\'],\n      ].map(([operator, precedence, associativity]) =>\n        (associativity === \'right\' ? prec.right : prec.left)(precedence, seq(\n          field(\'left\', operator === \'in\' ? choice($.expression, $.private_property_identifier) : $.expression),\n          field(\'operator\', operator),\n          field(\'right\', $.expression),\n        )),\n      ),\n    ),\n\n    unary_expression: $ => prec.left(\'unary_void\', seq(\n      field(\'operator\', choice(\'!\', \'~\', \'-\', \'+\', \'typeof\', \'void\', \'delete\')),\n      field(\'argument\', $.expression),\n    )),\n\n    update_expression: $ => prec.left(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    sequence_expression: $ => prec.right(commaSep1($.expression)),\n\n    //\n    // Primitives\n    //\n\n    string: $ => choice(\n      seq(\n        \'\"\',\n        repeat(choice(\n          alias($.unescaped_double_string_fragment, $.string_fragment),\n          $.escape_sequence,\n        )),\n        \'\"\',\n      ),\n      seq(\n        \'\\\'\',\n        repeat(choice(\n          alias($.unescaped_single_string_fragment, $.string_fragment),\n          $.escape_sequence,\n        )),\n        \'\\\'\',\n      ),\n    ),\n\n    // Workaround to https://github.com/tree-sitter/tree-sitter/issues/1156\n    // We give names to the token() constructs containing a regexp\n    // so as to obtain a node in the CST.\n    //\n    unescaped_double_string_fragment: _ => token.immediate(prec(1, /[^\"\\\\\\r\\n]+/)),\n\n    // same here\n    unescaped_single_string_fragment: _ => token.immediate(prec(1, /[^\'\\\\\\r\\n]+/)),\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        /[\\r?][\\n\\u2028\\u2029]/,\n      ),\n    )),\n\n    // http://stackoverflow.com/questions/13014947/regex-to-match-a-c-style-multiline-comment/36328890#36328890\n    comment: $ => choice(\n      token(choice(\n        seq(\'//\', /.*/),\n        seq(\n          \'/*\',\n          /[^*]*\\*+([^/*][^*]*\\*+)*/,\n          \'/\',\n        ),\n      )),\n    ),\n\n    template_string: $ => seq(\n      \'`\',\n      repeat(choice(\n        alias($._template_chars, $.string_fragment),\n        $.escape_sequence,\n        $.template_substitution,\n      )),\n      \'`\',\n    ),\n\n    template_substitution: $ => seq(\n      \'${\',\n      $._expressions,\n      \'}\',\n    ),\n\n    regex: $ => seq(\n      \'/\',\n      field(\'pattern\', $.regex_pattern),\n      token.immediate(prec(1, \'/\')),\n      optional(field(\'flags\', $.regex_flags)),\n    ),\n\n    regex_pattern: _ => token.immediate(prec(-1,\n      repeat1(choice(\n        seq(\n          \'[\',\n          repeat(choice(\n            seq(\'\\\\\', /./), // escaped character\n            /[^\\]\\n\\\\]/, // any character besides \']\' or \'\\n\'\n          )),\n          \']\',\n        ), // square-bracket-delimited character class\n        seq(\'\\\\\', /./), // escaped character\n        /[^/\\\\\\[\\n]/, // any character besides \'[\', \'\\\', \'/\', \'\\n\'\n      )),\n    )),\n\n    regex_flags: _ => token.immediate(/[a-z]+/),\n\n    number: _ => {\n      const hex_literal = seq(\n        choice(\'0x\', \'0X\'),\n        /[\\da-fA-F](_?[\\da-fA-F])*/,\n      );\n\n      const decimal_digits = /\\d(_?\\d)*/;\n      const signed_integer = seq(optional(choice(\'-\', \'+\')), decimal_digits);\n      const exponent_part = seq(choice(\'e\', \'E\'), signed_integer);\n\n      const binary_literal = seq(choice(\'0b\', \'0B\'), /[0-1](_?[0-1])*/);\n\n      const octal_literal = seq(choice(\'0o\', \'0O\'), /[0-7](_?[0-7])*/);\n\n      const bigint_literal = seq(choice(hex_literal, binary_literal, octal_literal, decimal_digits), \'n\');\n\n      const decimal_integer_literal = choice(\n        \'0\',\n        seq(optional(\'0\'), /[1-9]/, optional(seq(optional(\'_\'), decimal_digits))),\n      );\n\n      const decimal_literal = choice(\n        seq(decimal_integer_literal, \'.\', optional(decimal_digits), optional(exponent_part)),\n        seq(\'.\', decimal_digits, optional(exponent_part)),\n        seq(decimal_integer_literal, exponent_part),\n        seq(decimal_digits),\n      );\n\n      return token(choice(\n        hex_literal,\n        decimal_literal,\n        binary_literal,\n        octal_literal,\n        bigint_literal,\n      ));\n    },\n\n    // \'undefined\' is syntactically a regular identifier in JavaScript.\n    // However, its main use is as the read-only global variable whose\n    // value is [undefined], for which there\'s no literal representation\n    // unlike \'null\'. We gave it its own rule so it\'s easy to\n    // highlight in text editors and other applications.\n    _identifier: $ => choice(\n      $.undefined,\n      $.identifier,\n    ),\n\n    identifier: _ => {\n      // eslint-disable-next-line max-len\n      const alpha = /[^\\x00-\\x1F\\s\\p{Zs}0-9:;`\"\'@#.,|^&<=>+\\-*/\\\\%?!~()\\[\\]{}\\uFEFF\\u2060\\u200B]|\\\\u[0-9a-fA-F]{4}|\\\\u\\{[0-9a-fA-F]+\\}/;\n      // eslint-disable-next-line max-len\n      const alphanumeric = /[^\\x00-\\x1F\\s\\p{Zs}:;`\"\'@#.,|^&<=>+\\-*/\\\\%?!~()\\[\\]{}\\uFEFF\\u2060\\u200B]|\\\\u[0-9a-fA-F]{4}|\\\\u\\{[0-9a-fA-F]+\\}/;\n      return token(seq(alpha, repeat(alphanumeric)));\n    },\n\n    private_property_identifier: _ => {\n      // eslint-disable-next-line max-len\n      const alpha = /[^\\x00-\\x1F\\s\\p{Zs}0-9:;`\"\'@#.,|^&<=>+\\-*/\\\\%?!~()\\[\\]{}\\uFEFF\\u2060\\u200B]|\\\\u[0-9a-fA-F]{4}|\\\\u\\{[0-9a-fA-F]+\\}/;\n      // eslint-disable-next-line max-len\n      const alphanumeric = /[^\\x00-\\x1F\\s\\p{Zs}:;`\"\'@#.,|^&<=>+\\-*/\\\\%?!~()\\[\\]{}\\uFEFF\\u2060\\u200B]|\\\\u[0-9a-fA-F]{4}|\\\\u\\{[0-9a-fA-F]+\\}/;\n      return token(seq(\'#\', alpha, repeat(alphanumeric)));\n    },\n\n    meta_property: _ => seq(\'new\', \'.\', \'target\'),\n\n    this: _ => \'this\',\n    super: _ => \'super\',\n    true: _ => \'true\',\n    false: _ => \'false\',\n    null: _ => \'null\',\n    undefined: _ => \'undefined\',\n\n    //\n    // Expression components\n    //\n\n    arguments: $ => seq(\n      \'(\',\n      commaSep(optional(choice($.expression, $.spread_element))),\n      \')\',\n    ),\n\n    decorator: $ => seq(\n      \'@\',\n      choice(\n        $.identifier,\n        alias($.decorator_member_expression, $.member_expression),\n        alias($.decorator_call_expression, $.call_expression),\n      ),\n    ),\n\n    decorator_member_expression: $ => prec(\'member\', seq(\n      field(\'object\', choice(\n        $.identifier,\n        alias($.decorator_member_expression, $.member_expression),\n      )),\n      \'.\',\n      field(\'property\', alias($.identifier, $.property_identifier)),\n    )),\n\n    decorator_call_expression: $ => prec(\'call\', seq(\n      field(\'function\', choice(\n        $.identifier,\n        alias($.decorator_member_expression, $.member_expression),\n      )),\n      field(\'arguments\', $.arguments),\n    )),\n\n    class_body: $ => seq(\n      \'{\',\n      repeat(choice(\n        seq(field(\'member\', $.method_definition), optional(\';\')),\n        seq(field(\'member\', $.field_definition), $._semicolon),\n        field(\'member\', $.class_static_block),\n        field(\'template\', $.glimmer_template),\n        \';\',\n      )),\n      \'}\',\n    ),\n\n    field_definition: $ => seq(\n      repeat(field(\'decorator\', $.decorator)),\n      optional(\'static\'),\n      field(\'property\', $._property_name),\n      optional($._initializer),\n    ),\n\n    formal_parameters: $ => seq(\n      \'(\',\n      optional(seq(\n        commaSep1($._formal_parameter),\n        optional(\',\'),\n      )),\n      \')\',\n    ),\n\n    class_static_block: $ => seq(\n      \'static\',\n      field(\'body\', $.statement_block),\n    ),\n\n    // This negative dynamic precedence ensures that during error recovery,\n    // unfinished constructs are generally treated as literal expressions,\n    // not patterns.\n    pattern: $ => prec.dynamic(-1, choice(\n      $._lhs_expression,\n      $.rest_pattern,\n    )),\n\n    rest_pattern: $ => prec.right(seq(\n      \'...\',\n      $._lhs_expression,\n    )),\n\n    method_definition: $ => seq(\n      repeat(field(\'decorator\', $.decorator)),\n      optional(choice(\'static\', alias(token(seq(\'static\', /\\s+/, \'get\', /\\s*\\n/)), \'static get\'))),\n      optional(\'async\'),\n      optional(choice(\'get\', \'set\', \'*\')),\n      field(\'name\', $._property_name),\n      field(\'parameters\', $.formal_parameters),\n      field(\'body\', $.statement_block),\n    ),\n\n    pair: $ => seq(\n      field(\'key\', $._property_name),\n      \':\',\n      field(\'value\', $.expression),\n    ),\n\n    pair_pattern: $ => seq(\n      field(\'key\', $._property_name),\n      \':\',\n      field(\'value\', choice($.pattern, $.assignment_pattern)),\n    ),\n\n    _property_name: $ => choice(\n      alias(choice(\n        $.identifier,\n        $._reserved_identifier,\n      ), $.property_identifier),\n      $.private_property_identifier,\n      $.string,\n      $.number,\n      $.computed_property_name,\n    ),\n\n    computed_property_name: $ => seq(\n      \'[\',\n      $.expression,\n      \']\',\n    ),\n\n    _reserved_identifier: _ => choice(\n      \'get\',\n      \'set\',\n      \'async\',\n      \'static\',\n      \'export\',\n      \'let\',\n    ),\n\n    _semicolon: $ => choice($._automatic_semicolon, \';\'),\n  },\n});\n\n/**\n * Creates a rule to match one or more of the rules separated by a comma\n *\n * @param {Rule} rule\n *\n * @return {SeqRule}\n *\n */\nfunction commaSep1(rule) {\n  return seq(rule, repeat(seq(\',\', rule)));\n}\n\n/**\n * Creates a rule to optionally match one or more of the rules separated by a comma\n *\n * @param {Rule} rule\n *\n * @return {ChoiceRule}\n *\n */\nfunction commaSep(rule) {\n  return optional(commaSep1(rule));\n}\n";
Expand description

The source of the JavaScript tree-sitter grammar description.