GRAMMAR

Constant GRAMMAR 

Source
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