Constant tree_sitter_cpp::GRAMMAR

source ·
pub const GRAMMAR: &str = "/**\n * @file C++ grammar for tree-sitter\n * @author Max Brunsfeld\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\nconst C = require(\'tree-sitter-c/grammar\');\n\nconst PREC = Object.assign(C.PREC, {\n  LAMBDA: 18,\n  NEW: C.PREC.CALL + 1,\n  STRUCTURED_BINDING: -1,\n  THREE_WAY: C.PREC.RELATIONAL + 1,\n});\n\nconst FOLD_OPERATORS = [\n  \'+\', \'-\', \'*\', \'/\', \'%\',\n  \'^\', \'&\', \'|\',\n  \'=\', \'<\', \'>\',\n  \'<<\', \'>>\',\n  \'+=\', \'-=\', \'*=\', \'/=\', \'%=\', \'^=\', \'&=\', \'|=\',\n  \'>>=\', \'<<=\',\n  \'==\', \'!=\', \'<=\', \'>=\',\n  \'&&\', \'||\',\n  \',\',\n  \'.*\', \'->*\',\n  \'or\', \'and\', \'bitor\', \'xor\', \'bitand\', \'not_eq\',\n];\n\nconst ASSIGNMENT_OPERATORS = [\n  \'=\',\n  \'*=\',\n  \'/=\',\n  \'%=\',\n  \'+=\',\n  \'-=\',\n  \'<<=\',\n  \'>>=\',\n  \'&=\',\n  \'^=\',\n  \'|=\',\n  \'and_eq\',\n  \'or_eq\',\n  \'xor_eq\',\n];\n\nmodule.exports = grammar(C, {\n  name: \'cpp\',\n\n  externals: $ => [\n    $.raw_string_delimiter,\n    $.raw_string_content,\n  ],\n\n  conflicts: $ => [\n    // C\n    [$._type_specifier, $._declarator],\n    [$._type_specifier, $._expression_not_binary],\n    [$.sized_type_specifier],\n    [$.attributed_statement],\n    [$._declaration_modifiers, $.attributed_statement],\n\n    // C++\n    [$.template_function, $.template_type],\n    [$.template_function, $.template_type, $._expression_not_binary],\n    [$.template_function, $.template_type, $.qualified_identifier],\n    [$.template_method, $.field_expression],\n    [$.template_type, $.qualified_type_identifier],\n    [$.qualified_type_identifier, $.qualified_identifier],\n    [$.comma_expression, $.initializer_list],\n    [$._expression_not_binary, $._declarator],\n    [$._expression_not_binary, $.structured_binding_declarator],\n    [$._expression_not_binary, $._declarator, $._type_specifier],\n    [$.parameter_list, $.argument_list],\n    [$._type_specifier, $.call_expression],\n    [$._declaration_specifiers, $._constructor_specifiers],\n    [$._binary_fold_operator, $._fold_operator],\n    [$._function_declarator_seq],\n    [$._type_specifier, $.sized_type_specifier],\n    [$.initializer_pair, $.comma_expression],\n    [$.expression_statement, $._for_statement_body],\n    [$.init_statement, $._for_statement_body],\n  ],\n\n  inline: ($, original) => original.concat([\n    $._namespace_identifier,\n  ]),\n\n  precedences: $ => [\n    [$.argument_list, $.type_qualifier],\n    [$._expression_not_binary, $._class_name],\n  ],\n\n  rules: {\n    _top_level_item: ($, original) => choice(\n      ...original.members.filter((member) => member.content?.name != \'_old_style_function_definition\'),\n      $.namespace_definition,\n      $.concept_definition,\n      $.namespace_alias_definition,\n      $.using_declaration,\n      $.alias_declaration,\n      $.static_assert_declaration,\n      $.template_declaration,\n      $.template_instantiation,\n      alias($.constructor_or_destructor_definition, $.function_definition),\n      alias($.operator_cast_definition, $.function_definition),\n      alias($.operator_cast_declaration, $.declaration),\n    ),\n\n    _block_item: ($, original) => choice(\n      ...original.members.filter((member) => member.content?.name != \'_old_style_function_definition\'),\n      $.namespace_definition,\n      $.concept_definition,\n      $.namespace_alias_definition,\n      $.using_declaration,\n      $.alias_declaration,\n      $.static_assert_declaration,\n      $.template_declaration,\n      $.template_instantiation,\n      alias($.constructor_or_destructor_definition, $.function_definition),\n      alias($.operator_cast_definition, $.function_definition),\n      alias($.operator_cast_declaration, $.declaration),\n    ),\n\n    // Types\n\n    placeholder_type_specifier: $ => prec(1, seq(\n      field(\'constraint\', optional($._type_specifier)),\n      choice($.auto, alias($.decltype_auto, $.decltype)),\n    )),\n\n    auto: _ => \'auto\',\n    decltype_auto: $ => seq(\n      \'decltype\',\n      \'(\',\n      $.auto,\n      \')\',\n    ),\n    decltype: $ => seq(\n      \'decltype\',\n      \'(\',\n      $._expression,\n      \')\',\n    ),\n\n    _type_specifier: $ => choice(\n      $.struct_specifier,\n      $.union_specifier,\n      $.enum_specifier,\n      $.class_specifier,\n      $.sized_type_specifier,\n      $.primitive_type,\n      $.template_type,\n      $.dependent_type,\n      $.placeholder_type_specifier,\n      $.decltype,\n      prec.right(choice(\n        alias($.qualified_type_identifier, $.qualified_identifier),\n        $._type_identifier,\n      )),\n    ),\n\n    type_qualifier: (_, original) => choice(\n      original,\n      \'mutable\',\n      \'constinit\',\n      \'consteval\',\n    ),\n\n    type_descriptor: (_, original) => prec.right(original),\n\n    // When used in a trailing return type, these specifiers can now occur immediately before\n    // a compound statement. This introduces a shift/reduce conflict that needs to be resolved\n    // with an associativity.\n    _class_declaration: $ => seq(\n      repeat(choice($.attribute_specifier, $.alignas_specifier)),\n      optional($.ms_declspec_modifier),\n      repeat($.attribute_declaration),\n      $._class_declaration_item,\n    ),\n    _class_declaration_item: $ => prec.right(seq(\n      choice(\n        field(\'name\', $._class_name),\n        seq(\n          optional(field(\'name\', $._class_name)),\n          optional($.virtual_specifier),\n          optional($.base_class_clause),\n          field(\'body\', $.field_declaration_list),\n        ),\n      ),\n      optional($.attribute_specifier),\n    )),\n\n    class_specifier: $ => seq(\n      \'class\',\n      $._class_declaration,\n    ),\n\n    union_specifier: $ => seq(\n      \'union\',\n      $._class_declaration,\n    ),\n\n    struct_specifier: $ => seq(\n      \'struct\',\n      $._class_declaration,\n    ),\n\n    _class_name: $ => prec.right(choice(\n      $._type_identifier,\n      $.template_type,\n      alias($.qualified_type_identifier, $.qualified_identifier),\n    )),\n\n    function_definition: ($, original) => ({\n      ...original,\n      members: original.members.map(\n        (e) => e.name !== \'body\' ?\n          e :\n          field(\'body\', choice(e.content, $.try_statement))),\n    }),\n\n    declaration: $ => seq(\n      $._declaration_specifiers,\n      commaSep1(field(\'declarator\', choice(\n        seq(\n          // C uses _declaration_declarator here for some nice macro parsing in function declarators,\n          // but this causes a world of pain for C++ so we\'ll just stick to the normal _declarator here.\n          $._declarator,\n          optional($.gnu_asm_expression),\n        ),\n        $.init_declarator,\n      ))),\n      \';\',\n    ),\n\n    virtual_specifier: _ => choice(\n      \'final\', // the only legal value here for classes\n      \'override\', // legal for functions in addition to final, plus permutations.\n    ),\n\n    virtual: _ => choice(\'virtual\'),\n\n    alignas_specifier: $ => seq(\n      \'alignas\',\n      \'(\',\n      choice($._expression, $.primitive_type),\n      \')\',\n    ),\n\n    _declaration_modifiers: ($, original) => choice(\n      original,\n      $.virtual,\n      $.alignas_specifier,\n    ),\n\n    explicit_function_specifier: $ => choice(\n      \'explicit\',\n      prec(PREC.CALL, seq(\n        \'explicit\',\n        \'(\',\n        $._expression,\n        \')\',\n      )),\n    ),\n\n    base_class_clause: $ => seq(\n      \':\',\n      commaSep1(seq(\n        repeat($.attribute_declaration),\n        optional(choice(\n          $.access_specifier,\n          seq($.access_specifier, $.virtual),\n          seq($.virtual, $.access_specifier),\n        )),\n        $._class_name,\n        optional(\'...\'),\n      )),\n    ),\n\n    enum_specifier: $ => prec.right(seq(\n      \'enum\',\n      optional(choice(\'class\', \'struct\')),\n      choice(\n        seq(\n          field(\'name\', $._class_name),\n          optional($._enum_base_clause),\n          optional(field(\'body\', $.enumerator_list)),\n        ),\n        field(\'body\', $.enumerator_list),\n      ),\n      optional($.attribute_specifier),\n    )),\n\n    _enum_base_clause: $ => prec.left(seq(\n      \':\',\n      field(\'base\', choice(\n        alias($.qualified_type_identifier, $.qualified_identifier),\n        $._type_identifier,\n        $.primitive_type,\n        $.sized_type_specifier,\n      )),\n    )),\n\n    // The `auto` storage class is removed in C++0x in order to allow for the `auto` type.\n    storage_class_specifier: (_, original) => choice(\n      ...original.members.filter((member) => member.value !== \'auto\'),\n      \'thread_local\',\n    ),\n\n    dependent_type: $ => prec.dynamic(-1, prec.right(seq(\n      \'typename\',\n      $._type_specifier,\n    ))),\n\n    // Declarations\n\n    template_declaration: $ => seq(\n      \'template\',\n      field(\'parameters\', $.template_parameter_list),\n      optional($.requires_clause),\n      choice(\n        $._empty_declaration,\n        $.alias_declaration,\n        $.declaration,\n        $.template_declaration,\n        $.function_definition,\n        $.concept_definition,\n        $.friend_declaration,\n        alias($.constructor_or_destructor_declaration, $.declaration),\n        alias($.constructor_or_destructor_definition, $.function_definition),\n        alias($.operator_cast_declaration, $.declaration),\n        alias($.operator_cast_definition, $.function_definition),\n      ),\n    ),\n\n    template_instantiation: $ => seq(\n      \'template\',\n      optional($._declaration_specifiers),\n      field(\'declarator\', $._declarator),\n      \';\',\n    ),\n\n    template_parameter_list: $ => seq(\n      \'<\',\n      commaSep(choice(\n        $.parameter_declaration,\n        $.optional_parameter_declaration,\n        $.type_parameter_declaration,\n        $.variadic_parameter_declaration,\n        $.variadic_type_parameter_declaration,\n        $.optional_type_parameter_declaration,\n        $.template_template_parameter_declaration,\n      )),\n      alias(token(prec(1, \'>\')), \'>\'),\n    ),\n\n    type_parameter_declaration: $ => prec(1, seq(\n      choice(\'typename\', \'class\'),\n      optional($._type_identifier),\n    )),\n\n    variadic_type_parameter_declaration: $ => prec(1, seq(\n      choice(\'typename\', \'class\'),\n      \'...\',\n      optional($._type_identifier),\n    )),\n\n    optional_type_parameter_declaration: $ => seq(\n      choice(\'typename\', \'class\'),\n      optional(field(\'name\', $._type_identifier)),\n      \'=\',\n      field(\'default_type\', $._type_specifier),\n    ),\n\n    template_template_parameter_declaration: $ => seq(\n      \'template\',\n      field(\'parameters\', $.template_parameter_list),\n      choice(\n        $.type_parameter_declaration,\n        $.variadic_type_parameter_declaration,\n        $.optional_type_parameter_declaration,\n      ),\n    ),\n\n    parameter_list: $ => seq(\n      \'(\',\n      commaSep(choice(\n        $.parameter_declaration,\n        $.optional_parameter_declaration,\n        $.variadic_parameter_declaration,\n        \'...\',\n      )),\n      \')\',\n    ),\n\n    optional_parameter_declaration: $ => seq(\n      $._declaration_specifiers,\n      field(\'declarator\', optional(choice($._declarator, $.abstract_reference_declarator))),\n      \'=\',\n      field(\'default_value\', $._expression),\n    ),\n\n    variadic_parameter_declaration: $ => seq(\n      $._declaration_specifiers,\n      field(\'declarator\', choice(\n        $.variadic_declarator,\n        alias($.variadic_reference_declarator, $.reference_declarator),\n      )),\n    ),\n\n    variadic_declarator: $ => seq(\n      \'...\',\n      optional($.identifier),\n    ),\n\n    variadic_reference_declarator: $ => seq(\n      choice(\'&&\', \'&\'),\n      $.variadic_declarator,\n    ),\n\n    init_declarator: ($, original) => choice(\n      original,\n      seq(\n        field(\'declarator\', $._declarator),\n        field(\'value\', choice(\n          $.argument_list,\n          $.initializer_list,\n        )),\n      ),\n    ),\n\n    operator_cast: $ => prec.right(1, seq(\n      \'operator\',\n      $._declaration_specifiers,\n      field(\'declarator\', $._abstract_declarator),\n    )),\n\n    // Avoid ambiguity between compound statement and initializer list in a construct like:\n    //   A b {};\n    compound_statement: (_, original) => prec(-1, original),\n\n    field_initializer_list: $ => seq(\n      \':\',\n      commaSep1($.field_initializer),\n    ),\n\n    field_initializer: $ => prec(1, seq(\n      choice(\n        $._field_identifier,\n        $.template_method,\n        alias($.qualified_field_identifier, $.qualified_identifier),\n      ),\n      choice($.initializer_list, $.argument_list),\n      optional(\'...\'),\n    )),\n\n    _field_declaration_list_item: ($, original) => choice(\n      original,\n      $.template_declaration,\n      alias($.inline_method_definition, $.function_definition),\n      alias($.constructor_or_destructor_definition, $.function_definition),\n      alias($.constructor_or_destructor_declaration, $.declaration),\n      alias($.operator_cast_definition, $.function_definition),\n      alias($.operator_cast_declaration, $.declaration),\n      $.friend_declaration,\n      seq($.access_specifier, \':\'),\n      $.alias_declaration,\n      $.using_declaration,\n      $.type_definition,\n      $.static_assert_declaration,\n    ),\n\n    field_declaration: $ => seq(\n      $._declaration_specifiers,\n      commaSep(seq(\n        field(\'declarator\', $._field_declarator),\n        optional(choice(\n          $.bitfield_clause,\n          field(\'default_value\', $.initializer_list),\n          seq(\'=\', field(\'default_value\', choice($._expression, $.initializer_list))),\n        )),\n      )),\n      optional($.attribute_specifier),\n      \';\',\n    ),\n\n    inline_method_definition: $ => seq(\n      $._declaration_specifiers,\n      field(\'declarator\', $._field_declarator),\n      choice(\n        field(\'body\', choice($.compound_statement, $.try_statement)),\n        $.default_method_clause,\n        $.delete_method_clause,\n      ),\n    ),\n\n    _constructor_specifiers: $ => choice(\n      $._declaration_modifiers,\n      $.explicit_function_specifier,\n    ),\n\n    operator_cast_definition: $ => seq(\n      repeat($._constructor_specifiers),\n      field(\'declarator\', choice(\n        $.operator_cast,\n        alias($.qualified_operator_cast_identifier, $.qualified_identifier),\n      )),\n      field(\'body\', choice($.compound_statement, $.try_statement)),\n    ),\n\n    operator_cast_declaration: $ => prec(1, seq(\n      repeat($._constructor_specifiers),\n      field(\'declarator\', choice(\n        $.operator_cast,\n        alias($.qualified_operator_cast_identifier, $.qualified_identifier),\n      )),\n      optional(seq(\'=\', field(\'default_value\', $._expression))),\n      \';\',\n    )),\n\n    constructor_try_statement: $ => seq(\n      \'try\',\n      optional($.field_initializer_list),\n      field(\'body\', $.compound_statement),\n      repeat1($.catch_clause),\n    ),\n\n    constructor_or_destructor_definition: $ => seq(\n      repeat($._constructor_specifiers),\n      field(\'declarator\', $.function_declarator),\n      choice(\n        seq(\n          optional($.field_initializer_list),\n          field(\'body\', $.compound_statement),\n        ),\n        alias($.constructor_try_statement, $.try_statement),\n        $.default_method_clause,\n        $.delete_method_clause,\n      ),\n    ),\n\n    constructor_or_destructor_declaration: $ => seq(\n      repeat($._constructor_specifiers),\n      field(\'declarator\', $.function_declarator),\n      \';\',\n    ),\n\n    default_method_clause: _ => seq(\'=\', \'default\', \';\'),\n    delete_method_clause: _ => seq(\'=\', \'delete\', \';\'),\n\n    friend_declaration: $ => seq(\n      \'friend\',\n      choice(\n        $.declaration,\n        $.function_definition,\n        seq(\n          optional(choice(\n            \'class\',\n            \'struct\',\n            \'union\',\n          )),\n          $._class_name, \';\',\n        ),\n      ),\n    ),\n\n    access_specifier: _ => choice(\n      \'public\',\n      \'private\',\n      \'protected\',\n    ),\n\n    _declarator: ($, original) => choice(\n      original,\n      $.reference_declarator,\n      $.qualified_identifier,\n      $.template_function,\n      $.operator_name,\n      $.destructor_name,\n      $.structured_binding_declarator,\n    ),\n\n    _field_declarator: ($, original) => choice(\n      original,\n      alias($.reference_field_declarator, $.reference_declarator),\n      $.template_method,\n      $.operator_name,\n    ),\n\n    _abstract_declarator: ($, original) => choice(\n      original,\n      $.abstract_reference_declarator,\n    ),\n\n    reference_declarator: $ => prec.dynamic(1, prec.right(seq(choice(\'&\', \'&&\'), $._declarator))),\n    reference_field_declarator: $ => prec.dynamic(1, prec.right(seq(choice(\'&\', \'&&\'), $._field_declarator))),\n    abstract_reference_declarator: $ => prec.right(seq(choice(\'&\', \'&&\'), optional($._abstract_declarator))),\n\n    structured_binding_declarator: $ => prec.dynamic(PREC.STRUCTURED_BINDING, seq(\n      \'[\', commaSep1($.identifier), \']\',\n    )),\n\n    ref_qualifier: _ => choice(\'&\', \'&&\'),\n\n    _function_declarator_seq: $ => seq(\n      field(\'parameters\', $.parameter_list),\n      optional($._function_attributes_start),\n      optional($.ref_qualifier),\n      optional($._function_exception_specification),\n      optional($._function_attributes_end),\n      optional($.trailing_return_type),\n      optional($._function_postfix),\n    ),\n\n    _function_attributes_start: $ => prec(1, choice(\n      seq(repeat1($.attribute_specifier), repeat($.type_qualifier)),\n      seq(repeat($.attribute_specifier), repeat1($.type_qualifier)),\n    )),\n\n    _function_exception_specification: $ => choice(\n      $.noexcept,\n      $.throw_specifier,\n    ),\n\n    _function_attributes_end: $ => prec.right(seq(\n      optional($.gnu_asm_expression),\n      choice(\n        seq(repeat1($.attribute_specifier), repeat($.attribute_declaration)),\n        seq(repeat($.attribute_specifier), repeat1($.attribute_declaration)),\n      ),\n    )),\n\n    _function_postfix: $ => prec.right(choice(\n      repeat1($.virtual_specifier),\n      $.requires_clause,\n    )),\n\n    function_declarator: $ => prec.dynamic(1, seq(\n      field(\'declarator\', $._declarator),\n      $._function_declarator_seq,\n    )),\n\n    function_field_declarator: $ => prec.dynamic(1, seq(\n      field(\'declarator\', $._field_declarator),\n      $._function_declarator_seq,\n    )),\n\n    abstract_function_declarator: $ => seq(\n      field(\'declarator\', optional($._abstract_declarator)),\n      $._function_declarator_seq,\n    ),\n\n    trailing_return_type: $ => seq(\'->\', $.type_descriptor),\n\n    noexcept: $ => prec.right(seq(\n      \'noexcept\',\n      optional(\n        seq(\n          \'(\',\n          optional($._expression),\n          \')\',\n        ),\n      ),\n    )),\n\n    throw_specifier: $ => seq(\n      \'throw\',\n      seq(\n        \'(\',\n        commaSep($.type_descriptor),\n        \')\',\n      ),\n    ),\n\n    template_type: $ => seq(\n      field(\'name\', $._type_identifier),\n      field(\'arguments\', $.template_argument_list),\n    ),\n\n    template_method: $ => seq(\n      field(\'name\', choice($._field_identifier, $.operator_name)),\n      field(\'arguments\', $.template_argument_list),\n    ),\n\n    template_function: $ => seq(\n      field(\'name\', $.identifier),\n      field(\'arguments\', $.template_argument_list),\n    ),\n\n    template_argument_list: $ => seq(\n      \'<\',\n      commaSep(choice(\n        prec.dynamic(3, $.type_descriptor),\n        prec.dynamic(2, alias($.type_parameter_pack_expansion, $.parameter_pack_expansion)),\n        prec.dynamic(1, $._expression),\n      )),\n      alias(token(prec(1, \'>\')), \'>\'),\n    ),\n\n    namespace_definition: $ => seq(\n      optional(\'inline\'),\n      \'namespace\',\n      field(\'name\', optional(\n        choice(\n          $._namespace_identifier,\n          $.nested_namespace_specifier,\n        ))),\n      field(\'body\', $.declaration_list),\n    ),\n\n    namespace_alias_definition: $ => seq(\n      \'namespace\',\n      field(\'name\', $._namespace_identifier),\n      \'=\',\n      choice(\n        $._namespace_identifier,\n        $.nested_namespace_specifier,\n      ),\n      \';\',\n    ),\n\n    _namespace_specifier: $ => seq(\n      optional(\'inline\'),\n      $._namespace_identifier,\n    ),\n\n    nested_namespace_specifier: $ => prec(1, seq(\n      optional($._namespace_specifier),\n      \'::\',\n      choice(\n        $.nested_namespace_specifier,\n        $._namespace_specifier,\n      ),\n    )),\n\n    using_declaration: $ => seq(\n      \'using\',\n      optional(choice(\'namespace\', \'enum\')),\n      choice(\n        $.identifier,\n        $.qualified_identifier,\n      ),\n      \';\',\n    ),\n\n    alias_declaration: $ => seq(\n      \'using\',\n      field(\'name\', $._type_identifier),\n      repeat($.attribute_declaration),\n      \'=\',\n      field(\'type\', $.type_descriptor),\n      \';\',\n    ),\n\n    static_assert_declaration: $ => seq(\n      \'static_assert\',\n      \'(\',\n      field(\'condition\', $._expression),\n      optional(seq(\n        \',\',\n        field(\'message\', choice(\n          $.string_literal,\n          $.raw_string_literal,\n          $.concatenated_string,\n        )),\n      )),\n      \')\',\n      \';\',\n    ),\n\n    concept_definition: $ => seq(\n      \'concept\',\n      field(\'name\', $.identifier),\n      \'=\',\n      $._expression,\n      \';\',\n    ),\n\n    // Statements\n\n    _top_level_statement: ($, original) => choice(\n      original,\n      $.co_return_statement,\n      $.co_yield_statement,\n      $.for_range_loop,\n      $.try_statement,\n      $.throw_statement,\n    ),\n\n    _non_case_statement: ($, original) => choice(\n      original,\n      $.co_return_statement,\n      $.co_yield_statement,\n      $.for_range_loop,\n      $.try_statement,\n      $.throw_statement,\n    ),\n\n    switch_statement: $ => seq(\n      \'switch\',\n      field(\'condition\', $.condition_clause),\n      field(\'body\', $.compound_statement),\n    ),\n\n    while_statement: $ => seq(\n      \'while\',\n      field(\'condition\', $.condition_clause),\n      field(\'body\', $._statement),\n    ),\n\n    if_statement: $ => prec.right(seq(\n      \'if\',\n      optional(\'constexpr\'),\n      field(\'condition\', $.condition_clause),\n      field(\'consequence\', $._statement),\n      optional(field(\'alternative\', $.else_clause)),\n    )),\n\n    // Using prec(1) instead of prec.dynamic(1) causes issues with the\n    // range loop\'s declaration specifiers if `int` is passed in, it\'ll\n    // always prefer the standard for loop and give us a parse error.\n    _for_statement_body: ($, original) => prec.dynamic(1, original),\n    for_range_loop: $ => seq(\n      \'for\',\n      \'(\',\n      $._for_range_loop_body,\n      \')\',\n      field(\'body\', $._statement),\n    ),\n    _for_range_loop_body: $ => seq(\n      field(\'initializer\', optional($.init_statement)),\n      $._declaration_specifiers,\n      field(\'declarator\', $._declarator),\n      \':\',\n      field(\'right\', choice(\n        $._expression,\n        $.initializer_list,\n      )),\n    ),\n\n    init_statement: $ => choice(\n      $.alias_declaration,\n      $.type_definition,\n      $.declaration,\n      $.expression_statement,\n    ),\n\n    condition_clause: $ => seq(\n      \'(\',\n      field(\'initializer\', optional($.init_statement)),\n      field(\'value\', choice(\n        $._expression,\n        $.comma_expression,\n        alias($.condition_declaration, $.declaration),\n      )),\n      \')\',\n    ),\n\n    condition_declaration: $ => seq(\n      $._declaration_specifiers,\n      field(\'declarator\', $._declarator),\n      choice(\n        seq(\n          \'=\',\n          field(\'value\', $._expression),\n        ),\n        field(\'value\', $.initializer_list),\n      ),\n    ),\n\n    return_statement: ($, original) => seq(\n      choice(\n        original,\n        seq(\'return\', $.initializer_list, \';\'),\n      ),\n    ),\n\n    co_return_statement: $ => seq(\n      \'co_return\',\n      optional($._expression),\n      \';\',\n    ),\n\n    co_yield_statement: $ => seq(\n      \'co_yield\',\n      $._expression,\n      \';\',\n    ),\n\n    throw_statement: $ => seq(\n      \'throw\',\n      optional($._expression),\n      \';\',\n    ),\n\n    try_statement: $ => seq(\n      \'try\',\n      field(\'body\', $.compound_statement),\n      repeat1($.catch_clause),\n    ),\n\n    catch_clause: $ => seq(\n      \'catch\',\n      field(\'parameters\', $.parameter_list),\n      field(\'body\', $.compound_statement),\n    ),\n\n    // Expressions\n\n    _expression_not_binary: ($, original) => choice(\n      original,\n      $.co_await_expression,\n      $.requires_expression,\n      $.requires_clause,\n      $.template_function,\n      $.qualified_identifier,\n      $.new_expression,\n      $.delete_expression,\n      $.lambda_expression,\n      $.parameter_pack_expansion,\n      $.this,\n      $.raw_string_literal,\n      $.user_defined_literal,\n      $.fold_expression,\n    ),\n\n    raw_string_literal: $ => seq(\n      choice(\'R\"\', \'LR\"\', \'uR\"\', \'UR\"\', \'u8R\"\'),\n      choice(\n        seq(\n          field(\'delimiter\', $.raw_string_delimiter),\n          \'(\',\n          $.raw_string_content,\n          \')\',\n          $.raw_string_delimiter,\n        ),\n        seq(\n          \'(\',\n          $.raw_string_content,\n          \')\',\n        )),\n      \'\"\',\n    ),\n\n    subscript_expression: $ => prec(PREC.SUBSCRIPT, seq(\n      field(\'argument\', $._expression),\n      field(\'indices\', $.subscript_argument_list),\n    )),\n\n    subscript_argument_list: $ => seq(\n      \'[\',\n      commaSep(choice($._expression, $.initializer_list)),\n      \']\',\n    ),\n\n    call_expression: ($, original) => choice(original, seq(\n      field(\'function\', $.primitive_type),\n      field(\'arguments\', $.argument_list),\n    )),\n\n    co_await_expression: $ => prec.left(PREC.UNARY, seq(\n      field(\'operator\', \'co_await\'),\n      field(\'argument\', $._expression),\n    )),\n\n    new_expression: $ => prec.right(PREC.NEW, seq(\n      optional(\'::\'),\n      \'new\',\n      field(\'placement\', optional($.argument_list)),\n      field(\'type\', $._type_specifier),\n      field(\'declarator\', optional($.new_declarator)),\n      field(\'arguments\', optional(choice(\n        $.argument_list,\n        $.initializer_list,\n      ))),\n    )),\n\n    new_declarator: $ => prec.right(seq(\n      \'[\',\n      field(\'length\', $._expression),\n      \']\',\n      optional($.new_declarator),\n    )),\n\n    delete_expression: $ => seq(\n      optional(\'::\'),\n      \'delete\',\n      optional(seq(\'[\', \']\')),\n      $._expression,\n    ),\n\n    field_expression: $ => prec.right(seq(\n      prec(PREC.FIELD, seq(\n        field(\'argument\', $._expression),\n        field(\'operator\', choice(\'.\', \'.*\', \'->\')),\n      )),\n      field(\'field\', choice(\n        $._field_identifier,\n        alias($.qualified_field_identifier, $.qualified_identifier),\n        $.destructor_name,\n        $.template_method,\n        alias($.dependent_field_identifier, $.dependent_name),\n      )),\n    )),\n\n    type_requirement: $ => seq(\'typename\', $._class_name),\n\n    compound_requirement: $ => seq(\n      \'{\', $._expression, \'}\',\n      optional(\'noexcept\'),\n      optional($.trailing_return_type),\n      \';\',\n    ),\n\n    _requirement: $ => choice(\n      alias($.expression_statement, $.simple_requirement),\n      $.type_requirement,\n      $.compound_requirement,\n    ),\n\n    requirement_seq: $ => seq(\'{\', repeat($._requirement), \'}\'),\n\n    constraint_conjunction: $ => prec.left(PREC.LOGICAL_AND, seq(\n      field(\'left\', $._requirement_clause_constraint),\n      field(\'operator\', choice(\'&&\', \'and\')),\n      field(\'right\', $._requirement_clause_constraint)),\n    ),\n\n    constraint_disjunction: $ => prec.left(PREC.LOGICAL_OR, seq(\n      field(\'left\', $._requirement_clause_constraint),\n      field(\'operator\', choice(\'||\', \'or\')),\n      field(\'right\', $._requirement_clause_constraint)),\n    ),\n\n    _requirement_clause_constraint: $ => choice(\n      // Primary expressions\"\n      $.true,\n      $.false,\n      $._class_name,\n      $.fold_expression,\n      $.lambda_expression,\n      $.requires_expression,\n\n      // Parenthesized expressions\n      seq(\'(\', $._expression, \')\'),\n\n      // conjunction or disjunction of the above\n      $.constraint_conjunction,\n      $.constraint_disjunction,\n    ),\n\n    requires_clause: $ => seq(\n      \'requires\',\n      field(\'constraint\', $._requirement_clause_constraint),\n    ),\n\n    requires_parameter_list: $ => seq(\n      \'(\',\n      commaSep(choice(\n        $.parameter_declaration,\n        $.optional_parameter_declaration,\n        $.variadic_parameter_declaration,\n      )),\n      \')\',\n    ),\n\n    requires_expression: $ => seq(\n      \'requires\',\n      field(\'parameters\', optional(alias($.requires_parameter_list, $.parameter_list))),\n      field(\'requirements\', $.requirement_seq),\n    ),\n\n    lambda_expression: $ => seq(\n      field(\'captures\', $.lambda_capture_specifier),\n      optional(seq(\n        field(\'template_parameters\', $.template_parameter_list),\n        optional(field(\'constraint\', $.requires_clause)),\n      )),\n      optional(field(\'declarator\', $.abstract_function_declarator)),\n      field(\'body\', $.compound_statement),\n    ),\n\n    lambda_capture_specifier: $ => prec(PREC.LAMBDA, seq(\n      \'[\',\n      choice(\n        $.lambda_default_capture,\n        commaSep($._expression),\n        seq(\n          $.lambda_default_capture,\n          \',\', commaSep1($._expression),\n        ),\n      ),\n      \']\',\n    )),\n\n    lambda_default_capture: _ => choice(\'=\', \'&\'),\n\n    _fold_operator: _ => choice(...FOLD_OPERATORS),\n    _binary_fold_operator: _ => choice(...FOLD_OPERATORS.map((operator) => seq(field(\'operator\', operator), \'...\', operator))),\n\n    _unary_left_fold: $ => seq(\n      field(\'left\', \'...\'),\n      field(\'operator\', $._fold_operator),\n      field(\'right\', $._expression),\n    ),\n    _unary_right_fold: $ => seq(\n      field(\'left\', $._expression),\n      field(\'operator\', $._fold_operator),\n      field(\'right\', \'...\'),\n    ),\n    _binary_fold: $ => seq(\n      field(\'left\', $._expression),\n      $._binary_fold_operator,\n      field(\'right\', $._expression),\n    ),\n\n    fold_expression: $ => seq(\n      \'(\',\n      choice(\n        $._unary_right_fold,\n        $._unary_left_fold,\n        $._binary_fold,\n      ),\n      \')\',\n    ),\n\n    parameter_pack_expansion: $ => prec(-1, seq(\n      field(\'pattern\', $._expression),\n      \'...\',\n    )),\n\n    type_parameter_pack_expansion: $ => seq(\n      field(\'pattern\', $.type_descriptor),\n      \'...\',\n    ),\n\n    sizeof_expression: ($, original) => prec.right(PREC.SIZEOF, choice(\n      original,\n      seq(\n        \'sizeof\', \'...\',\n        \'(\',\n        field(\'value\', $.identifier),\n        \')\',\n      ),\n    )),\n\n    unary_expression: ($, original) => choice(\n      original,\n      prec.left(PREC.UNARY, seq(\n        field(\'operator\', choice(\'not\', \'compl\')),\n        field(\'argument\', $._expression),\n      )),\n    ),\n\n    binary_expression: ($, original) => {\n      const table = [\n        [\'<=>\', PREC.THREE_WAY],\n        [\'or\', PREC.LOGICAL_OR],\n        [\'and\', PREC.LOGICAL_AND],\n        [\'bitor\', PREC.INCLUSIVE_OR],\n        [\'xor\', PREC.EXCLUSIVE_OR],\n        [\'bitand\', PREC.BITWISE_AND],\n        [\'not_eq\', PREC.EQUAL],\n      ];\n\n      return choice(\n        ...original.members,\n        ...table.map(([operator, precedence]) => {\n          return prec.left(precedence, seq(\n            field(\'left\', $._expression),\n            // @ts-ignore\n            field(\'operator\', operator),\n            field(\'right\', $._expression),\n          ));\n        }));\n    },\n\n    // The compound_statement is added to parse macros taking statements as arguments, e.g. MYFORLOOP(1, 10, i, { foo(i); bar(i); })\n    argument_list: $ => seq(\n      \'(\',\n      commaSep(choice(seq(optional(\'__extension__\'), $._expression), $.initializer_list, $.compound_statement)),\n      \')\',\n    ),\n\n    destructor_name: $ => prec(1, seq(\'~\', $.identifier)),\n\n    compound_literal_expression: ($, original) => choice(\n      original,\n      seq(\n        field(\'type\', choice($._class_name, $.primitive_type)),\n        field(\'value\', $.initializer_list),\n      ),\n    ),\n\n    dependent_identifier: $ => seq(\'template\', $.template_function),\n    dependent_field_identifier: $ => seq(\'template\', $.template_method),\n    dependent_type_identifier: $ => seq(\'template\', $.template_type),\n\n    _scope_resolution: $ => prec(1, seq(\n      field(\'scope\', optional(choice(\n        $._namespace_identifier,\n        $.template_type,\n        $.decltype,\n        alias($.dependent_type_identifier, $.dependent_name),\n      ))),\n      \'::\',\n    )),\n\n    qualified_field_identifier: $ => prec.right(seq(\n      $._scope_resolution,\n      field(\'name\', choice(\n        alias($.dependent_field_identifier, $.dependent_name),\n        alias($.qualified_field_identifier, $.qualified_identifier),\n        $.template_method,\n        $._field_identifier,\n      )),\n    )),\n\n    qualified_identifier: $ => seq(\n      $._scope_resolution,\n      field(\'name\', choice(\n        alias($.dependent_identifier, $.dependent_name),\n        $.qualified_identifier,\n        $.template_function,\n        seq(optional(\'template\'), $.identifier),\n        $.operator_name,\n        $.destructor_name,\n        $.pointer_type_declarator,\n      )),\n    ),\n\n    qualified_type_identifier: $ => seq(\n      $._scope_resolution,\n      field(\'name\', choice(\n        alias($.dependent_type_identifier, $.dependent_name),\n        alias($.qualified_type_identifier, $.qualified_identifier),\n        $.template_type,\n        $._type_identifier,\n      )),\n    ),\n\n    qualified_operator_cast_identifier: $ => seq(\n      $._scope_resolution,\n      field(\'name\', choice(\n        alias($.qualified_operator_cast_identifier, $.qualified_identifier),\n        $.operator_cast,\n      )),\n    ),\n\n    _assignment_left_expression: ($, original) => choice(\n      original,\n      $.qualified_identifier,\n      $.user_defined_literal,\n    ),\n\n    assignment_expression: $ => prec.right(PREC.ASSIGNMENT, seq(\n      field(\'left\', $._assignment_left_expression),\n      field(\'operator\', choice(...ASSIGNMENT_OPERATORS)),\n      field(\'right\', choice($._expression, $.initializer_list)),\n    )),\n\n    _assignment_expression_lhs: $ => seq(\n      field(\'left\', $._expression),\n      field(\'operator\', choice(...ASSIGNMENT_OPERATORS)),\n      field(\'right\', choice($._expression, $.initializer_list)),\n    ),\n\n    // This prevents an ambiguity between fold expressions\n    // and assignment expressions within parentheses.\n    parenthesized_expression: ($, original) => choice(\n      original,\n      seq(\'(\', alias($._assignment_expression_lhs, $.assignment_expression), \')\'),\n    ),\n\n    operator_name: $ => prec(1, seq(\n      \'operator\',\n      choice(\n        \'co_await\',\n        \'+\', \'-\', \'*\', \'/\', \'%\',\n        \'^\', \'&\', \'|\', \'~\',\n        \'!\', \'=\', \'<\', \'>\',\n        \'+=\', \'-=\', \'*=\', \'/=\', \'%=\', \'^=\', \'&=\', \'|=\',\n        \'<<\', \'>>\', \'>>=\', \'<<=\',\n        \'==\', \'!=\', \'<=\', \'>=\',\n        \'<=>\',\n        \'&&\', \'||\',\n        \'++\', \'--\',\n        \',\',\n        \'->*\',\n        \'->\',\n        \'()\', \'[]\',\n        \'xor\', \'bitand\', \'bitor\', \'compl\',\n        \'not\', \'xor_eq\', \'and_eq\', \'or_eq\', \'not_eq\',\n        \'and\', \'or\',\n        seq(choice(\'new\', \'delete\'), optional(\'[]\')),\n        seq(\'\"\"\', $.identifier),\n      ),\n    )),\n\n    this: _ => \'this\',\n\n    concatenated_string: $ => prec.right(seq(\n      choice($.identifier, $.string_literal, $.raw_string_literal),\n      choice($.string_literal, $.raw_string_literal),\n      repeat(choice($.identifier, $.string_literal, $.raw_string_literal)),\n    )),\n\n    number_literal: $ => {\n      const sign = /[-\\+]/;\n      const separator = \'\\\'\';\n      const binary = /[01]/;\n      const binaryDigits = seq(repeat1(binary), repeat(seq(separator, repeat1(binary))));\n      const decimal = /[0-9]/;\n      const firstDecimal = /[1-9]/;\n      const intDecimalDigits = seq(firstDecimal, repeat(decimal), repeat(seq(separator, repeat1(decimal))));\n      const floatDecimalDigits = seq(repeat1(decimal), repeat(seq(separator, repeat1(decimal))));\n      const hex = /[0-9a-fA-F]/;\n      const hexDigits = seq(repeat1(hex), repeat(seq(separator, repeat1(hex))));\n      const octal = /[0-7]/;\n      const octalDigits = seq(\'0\', repeat(octal), repeat(seq(separator, repeat1(octal))));\n      const hexExponent = seq(/[pP]/, optional(sign), floatDecimalDigits);\n      const decimalExponent = seq(/[eE]/, optional(sign), floatDecimalDigits);\n      const intSuffix = /(ll|LL)[uU]?|[uU](ll|LL)?|[uU][lL]?|[uU][zZ]?|[lL][uU]?|[zZ][uU]?/;\n      const floatSuffix = /([fF](16|32|64|128)?)|[lL]|(bf16|BF16)/;\n\n      return token(seq(\n        optional(sign),\n        choice(\n          seq(\n            choice(\n              seq(choice(\'0b\', \'0B\'), binaryDigits),\n              intDecimalDigits,\n              seq(choice(\'0x\', \'0X\'), hexDigits),\n              octalDigits,\n            ),\n            optional(intSuffix),\n          ),\n          seq(\n            choice(\n              seq(floatDecimalDigits, decimalExponent),\n              seq(floatDecimalDigits, \'.\', optional(floatDecimalDigits), optional(decimalExponent)),\n              seq(\'.\', floatDecimalDigits, optional(decimalExponent)),\n              seq(\n                choice(\'0x\', \'0X\'),\n                choice(\n                  hexDigits,\n                  seq(hexDigits, \'.\', optional(hexDigits)),\n                  seq(\'.\', hexDigits)),\n                hexExponent,\n              ),\n            ),\n            optional(floatSuffix),\n          ),\n        ),\n      ));\n    },\n\n    literal_suffix: _ => token.immediate(/[a-zA-Z_]\\w*/),\n\n    user_defined_literal: $ => seq(\n      choice(\n        $.number_literal,\n        $.char_literal,\n        $.string_literal,\n        $.raw_string_literal,\n        $.concatenated_string,\n      ),\n      $.literal_suffix,\n    ),\n\n    _namespace_identifier: $ => alias($.identifier, $.namespace_identifier),\n  },\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\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";
Expand description

The source of the Cpp tree-sitter grammar description.