pub const GRAMMAR: &str = "/**\n * @file Python grammar for tree-sitter\n * @author Max Brunsfeld <maxbrunsfeld@gmail.com>\n * @license MIT\n * @see {@link https://docs.python.org/2/reference/grammar.html|Python 2 grammar}\n * @see {@link https://docs.python.org/3/reference/grammar.html|Python 3 grammar}\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\nconst PREC = {\n // this resolves a conflict between the usage of \':\' in a lambda vs in a\n // typed parameter. In the case of a lambda, we don\'t allow typed parameters.\n lambda: -2,\n typed_parameter: -1,\n conditional: -1,\n\n parenthesized_expression: 1,\n parenthesized_list_splat: 1,\n or: 10,\n and: 11,\n not: 12,\n compare: 13,\n bitwise_or: 14,\n bitwise_and: 15,\n xor: 16,\n shift: 17,\n plus: 18,\n times: 19,\n unary: 20,\n power: 21,\n call: 22,\n};\n\nconst SEMICOLON = \';\';\n\nmodule.exports = grammar({\n name: \'python\',\n\n extras: $ => [\n $.comment,\n /[\\s\\f\\uFEFF\\u2060\\u200B]|\\r?\\n/,\n $.line_continuation,\n ],\n\n conflicts: $ => [\n [$.primary_expression, $.pattern],\n [$.primary_expression, $.list_splat_pattern],\n [$.tuple, $.tuple_pattern],\n [$.list, $.list_pattern],\n [$.with_item, $._collection_elements],\n [$.named_expression, $.as_pattern],\n [$.print_statement, $.primary_expression],\n [$.type_alias_statement, $.primary_expression],\n ],\n\n supertypes: $ => [\n $._simple_statement,\n $._compound_statement,\n $.expression,\n $.primary_expression,\n $.pattern,\n $.parameter,\n ],\n\n externals: $ => [\n $._newline,\n $._indent,\n $._dedent,\n $.string_start,\n $._string_content,\n $.escape_interpolation,\n $.string_end,\n\n // Mark comments as external tokens so that the external scanner is always\n // invoked, even if no external token is expected. This allows for better\n // error recovery, because the external scanner can maintain the overall\n // structure by returning dedent tokens whenever a dedent occurs, even\n // if no dedent is expected.\n $.comment,\n\n // Allow the external scanner to check for the validity of closing brackets\n // so that it can avoid returning dedent tokens between brackets.\n \']\',\n \')\',\n \'}\',\n \'except\',\n ],\n\n inline: $ => [\n $._simple_statement,\n $._compound_statement,\n $._suite,\n $._expressions,\n $._left_hand_side,\n $.keyword_identifier,\n ],\n\n word: $ => $.identifier,\n\n rules: {\n module: $ => repeat($._statement),\n\n _statement: $ => choice(\n $._simple_statements,\n $._compound_statement,\n ),\n\n // Simple statements\n\n _simple_statements: $ => seq(\n sep1($._simple_statement, SEMICOLON),\n optional(SEMICOLON),\n $._newline,\n ),\n\n _simple_statement: $ => choice(\n $.future_import_statement,\n $.import_statement,\n $.import_from_statement,\n $.print_statement,\n $.assert_statement,\n $.expression_statement,\n $.return_statement,\n $.delete_statement,\n $.raise_statement,\n $.pass_statement,\n $.break_statement,\n $.continue_statement,\n $.global_statement,\n $.nonlocal_statement,\n $.exec_statement,\n $.type_alias_statement,\n ),\n\n import_statement: $ => seq(\n \'import\',\n $._import_list,\n ),\n\n import_prefix: _ => repeat1(\'.\'),\n\n relative_import: $ => seq(\n $.import_prefix,\n optional($.dotted_name),\n ),\n\n future_import_statement: $ => seq(\n \'from\',\n \'__future__\',\n \'import\',\n choice(\n $._import_list,\n seq(\'(\', $._import_list, \')\'),\n ),\n ),\n\n import_from_statement: $ => seq(\n \'from\',\n field(\'module_name\', choice(\n $.relative_import,\n $.dotted_name,\n )),\n \'import\',\n choice(\n $.wildcard_import,\n $._import_list,\n seq(\'(\', $._import_list, \')\'),\n ),\n ),\n\n _import_list: $ => seq(\n commaSep1(field(\'name\', choice(\n $.dotted_name,\n $.aliased_import,\n ))),\n optional(\',\'),\n ),\n\n aliased_import: $ => seq(\n field(\'name\', $.dotted_name),\n \'as\',\n field(\'alias\', $.identifier),\n ),\n\n wildcard_import: _ => \'*\',\n\n print_statement: $ => choice(\n prec(1, seq(\n \'print\',\n $.chevron,\n repeat(seq(\',\', field(\'argument\', $.expression))),\n optional(\',\')),\n ),\n prec(-3, prec.dynamic(-1, seq(\n \'print\',\n commaSep1(field(\'argument\', $.expression)),\n optional(\',\'),\n ))),\n ),\n\n chevron: $ => seq(\n \'>>\',\n $.expression,\n ),\n\n assert_statement: $ => seq(\n \'assert\',\n commaSep1($.expression),\n ),\n\n expression_statement: $ => choice(\n $.expression,\n seq(commaSep1($.expression), optional(\',\')),\n $.assignment,\n $.augmented_assignment,\n $.yield,\n ),\n\n named_expression: $ => seq(\n field(\'name\', $._named_expression_lhs),\n \':=\',\n field(\'value\', $.expression),\n ),\n\n _named_expression_lhs: $ => choice(\n $.identifier,\n $.keyword_identifier,\n ),\n\n return_statement: $ => seq(\n \'return\',\n optional($._expressions),\n ),\n\n delete_statement: $ => seq(\n \'del\',\n $._expressions,\n ),\n\n _expressions: $ => choice(\n $.expression,\n $.expression_list,\n ),\n\n raise_statement: $ => seq(\n \'raise\',\n optional($._expressions),\n optional(seq(\'from\', field(\'cause\', $.expression))),\n ),\n\n pass_statement: _ => prec.left(\'pass\'),\n break_statement: _ => prec.left(\'break\'),\n continue_statement: _ => prec.left(\'continue\'),\n\n // Compound statements\n\n _compound_statement: $ => choice(\n $.if_statement,\n $.for_statement,\n $.while_statement,\n $.try_statement,\n $.with_statement,\n $.function_definition,\n $.class_definition,\n $.decorated_definition,\n $.match_statement,\n ),\n\n if_statement: $ => seq(\n \'if\',\n field(\'condition\', $.expression),\n \':\',\n field(\'consequence\', $._suite),\n repeat(field(\'alternative\', $.elif_clause)),\n optional(field(\'alternative\', $.else_clause)),\n ),\n\n elif_clause: $ => seq(\n \'elif\',\n field(\'condition\', $.expression),\n \':\',\n field(\'consequence\', $._suite),\n ),\n\n else_clause: $ => seq(\n \'else\',\n \':\',\n field(\'body\', $._suite),\n ),\n\n match_statement: $ => seq(\n \'match\',\n commaSep1(field(\'subject\', $.expression)),\n optional(\',\'),\n \':\',\n field(\'body\', alias($._match_block, $.block)),\n ),\n\n _match_block: $ => choice(\n seq(\n $._indent,\n repeat(field(\'alternative\', $.case_clause)),\n $._dedent,\n ),\n $._newline,\n ),\n\n case_clause: $ => seq(\n \'case\',\n commaSep1($.case_pattern),\n optional(\',\'),\n optional(field(\'guard\', $.if_clause)),\n \':\',\n field(\'consequence\', $._suite),\n ),\n\n for_statement: $ => seq(\n optional(\'async\'),\n \'for\',\n field(\'left\', $._left_hand_side),\n \'in\',\n field(\'right\', $._expressions),\n \':\',\n field(\'body\', $._suite),\n field(\'alternative\', optional($.else_clause)),\n ),\n\n while_statement: $ => seq(\n \'while\',\n field(\'condition\', $.expression),\n \':\',\n field(\'body\', $._suite),\n optional(field(\'alternative\', $.else_clause)),\n ),\n\n try_statement: $ => seq(\n \'try\',\n \':\',\n field(\'body\', $._suite),\n choice(\n seq(\n repeat1($.except_clause),\n optional($.else_clause),\n optional($.finally_clause),\n ),\n seq(\n repeat1($.except_group_clause),\n optional($.else_clause),\n optional($.finally_clause),\n ),\n $.finally_clause,\n ),\n ),\n\n except_clause: $ => seq(\n \'except\',\n optional(seq(\n $.expression,\n optional(seq(\n choice(\'as\', \',\'),\n $.expression,\n )),\n )),\n \':\',\n $._suite,\n ),\n\n except_group_clause: $ => seq(\n \'except*\',\n seq(\n $.expression,\n optional(seq(\n \'as\',\n $.expression,\n )),\n ),\n \':\',\n $._suite,\n ),\n\n finally_clause: $ => seq(\n \'finally\',\n \':\',\n $._suite,\n ),\n\n with_statement: $ => seq(\n optional(\'async\'),\n \'with\',\n $.with_clause,\n \':\',\n field(\'body\', $._suite),\n ),\n\n with_clause: $ => choice(\n seq(commaSep1($.with_item), optional(\',\')),\n seq(\'(\', commaSep1($.with_item), optional(\',\'), \')\'),\n ),\n\n with_item: $ => prec.dynamic(1, seq(\n field(\'value\', $.expression),\n )),\n\n function_definition: $ => seq(\n optional(\'async\'),\n \'def\',\n field(\'name\', $.identifier),\n field(\'type_parameters\', optional($.type_parameter)),\n field(\'parameters\', $.parameters),\n optional(\n seq(\n \'->\',\n field(\'return_type\', $.type),\n ),\n ),\n \':\',\n field(\'body\', $._suite),\n ),\n\n parameters: $ => seq(\n \'(\',\n optional($._parameters),\n \')\',\n ),\n\n lambda_parameters: $ => $._parameters,\n\n list_splat: $ => seq(\n \'*\',\n $.expression,\n ),\n\n dictionary_splat: $ => seq(\n \'**\',\n $.expression,\n ),\n\n global_statement: $ => seq(\n \'global\',\n commaSep1($.identifier),\n ),\n\n nonlocal_statement: $ => seq(\n \'nonlocal\',\n commaSep1($.identifier),\n ),\n\n exec_statement: $ => seq(\n \'exec\',\n field(\'code\', choice($.string, $.identifier)),\n optional(\n seq(\n \'in\',\n commaSep1($.expression),\n ),\n ),\n ),\n\n type_alias_statement: $ => prec.dynamic(1, seq(\n \'type\',\n $.type,\n \'=\',\n $.type,\n )),\n\n class_definition: $ => seq(\n \'class\',\n field(\'name\', $.identifier),\n field(\'type_parameters\', optional($.type_parameter)),\n field(\'superclasses\', optional($.argument_list)),\n \':\',\n field(\'body\', $._suite),\n ),\n type_parameter: $ => seq(\n \'[\',\n commaSep1($.type),\n \']\',\n ),\n\n parenthesized_list_splat: $ => prec(PREC.parenthesized_list_splat, seq(\n \'(\',\n choice(\n alias($.parenthesized_list_splat, $.parenthesized_expression),\n $.list_splat,\n ),\n \')\',\n )),\n\n argument_list: $ => seq(\n \'(\',\n optional(commaSep1(\n choice(\n $.expression,\n $.list_splat,\n $.dictionary_splat,\n alias($.parenthesized_list_splat, $.parenthesized_expression),\n $.keyword_argument,\n ),\n )),\n optional(\',\'),\n \')\',\n ),\n\n decorated_definition: $ => seq(\n repeat1($.decorator),\n field(\'definition\', choice(\n $.class_definition,\n $.function_definition,\n )),\n ),\n\n decorator: $ => seq(\n \'@\',\n $.expression,\n $._newline,\n ),\n\n _suite: $ => choice(\n alias($._simple_statements, $.block),\n seq($._indent, $.block),\n alias($._newline, $.block),\n ),\n\n block: $ => seq(\n repeat($._statement),\n $._dedent,\n ),\n\n expression_list: $ => prec.right(seq(\n $.expression,\n choice(\n \',\',\n seq(\n repeat1(seq(\n \',\',\n $.expression,\n )),\n optional(\',\'),\n ),\n ),\n )),\n\n dotted_name: $ => prec(1, sep1($.identifier, \'.\')),\n\n // Match cases\n\n case_pattern: $ => prec(1, choice(\n alias($._as_pattern, $.as_pattern),\n $.keyword_pattern,\n $._simple_pattern,\n )),\n\n _simple_pattern: $ => prec(1, choice(\n $.class_pattern,\n $.splat_pattern,\n $.union_pattern,\n alias($._list_pattern, $.list_pattern),\n alias($._tuple_pattern, $.tuple_pattern),\n $.dict_pattern,\n $.string,\n $.concatenated_string,\n $.true,\n $.false,\n $.none,\n seq(optional(\'-\'), choice($.integer, $.float)),\n $.complex_pattern,\n $.dotted_name,\n \'_\',\n )),\n\n _as_pattern: $ => seq($.case_pattern, \'as\', $.identifier),\n\n union_pattern: $ => prec.right(seq($._simple_pattern, repeat1(prec.left(seq(\'|\', $._simple_pattern))))),\n\n _list_pattern: $ => seq(\n \'[\',\n optional(seq(\n commaSep1($.case_pattern),\n optional(\',\'),\n )),\n \']\',\n ),\n\n _tuple_pattern: $ => seq(\n \'(\',\n optional(seq(\n commaSep1($.case_pattern),\n optional(\',\'),\n )),\n \')\',\n ),\n\n dict_pattern: $ => seq(\n \'{\',\n optional(seq(\n commaSep1(choice($._key_value_pattern, $.splat_pattern)),\n optional(\',\'),\n )),\n \'}\',\n ),\n\n _key_value_pattern: $ => seq(\n field(\'key\', $._simple_pattern),\n \':\',\n field(\'value\', $.case_pattern),\n ),\n\n keyword_pattern: $ => seq($.identifier, \'=\', $._simple_pattern),\n\n splat_pattern: $ => prec(1, seq(choice(\'*\', \'**\'), choice($.identifier, \'_\'))),\n\n class_pattern: $ => seq(\n $.dotted_name,\n \'(\',\n optional(seq(\n commaSep1($.case_pattern),\n optional(\',\'),\n )),\n \')\',\n ),\n\n complex_pattern: $ => prec(1, seq(\n optional(\'-\'),\n choice($.integer, $.float),\n choice(\'+\', \'-\'),\n choice($.integer, $.float),\n )),\n\n // Patterns\n\n _parameters: $ => seq(\n commaSep1($.parameter),\n optional(\',\'),\n ),\n\n _patterns: $ => seq(\n commaSep1($.pattern),\n optional(\',\'),\n ),\n\n parameter: $ => choice(\n $.identifier,\n $.typed_parameter,\n $.default_parameter,\n $.typed_default_parameter,\n $.list_splat_pattern,\n $.tuple_pattern,\n $.keyword_separator,\n $.positional_separator,\n $.dictionary_splat_pattern,\n ),\n\n pattern: $ => choice(\n $.identifier,\n $.keyword_identifier,\n $.subscript,\n $.attribute,\n $.list_splat_pattern,\n $.tuple_pattern,\n $.list_pattern,\n ),\n\n tuple_pattern: $ => seq(\n \'(\',\n optional($._patterns),\n \')\',\n ),\n\n list_pattern: $ => seq(\n \'[\',\n optional($._patterns),\n \']\',\n ),\n\n default_parameter: $ => seq(\n field(\'name\', choice($.identifier, $.tuple_pattern)),\n \'=\',\n field(\'value\', $.expression),\n ),\n\n typed_default_parameter: $ => prec(PREC.typed_parameter, seq(\n field(\'name\', $.identifier),\n \':\',\n field(\'type\', $.type),\n \'=\',\n field(\'value\', $.expression),\n )),\n\n list_splat_pattern: $ => seq(\n \'*\',\n choice($.identifier, $.keyword_identifier, $.subscript, $.attribute),\n ),\n\n dictionary_splat_pattern: $ => seq(\n \'**\',\n choice($.identifier, $.keyword_identifier, $.subscript, $.attribute),\n ),\n\n // Extended patterns (patterns allowed in match statement are far more flexible than simple patterns though still a subset of \"expression\")\n\n as_pattern: $ => prec.left(seq(\n $.expression,\n \'as\',\n field(\'alias\', alias($.expression, $.as_pattern_target)),\n )),\n\n // Expressions\n\n _expression_within_for_in_clause: $ => choice(\n $.expression,\n alias($.lambda_within_for_in_clause, $.lambda),\n ),\n\n expression: $ => choice(\n $.comparison_operator,\n $.not_operator,\n $.boolean_operator,\n $.lambda,\n $.primary_expression,\n $.conditional_expression,\n $.named_expression,\n $.as_pattern,\n ),\n\n primary_expression: $ => choice(\n $.await,\n $.binary_operator,\n $.identifier,\n $.keyword_identifier,\n $.string,\n $.concatenated_string,\n $.integer,\n $.float,\n $.true,\n $.false,\n $.none,\n $.unary_operator,\n $.attribute,\n $.subscript,\n $.call,\n $.list,\n $.list_comprehension,\n $.dictionary,\n $.dictionary_comprehension,\n $.set,\n $.set_comprehension,\n $.tuple,\n $.parenthesized_expression,\n $.generator_expression,\n $.ellipsis,\n alias($.list_splat_pattern, $.list_splat),\n ),\n\n not_operator: $ => prec(PREC.not, seq(\n \'not\',\n field(\'argument\', $.expression),\n )),\n\n boolean_operator: $ => choice(\n prec.left(PREC.and, seq(\n field(\'left\', $.expression),\n field(\'operator\', \'and\'),\n field(\'right\', $.expression),\n )),\n prec.left(PREC.or, seq(\n field(\'left\', $.expression),\n field(\'operator\', \'or\'),\n field(\'right\', $.expression),\n )),\n ),\n\n binary_operator: $ => {\n const table = [\n [prec.left, \'+\', PREC.plus],\n [prec.left, \'-\', PREC.plus],\n [prec.left, \'*\', PREC.times],\n [prec.left, \'@\', PREC.times],\n [prec.left, \'/\', PREC.times],\n [prec.left, \'%\', PREC.times],\n [prec.left, \'//\', PREC.times],\n [prec.right, \'**\', PREC.power],\n [prec.left, \'|\', PREC.bitwise_or],\n [prec.left, \'&\', PREC.bitwise_and],\n [prec.left, \'^\', PREC.xor],\n [prec.left, \'<<\', PREC.shift],\n [prec.left, \'>>\', PREC.shift],\n ];\n\n // @ts-ignore\n return choice(...table.map(([fn, operator, precedence]) => fn(precedence, seq(\n field(\'left\', $.primary_expression),\n // @ts-ignore\n field(\'operator\', operator),\n field(\'right\', $.primary_expression),\n ))));\n },\n\n unary_operator: $ => prec(PREC.unary, seq(\n field(\'operator\', choice(\'+\', \'-\', \'~\')),\n field(\'argument\', $.primary_expression),\n )),\n\n comparison_operator: $ => prec.left(PREC.compare, seq(\n $.primary_expression,\n repeat1(seq(\n field(\'operators\',\n choice(\n \'<\',\n \'<=\',\n \'==\',\n \'!=\',\n \'>=\',\n \'>\',\n \'<>\',\n \'in\',\n alias(seq(\'not\', \'in\'), \'not in\'),\n \'is\',\n alias(seq(\'is\', \'not\'), \'is not\'),\n )),\n $.primary_expression,\n )),\n )),\n\n lambda: $ => prec(PREC.lambda, seq(\n \'lambda\',\n field(\'parameters\', optional($.lambda_parameters)),\n \':\',\n field(\'body\', $.expression),\n )),\n\n lambda_within_for_in_clause: $ => seq(\n \'lambda\',\n field(\'parameters\', optional($.lambda_parameters)),\n \':\',\n field(\'body\', $._expression_within_for_in_clause),\n ),\n\n assignment: $ => seq(\n field(\'left\', $._left_hand_side),\n choice(\n seq(\'=\', field(\'right\', $._right_hand_side)),\n seq(\':\', field(\'type\', $.type)),\n seq(\':\', field(\'type\', $.type), \'=\', field(\'right\', $._right_hand_side)),\n ),\n ),\n\n augmented_assignment: $ => seq(\n field(\'left\', $._left_hand_side),\n field(\'operator\', choice(\n \'+=\', \'-=\', \'*=\', \'/=\', \'@=\', \'//=\', \'%=\', \'**=\',\n \'>>=\', \'<<=\', \'&=\', \'^=\', \'|=\',\n )),\n field(\'right\', $._right_hand_side),\n ),\n\n _left_hand_side: $ => choice(\n $.pattern,\n $.pattern_list,\n ),\n\n pattern_list: $ => seq(\n $.pattern,\n choice(\n \',\',\n seq(\n repeat1(seq(\n \',\',\n $.pattern,\n )),\n optional(\',\'),\n ),\n ),\n ),\n\n _right_hand_side: $ => choice(\n $.expression,\n $.expression_list,\n $.assignment,\n $.augmented_assignment,\n $.pattern_list,\n $.yield,\n ),\n\n yield: $ => prec.right(seq(\n \'yield\',\n choice(\n seq(\n \'from\',\n $.expression,\n ),\n optional($._expressions),\n ),\n )),\n\n attribute: $ => prec(PREC.call, seq(\n field(\'object\', $.primary_expression),\n \'.\',\n field(\'attribute\', $.identifier),\n )),\n\n subscript: $ => prec(PREC.call, seq(\n field(\'value\', $.primary_expression),\n \'[\',\n commaSep1(field(\'subscript\', choice($.expression, $.slice))),\n optional(\',\'),\n \']\',\n )),\n\n slice: $ => seq(\n optional($.expression),\n \':\',\n optional($.expression),\n optional(seq(\':\', optional($.expression))),\n ),\n\n ellipsis: _ => \'...\',\n\n call: $ => prec(PREC.call, seq(\n field(\'function\', $.primary_expression),\n field(\'arguments\', choice(\n $.generator_expression,\n $.argument_list,\n )),\n )),\n\n typed_parameter: $ => prec(PREC.typed_parameter, seq(\n choice(\n $.identifier,\n $.list_splat_pattern,\n $.dictionary_splat_pattern,\n ),\n \':\',\n field(\'type\', $.type),\n )),\n\n type: $ => choice(\n $.expression,\n $.splat_type,\n $.generic_type,\n $.union_type,\n $.constrained_type,\n $.member_type,\n ),\n splat_type: $ => prec(1, seq(choice(\'*\', \'**\'), $.identifier)),\n generic_type: $ => prec(1, seq($.identifier, $.type_parameter)),\n union_type: $ => prec.left(seq($.type, \'|\', $.type)),\n constrained_type: $ => prec.right(seq($.type, \':\', $.type)),\n member_type: $ => seq($.type, \'.\', $.identifier),\n\n keyword_argument: $ => seq(\n field(\'name\', choice($.identifier, $.keyword_identifier)),\n \'=\',\n field(\'value\', $.expression),\n ),\n\n // Literals\n\n list: $ => seq(\n \'[\',\n optional($._collection_elements),\n \']\',\n ),\n\n set: $ => seq(\n \'{\',\n $._collection_elements,\n \'}\',\n ),\n\n tuple: $ => seq(\n \'(\',\n optional($._collection_elements),\n \')\',\n ),\n\n dictionary: $ => seq(\n \'{\',\n optional(commaSep1(choice($.pair, $.dictionary_splat))),\n optional(\',\'),\n \'}\',\n ),\n\n pair: $ => seq(\n field(\'key\', $.expression),\n \':\',\n field(\'value\', $.expression),\n ),\n\n list_comprehension: $ => seq(\n \'[\',\n field(\'body\', $.expression),\n $._comprehension_clauses,\n \']\',\n ),\n\n dictionary_comprehension: $ => seq(\n \'{\',\n field(\'body\', $.pair),\n $._comprehension_clauses,\n \'}\',\n ),\n\n set_comprehension: $ => seq(\n \'{\',\n field(\'body\', $.expression),\n $._comprehension_clauses,\n \'}\',\n ),\n\n generator_expression: $ => seq(\n \'(\',\n field(\'body\', $.expression),\n $._comprehension_clauses,\n \')\',\n ),\n\n _comprehension_clauses: $ => seq(\n $.for_in_clause,\n repeat(choice(\n $.for_in_clause,\n $.if_clause,\n )),\n ),\n\n parenthesized_expression: $ => prec(PREC.parenthesized_expression, seq(\n \'(\',\n choice($.expression, $.yield),\n \')\',\n )),\n\n _collection_elements: $ => seq(\n commaSep1(choice(\n $.expression, $.yield, $.list_splat, $.parenthesized_list_splat,\n )),\n optional(\',\'),\n ),\n\n for_in_clause: $ => prec.left(seq(\n optional(\'async\'),\n \'for\',\n field(\'left\', $._left_hand_side),\n \'in\',\n field(\'right\', commaSep1($._expression_within_for_in_clause)),\n optional(\',\'),\n )),\n\n if_clause: $ => seq(\n \'if\',\n $.expression,\n ),\n\n conditional_expression: $ => prec.right(PREC.conditional, seq(\n $.expression,\n \'if\',\n $.expression,\n \'else\',\n $.expression,\n )),\n\n concatenated_string: $ => seq(\n $.string,\n repeat1($.string),\n ),\n\n string: $ => seq(\n $.string_start,\n repeat(choice($.interpolation, $.string_content)),\n $.string_end,\n ),\n\n string_content: $ => prec.right(repeat1(\n choice(\n $.escape_interpolation,\n $.escape_sequence,\n $._not_escape_sequence,\n $._string_content,\n ))),\n\n interpolation: $ => seq(\n \'{\',\n field(\'expression\', $._f_expression),\n optional(\'=\'),\n optional(field(\'type_conversion\', $.type_conversion)),\n optional(field(\'format_specifier\', $.format_specifier)),\n \'}\',\n ),\n\n _f_expression: $ => choice(\n $.expression,\n $.expression_list,\n $.pattern_list,\n $.yield,\n ),\n\n escape_sequence: _ => token.immediate(prec(1, seq(\n \'\\\\\',\n choice(\n /u[a-fA-F\\d]{4}/,\n /U[a-fA-F\\d]{8}/,\n /x[a-fA-F\\d]{2}/,\n /\\d{3}/,\n /\\r?\\n/,\n /[\'\"abfrntv\\\\]/,\n /N\\{[^}]+\\}/,\n ),\n ))),\n\n _not_escape_sequence: _ => token.immediate(\'\\\\\'),\n\n format_specifier: $ => seq(\n \':\',\n repeat(choice(\n token(prec(1, /[^{}\\n]+/)),\n alias($.interpolation, $.format_expression),\n )),\n ),\n\n type_conversion: _ => /![a-z]/,\n\n integer: _ => token(choice(\n seq(\n choice(\'0x\', \'0X\'),\n repeat1(/_?[A-Fa-f0-9]+/),\n optional(/[Ll]/),\n ),\n seq(\n choice(\'0o\', \'0O\'),\n repeat1(/_?[0-7]+/),\n optional(/[Ll]/),\n ),\n seq(\n choice(\'0b\', \'0B\'),\n repeat1(/_?[0-1]+/),\n optional(/[Ll]/),\n ),\n seq(\n repeat1(/[0-9]+_?/),\n choice(\n optional(/[Ll]/), // long numbers\n optional(/[jJ]/), // complex numbers\n ),\n ),\n )),\n\n float: _ => {\n const digits = repeat1(/[0-9]+_?/);\n const exponent = seq(/[eE][\\+-]?/, digits);\n\n return token(seq(\n choice(\n seq(digits, \'.\', optional(digits), optional(exponent)),\n seq(optional(digits), \'.\', digits, optional(exponent)),\n seq(digits, exponent),\n ),\n optional(choice(/[Ll]/, /[jJ]/)),\n ));\n },\n\n identifier: _ => /[_\\p{XID_Start}][_\\p{XID_Continue}]*/,\n\n keyword_identifier: $ => choice(\n prec(-3, alias(\n choice(\n \'print\',\n \'exec\',\n \'async\',\n \'await\',\n \'match\',\n ),\n $.identifier,\n )),\n alias(\'type\', $.identifier),\n ),\n\n true: _ => \'True\',\n false: _ => \'False\',\n none: _ => \'None\',\n\n await: $ => prec(PREC.unary, seq(\n \'await\',\n $.primary_expression,\n )),\n\n comment: _ => token(seq(\'#\', /.*/)),\n\n line_continuation: _ => token(seq(\'\\\\\', choice(seq(optional(\'\\r\'), \'\\n\'), \'\\0\'))),\n\n positional_separator: _ => \'/\',\n keyword_separator: _ => \'*\',\n },\n});\n\nmodule.exports.PREC = PREC;\n\n/**\n * Creates a rule to match one or more of the rules separated by a comma\n *\n * @param {RuleOrLiteral} rule\n *\n * @return {SeqRule}\n *\n */\nfunction commaSep1(rule) {\n return sep1(rule, \',\');\n}\n\n/**\n * Creates a rule to match one or more occurrences of `rule` separated by `sep`\n *\n * @param {RuleOrLiteral} rule\n *\n * @param {RuleOrLiteral} separator\n *\n * @return {SeqRule}\n *\n */\nfunction sep1(rule, separator) {\n return seq(rule, repeat(seq(separator, rule)));\n}\n";Expand description
GRAMMAR