Constant tree_sitter_javascript::GRAMMAR
source · 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.