Directory structure:
└── tree-sitter-tree-sitter-cpp/
    ├── README.md
    ├── binding.gyp
    ├── Cargo.toml
    ├── CMakeLists.txt
    ├── eslint.config.mjs
    ├── go.mod
    ├── go.sum
    ├── grammar.js
    ├── LICENSE
    ├── Makefile
    ├── package.json
    ├── Package.resolved
    ├── Package.swift
    ├── pyproject.toml
    ├── setup.py
    ├── tree-sitter.json
    ├── .editorconfig
    ├── bindings/
    │   ├── c/
    │   │   ├── tree-sitter-cpp.h
    │   │   └── tree-sitter-cpp.pc.in
    │   ├── go/
    │   │   ├── binding.go
    │   │   └── binding_test.go
    │   ├── node/
    │   │   ├── binding.cc
    │   │   ├── binding_test.js
    │   │   ├── index.d.ts
    │   │   └── index.js
    │   ├── python/
    │   │   ├── tests/
    │   │   │   └── test_binding.py
    │   │   └── tree_sitter_cpp/
    │   │       ├── __init__.py
    │   │       ├── __init__.pyi
    │   │       ├── binding.c
    │   │       └── py.typed
    │   ├── rust/
    │   │   ├── build.rs
    │   │   └── lib.rs
    │   └── swift/
    │       ├── TreeSitterCPP/
    │       │   └── cpp.h
    │       └── TreeSitterCPPTests/
    │           └── TreeSitterCPPTests.swift
    ├── examples/
    │   ├── marker-index.h
    │   └── rule.cc
    ├── queries/
    │   ├── highlights.scm
    │   ├── injections.scm
    │   └── tags.scm
    ├── src/
    │   ├── scanner.c
    │   └── tree_sitter/
    │       ├── alloc.h
    │       ├── array.h
    │       └── parser.h
    ├── test/
    │   ├── corpus/
    │   │   ├── ambiguities.txt
    │   │   ├── concepts.txt
    │   │   ├── definitions.txt
    │   │   ├── expressions.txt
    │   │   ├── microsoft.txt
    │   │   ├── modules.txt
    │   │   ├── statements.txt
    │   │   ├── types.txt
    │   │   └── c/
    │   │       ├── ambiguities.txt
    │   │       ├── crlf.txt
    │   │       ├── declarations.txt
    │   │       ├── expressions.txt
    │   │       ├── microsoft.txt
    │   │       ├── preprocessor.txt
    │   │       ├── statements.txt
    │   │       └── types.txt
    │   └── highlight/
    │       ├── keywords.cpp
    │       └── names.cpp
    └── .github/
        ├── dependabot.yml
        ├── FUNDING.yml
        ├── ISSUE_TEMPLATE/
        │   ├── bug_report.yml
        │   ├── config.yml
        │   └── feature_request.yml
        └── workflows/
            ├── ci.yml
            ├── fuzz.yml
            ├── lint.yml
            └── publish.yml


Files Content:

================================================
FILE: README.md
================================================
# tree-sitter-cpp

[![CI][ci]](https://github.com/tree-sitter/tree-sitter-cpp/actions/workflows/ci.yml)
[![discord][discord]](https://discord.gg/w7nTvsVJhm)
[![matrix][matrix]](https://matrix.to/#/#tree-sitter-chat:matrix.org)
[![crates][crates]](https://crates.io/crates/tree-sitter-cpp)
[![npm][npm]](https://www.npmjs.com/package/tree-sitter-cpp)
[![pypi][pypi]](https://pypi.org/project/tree-sitter-cpp)

C++ grammar for [tree-sitter](https://github.com/tree-sitter/tree-sitter).

## References

- [Hyperlinked C++ BNF Grammar](http://www.nongnu.org/hcb/)
- [EBNF Syntax: C++](http://www.externsoft.ch/download/cpp-iso.html)

[ci]: https://img.shields.io/github/actions/workflow/status/tree-sitter/tree-sitter-cpp/ci.yml?logo=github&label=CI
[discord]: https://img.shields.io/discord/1063097320771698699?logo=discord&label=discord
[matrix]: https://img.shields.io/matrix/tree-sitter-chat%3Amatrix.org?logo=matrix&label=matrix
[npm]: https://img.shields.io/npm/v/tree-sitter-cpp?logo=npm
[crates]: https://img.shields.io/crates/v/tree-sitter-cpp?logo=rust
[pypi]: https://img.shields.io/pypi/v/tree-sitter-cpp?logo=pypi&logoColor=ffd242



================================================
FILE: binding.gyp
================================================
{
  "targets": [
    {
      "target_name": "tree_sitter_cpp_binding",
      "dependencies": [
        "<!(node -p \"require('node-addon-api').targets\"):node_addon_api_except",
      ],
      "include_dirs": [
        "src",
      ],
      "sources": [
        "bindings/node/binding.cc",
        "src/parser.c",
        "src/scanner.c",
      ],
      "conditions": [
        ["OS!='win'", {
          "cflags_c": [
            "-std=c11",
          ],
        }, { # OS == "win"
          "cflags_c": [
            "/std:c11",
            "/utf-8",
          ],
        }],
      ],
    }
  ]
}



================================================
FILE: Cargo.toml
================================================
[package]
name = "tree-sitter-cpp"
description = "C++ grammar for tree-sitter"
version = "0.23.4"
authors = [
  "Max Brunsfeld <maxbrunsfeld@gmail.com>",
  "Amaan Qureshi <amaanq12@gmail.com>",
]
license = "MIT"
readme = "README.md"
keywords = ["incremental", "parsing", "tree-sitter", "cpp"]
categories = ["parsing", "text-editors"]
repository = "https://github.com/tree-sitter/tree-sitter-cpp"
edition = "2021"
autoexamples = false

build = "bindings/rust/build.rs"
include = [
  "LICENSE",
  "bindings/rust/*",
  "./grammar.js",
  "queries/*",
  "src/*",
  "tree-sitter.json",
]

[lib]
path = "bindings/rust/lib.rs"

[dependencies]
tree-sitter-language = "0.1"

[build-dependencies]
cc = "1.1"

[dev-dependencies]
tree-sitter = "0.24"



================================================
FILE: CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.13)

project(tree-sitter-cpp
        VERSION "0.23.4"
        DESCRIPTION "C++ grammar for tree-sitter"
        HOMEPAGE_URL "https://github.com/tree-sitter/tree-sitter-cpp"
        LANGUAGES C)

option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
option(TREE_SITTER_REUSE_ALLOCATOR "Reuse the library allocator" OFF)

set(TREE_SITTER_ABI_VERSION 14 CACHE STRING "Tree-sitter ABI version")
if(NOT ${TREE_SITTER_ABI_VERSION} MATCHES "^[0-9]+$")
    unset(TREE_SITTER_ABI_VERSION CACHE)
    message(FATAL_ERROR "TREE_SITTER_ABI_VERSION must be an integer")
endif()

find_program(TREE_SITTER_CLI tree-sitter DOC "Tree-sitter CLI")

add_custom_command(OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/src/parser.c"
                   DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/grammar.json"
                   COMMAND "${TREE_SITTER_CLI}" generate src/grammar.json
                            --abi=${TREE_SITTER_ABI_VERSION}
                   WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
                   COMMENT "Generating parser.c")

add_library(tree-sitter-cpp src/parser.c)
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/scanner.c)
  target_sources(tree-sitter-cpp PRIVATE src/scanner.c)
endif()
target_include_directories(tree-sitter-cpp PRIVATE src)

target_compile_definitions(tree-sitter-cpp PRIVATE
                           $<$<BOOL:${TREE_SITTER_REUSE_ALLOCATOR}>:TREE_SITTER_REUSE_ALLOCATOR>
                           $<$<CONFIG:Debug>:TREE_SITTER_DEBUG>)

set_target_properties(tree-sitter-cpp
                      PROPERTIES
                      C_STANDARD 11
                      POSITION_INDEPENDENT_CODE ON
                      SOVERSION "${TREE_SITTER_ABI_VERSION}.${PROJECT_VERSION_MAJOR}"
                      DEFINE_SYMBOL "")

configure_file(bindings/c/tree-sitter-cpp.pc.in
               "${CMAKE_CURRENT_BINARY_DIR}/tree-sitter-cpp.pc" @ONLY)

include(GNUInstallDirs)

install(FILES bindings/c/tree-sitter-cpp.h
        DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/tree_sitter")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/tree-sitter-cpp.pc"
        DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig")
install(TARGETS tree-sitter-cpp
        LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}")

add_custom_target(ts-test "${TREE_SITTER_CLI}" test
                  WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
                  COMMENT "tree-sitter test")



================================================
FILE: eslint.config.mjs
================================================
import treesitter from 'eslint-config-treesitter';

export default [
  ...treesitter,
];



================================================
FILE: go.mod
================================================
module github.com/tree-sitter/tree-sitter-cpp

go 1.22

require github.com/tree-sitter/go-tree-sitter v0.24.0

require github.com/mattn/go-pointer v0.0.1 // indirect



================================================
FILE: go.sum
================================================
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0=
github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tree-sitter/go-tree-sitter v0.24.0 h1:kRZb6aBNfcI/u0Qh8XEt3zjNVnmxTisDBN+kXK0xRYQ=
github.com/tree-sitter/go-tree-sitter v0.24.0/go.mod h1:x681iFVoLMEwOSIHA1chaLkXlroXEN7WY+VHGFaoDbk=
github.com/tree-sitter/tree-sitter-c v0.21.5-0.20240818205408-927da1f210eb h1:A8425heRM8mylnv4H58FPUiH+aYivyitre0PzxrfmWs=
github.com/tree-sitter/tree-sitter-c v0.21.5-0.20240818205408-927da1f210eb/go.mod h1:dOF6gtQiF9UwNh995T5OphYmtIypkjsp3ap7r9AN/iA=
github.com/tree-sitter/tree-sitter-embedded-template v0.21.1-0.20240819044651-ffbf64942c33 h1:TwqSV3qLp3tKSqirGLRHnjFk9Tc2oy57LIl+FQ4GjI4=
github.com/tree-sitter/tree-sitter-embedded-template v0.21.1-0.20240819044651-ffbf64942c33/go.mod h1:CvCKCt3v04Ufos1zZnNCelBDeCGRpPucaN8QczoUsN4=
github.com/tree-sitter/tree-sitter-go v0.21.3-0.20240818010209-8c0f0e7a6012 h1:Xvxck3tE5FW7F7bTS97iNM2ADMyCMJztVqn5HYKdJGo=
github.com/tree-sitter/tree-sitter-go v0.21.3-0.20240818010209-8c0f0e7a6012/go.mod h1:T40D0O1cPvUU/+AmiXVXy1cncYQT6wem4Z0g4SfAYvY=
github.com/tree-sitter/tree-sitter-html v0.20.5-0.20240818004741-d11201a263d0 h1:c46K6uh5Dz00zJeU9BfjXdb8I+E4RkUdfnWJpQADXFo=
github.com/tree-sitter/tree-sitter-html v0.20.5-0.20240818004741-d11201a263d0/go.mod h1:hcNt/kOJHcIcuMvouE7LJcYdeFUFbVpBJ6d4wmOA+tU=
github.com/tree-sitter/tree-sitter-java v0.21.1-0.20240824015150-576d8097e495 h1:jrt4qbJVEFs4H93/ITxygHc6u0TGqAkkate7TQ4wFSA=
github.com/tree-sitter/tree-sitter-java v0.21.1-0.20240824015150-576d8097e495/go.mod h1:oyaR7fLnRV0hT9z6qwE9GkaeTom/hTDwK3H2idcOJFc=
github.com/tree-sitter/tree-sitter-javascript v0.21.5-0.20240818005344-15887341e5b5 h1:om4X9AVg3asL8gxNJDcz4e/Wp+VpQj1PY3uJXKr6EOg=
github.com/tree-sitter/tree-sitter-javascript v0.21.5-0.20240818005344-15887341e5b5/go.mod h1:nNqgPoV/h9uYWk6kYEFdEAhNVOacpfpRW5SFmdaP4tU=
github.com/tree-sitter/tree-sitter-json v0.21.1-0.20240818005659-bdd69eb8c8a5 h1:pfV3G3k7NCKqKk8THBmyuh2zA33lgYHS3GVrzRR8ry4=
github.com/tree-sitter/tree-sitter-json v0.21.1-0.20240818005659-bdd69eb8c8a5/go.mod h1:GbMKRjLfk0H+PI7nLi1Sx5lHf5wCpLz9al8tQYSxpEk=
github.com/tree-sitter/tree-sitter-php v0.22.9-0.20240819002312-a552625b56c1 h1:ZXZMDwE+IhUtGug4Brv6NjJWUU3rfkZBKpemf6RY8/g=
github.com/tree-sitter/tree-sitter-php v0.22.9-0.20240819002312-a552625b56c1/go.mod h1:UKCLuYnJ312Mei+3cyTmGOHzn0YAnaPRECgJmHtzrqs=
github.com/tree-sitter/tree-sitter-python v0.21.1-0.20240818005537-55a9b8a4fbfb h1:EXEM82lFM7JjJb6qiKZXkpIDaCcbV2obNn82ghwj9lw=
github.com/tree-sitter/tree-sitter-python v0.21.1-0.20240818005537-55a9b8a4fbfb/go.mod h1:lXCF1nGG5Dr4J3BTS0ObN4xJCCICiSu/b+Xe/VqMV7g=
github.com/tree-sitter/tree-sitter-ruby v0.21.1-0.20240818211811-7dbc1e2d0e2d h1:fcYCvoXdcP1uRQYXqJHRy6Hec+uKScQdKVtMwK9JeCI=
github.com/tree-sitter/tree-sitter-ruby v0.21.1-0.20240818211811-7dbc1e2d0e2d/go.mod h1:T1nShQ4v5AJtozZ8YyAS4uzUtDAJj/iv4YfwXSbUHzg=
github.com/tree-sitter/tree-sitter-rust v0.21.3-0.20240818005432-2b43eafe6447 h1:o9alBu1J/WjrcTKEthYtXmdkDc5OVXD+PqlvnEZ0Lzc=
github.com/tree-sitter/tree-sitter-rust v0.21.3-0.20240818005432-2b43eafe6447/go.mod h1:1Oh95COkkTn6Ezp0vcMbvfhRP5gLeqqljR0BYnBzWvc=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=



================================================
FILE: grammar.js
================================================
/**
 * @file C++ grammar for tree-sitter
 * @author Max Brunsfeld <maxbrunsfeld@gmail.com>
 * @author Amaan Qureshi <amaanq12@gmail.com>
 * @author John Drouhard <john@drouhard.dev>
 * @author Pablo Hugen <pabloashugen@protonmail.com>
 * @license MIT
 */

/// <reference types="tree-sitter-cli/dsl" />
// @ts-check

const C = require('tree-sitter-c/grammar');

const PREC = Object.assign(C.PREC, {
  LAMBDA: 18,
  NEW: C.PREC.CALL + 1,
  STRUCTURED_BINDING: -1,
  THREE_WAY: C.PREC.RELATIONAL + 1,
});

const FOLD_OPERATORS = [
  '+', '-', '*', '/', '%',
  '^', '&', '|',
  '=', '<', '>',
  '<<', '>>',
  '+=', '-=', '*=', '/=', '%=', '^=', '&=', '|=',
  '>>=', '<<=',
  '==', '!=', '<=', '>=',
  '&&', '||',
  ',',
  '.*', '->*',
  'or', 'and', 'bitor', 'xor', 'bitand', 'not_eq',
];

const ASSIGNMENT_OPERATORS = [
  '=',
  '*=',
  '/=',
  '%=',
  '+=',
  '-=',
  '<<=',
  '>>=',
  '&=',
  '^=',
  '|=',
  'and_eq',
  'or_eq',
  'xor_eq',
];

module.exports = grammar(C, {
  name: 'cpp',

  externals: $ => [
    $.raw_string_delimiter,
    $.raw_string_content,
  ],

  conflicts: $ => [
    // C
    [$.type_specifier, $._declarator],
    [$.type_specifier, $.expression],
    [$.sized_type_specifier],
    [$.attributed_statement],
    [$._declaration_modifiers, $.attributed_statement],
    [$._declaration_modifiers, $.using_declaration],
    [$._declaration_modifiers, $.attributed_statement, $.using_declaration],
    [$._top_level_item, $._top_level_statement],
    [$._block_item, $.statement],
    [$.type_qualifier, $.extension_expression],

    // C++
    [$.template_function, $.template_type],
    [$.template_function, $.template_type, $.expression],
    [$.template_function, $.template_type, $.qualified_identifier],
    [$.template_type, $.qualified_type_identifier],
    [$.qualified_type_identifier, $.qualified_identifier],
    [$.comma_expression, $.initializer_list],
    [$.expression, $._declarator],
    [$.expression, $.structured_binding_declarator],
    [$.expression, $._declarator, $.type_specifier],
    [$.expression, $.identifier_parameter_pack_expansion],
    [$.expression, $._lambda_capture_identifier],
    [$.expression, $._lambda_capture],
    [$.expression, $.structured_binding_declarator, $._lambda_capture_identifier],
    [$.structured_binding_declarator, $._lambda_capture_identifier],
    [$.parameter_list, $.argument_list],
    [$.type_specifier, $.call_expression],
    [$._declaration_specifiers, $._constructor_specifiers],
    [$._binary_fold_operator, $._fold_operator],
    [$._function_declarator_seq],
    [$.type_specifier, $.sized_type_specifier],
    [$.initializer_pair, $.comma_expression],
    [$.expression_statement, $._for_statement_body],
    [$.init_statement, $._for_statement_body],
    [$.field_expression, $.template_method, $.template_type],
    [$.qualified_field_identifier, $.template_method, $.template_type],
  ],

  inline: ($, original) => original.concat([
    $._namespace_identifier,
  ]),

  precedences: $ => [
    [$.argument_list, $.type_qualifier],
    [$._expression_not_binary, $._class_name],
  ],

  rules: {
    _top_level_item: ($, original) => choice(
      ...original.members.filter((member) => member.content?.name != '_old_style_function_definition'),
      $.namespace_definition,
      $.concept_definition,
      $.namespace_alias_definition,
      $.using_declaration,
      $.alias_declaration,
      $.static_assert_declaration,
      $.template_declaration,
      $.template_instantiation,
      $.module_declaration,
      $.export_declaration,
      $.import_declaration,
      $.global_module_fragment_declaration,
      $.private_module_fragment_declaration,
      alias($.constructor_or_destructor_definition, $.function_definition),
      alias($.operator_cast_definition, $.function_definition),
      alias($.operator_cast_declaration, $.declaration),
    ),
    _block_item: ($, original) => choice(
      ...original.members.filter((member) => member.content?.name != '_old_style_function_definition'),
      $.namespace_definition,
      $.concept_definition,
      $.namespace_alias_definition,
      $.using_declaration,
      $.alias_declaration,
      $.static_assert_declaration,
      $.template_declaration,
      $.template_instantiation,
      alias($.constructor_or_destructor_definition, $.function_definition),
      alias($.operator_cast_definition, $.function_definition),
      alias($.operator_cast_declaration, $.declaration),
    ),

    // Types

    placeholder_type_specifier: $ => prec(1, seq(
      field('constraint', optional(choice(
        alias($.qualified_type_identifier, $.qualified_identifier),
        $.template_type,
        $._type_identifier,
      ))),
      choice($.auto, alias($.decltype_auto, $.decltype)),
    )),

    auto: _ => 'auto',
    decltype_auto: $ => seq(
      'decltype',
      '(',
      $.auto,
      ')',
    ),
    decltype: $ => seq(
      'decltype',
      '(',
      $.expression,
      ')',
    ),

    type_specifier: $ => choice(
      $.struct_specifier,
      $.union_specifier,
      $.enum_specifier,
      $.class_specifier,
      $.sized_type_specifier,
      $.primitive_type,
      $.template_type,
      $.dependent_type,
      $.placeholder_type_specifier,
      $.decltype,
      prec.right(choice(
        alias($.qualified_type_identifier, $.qualified_identifier),
        $._type_identifier,
      )),
    ),

    type_qualifier: (_, original) => choice(
      original,
      'mutable',
      'constinit',
      'consteval',
    ),

    type_descriptor: (_, original) => prec.right(original),

    attribute: ($, original) => seq(
      optional(seq('using', field('namespace', $.identifier), ':')),
      ...original.members,
    ),

    // When used in a trailing return type, these specifiers can now occur immediately before
    // a compound statement. This introduces a shift/reduce conflict that needs to be resolved
    // with an associativity.
    _class_declaration: $ => seq(
      repeat(choice($.attribute_specifier, $.alignas_qualifier)),
      optional($.ms_declspec_modifier),
      repeat($.attribute_declaration),
      $._class_declaration_item,
    ),
    _class_declaration_item: $ => prec.right(seq(
      choice(
        field('name', $._class_name),
        seq(
          optional(field('name', $._class_name)),
          optional($.virtual_specifier),
          optional($.base_class_clause),
          field('body', $.field_declaration_list),
        ),
      ),
      optional($.attribute_specifier),
    )),

    class_specifier: $ => seq(
      'class',
      $._class_declaration,
    ),

    union_specifier: $ => seq(
      'union',
      $._class_declaration,
    ),

    struct_specifier: $ => seq(
      'struct',
      $._class_declaration,
    ),

    _class_name: $ => prec.right(choice(
      $._type_identifier,
      $.template_type,
      alias($.qualified_type_identifier, $.qualified_identifier),
    )),

    function_definition: ($, original) => ({
      ...original,
      members: original.members.map(
        (e) => e.name !== 'body' ?
          e :
          field('body', choice(e.content, $.try_statement))),
    }),

    declaration: $ => seq(
      $._declaration_specifiers,
      commaSep1(field('declarator', choice(
        seq(
          // C uses _declaration_declarator here for some nice macro parsing in function declarators,
          // but this causes a world of pain for C++ so we'll just stick to the normal _declarator here.
          optional($.ms_call_modifier),
          $._declarator,
          optional($.gnu_asm_expression),
        ),
        $.init_declarator,
      ))),
      ';',
    ),

    virtual_specifier: _ => choice(
      'final', // the only legal value here for classes
      'override', // legal for functions in addition to final, plus permutations.
    ),

    _declaration_modifiers: ($, original) => choice(
      original,
      'virtual',
    ),

    explicit_function_specifier: $ => choice(
      'explicit',
      prec(PREC.CALL, seq(
        'explicit',
        '(',
        $.expression,
        ')',
      )),
    ),

    base_class_clause: $ => seq(
      ':',
      commaSep1(seq(
        repeat($.attribute_declaration),
        optional(choice(
          $.access_specifier,
          seq($.access_specifier, optional('virtual')),
          seq('virtual', optional($.access_specifier)),
        )),
        $._class_name,
        optional('...'),
      )),
    ),

    enum_specifier: $ => prec.right(seq(
      'enum',
      optional(choice('class', 'struct')),
      choice(
        seq(
          field('name', $._class_name),
          optional($._enum_base_clause),
          optional(field('body', $.enumerator_list)),
        ),
        field('body', $.enumerator_list),
      ),
      optional($.attribute_specifier),
    )),

    _enum_base_clause: $ => prec.left(seq(
      ':',
      field('base', choice(
        alias($.qualified_type_identifier, $.qualified_identifier),
        $._type_identifier,
        $.primitive_type,
        $.sized_type_specifier,
      )),
    )),

    // The `auto` storage class is removed in C++0x in order to allow for the `auto` type.
    storage_class_specifier: (_, original) => choice(
      ...original.members.filter((member) => member.value !== 'auto'),
      'thread_local',
    ),

    dependent_type: $ => prec.dynamic(-1, prec.right(seq(
      'typename',
      $.type_specifier,
    ))),

    // Declarations

    module_name: $ => seq(
      $.identifier,
      repeat(seq('.', $.identifier),
      ),
    ),

    module_partition: $ => seq(
      ':',
      $.module_name,
    ),

    module_declaration: $ => seq(
      optional('export'),
      'module',
      field('name', $.module_name),
      field('partition', optional($.module_partition)),
      optional($.attribute_declaration),
      ';',
    ),

    export_declaration: $ => seq(
      'export',
      choice($._block_item, seq('{', repeat($._block_item), '}')),
    ),

    import_declaration: $ => seq(
      optional('export'),
      'import',
      choice(
        field('name', $.module_name),
        field('partition', $.module_partition),
        field('header', choice(
          $.string_literal,
          $.system_lib_string,
        )),
      ),
      optional($.attribute_declaration),
      ';',
    ),

    global_module_fragment_declaration: _ => seq('module', ';'),
    private_module_fragment_declaration: _ => seq('module', ':', 'private', ';'),

    template_declaration: $ => seq(
      'template',
      field('parameters', $.template_parameter_list),
      optional($.requires_clause),
      choice(
        $._empty_declaration,
        $.alias_declaration,
        $.declaration,
        $.template_declaration,
        $.function_definition,
        $.concept_definition,
        $.friend_declaration,
        alias($.constructor_or_destructor_declaration, $.declaration),
        alias($.constructor_or_destructor_definition, $.function_definition),
        alias($.operator_cast_declaration, $.declaration),
        alias($.operator_cast_definition, $.function_definition),
      ),
    ),

    template_instantiation: $ => prec(1, seq(
      optional('extern'),
      'template',
      optional($._declaration_specifiers),
      field('declarator', $._declarator),
      ';',
    )),

    template_parameter_list: $ => seq(
      '<',
      commaSep(choice(
        $.parameter_declaration,
        $.optional_parameter_declaration,
        $.type_parameter_declaration,
        $.variadic_parameter_declaration,
        $.variadic_type_parameter_declaration,
        $.optional_type_parameter_declaration,
        $.template_template_parameter_declaration,
      )),
      alias(token(prec(1, '>')), '>'),
    ),

    type_parameter_declaration: $ => prec(1, seq(
      choice('typename', 'class'),
      optional($._type_identifier),
    )),

    variadic_type_parameter_declaration: $ => prec(1, seq(
      choice('typename', 'class'),
      '...',
      optional($._type_identifier),
    )),

    optional_type_parameter_declaration: $ => seq(
      choice('typename', 'class'),
      optional(field('name', $._type_identifier)),
      '=',
      field('default_type', $.type_specifier),
    ),

    template_template_parameter_declaration: $ => seq(
      'template',
      field('parameters', $.template_parameter_list),
      choice(
        $.type_parameter_declaration,
        $.variadic_type_parameter_declaration,
        $.optional_type_parameter_declaration,
      ),
    ),

    parameter_list: $ => seq(
      '(',
      commaSep(choice(
        $.parameter_declaration,
        $.explicit_object_parameter_declaration,
        $.optional_parameter_declaration,
        $.variadic_parameter_declaration,
        '...',
      )),
      ')',
    ),

    explicit_object_parameter_declaration: $ => seq(
      $.this,
      $.parameter_declaration,
    ),

    optional_parameter_declaration: $ => seq(
      $._declaration_specifiers,
      field('declarator', optional(choice($._declarator, $.abstract_reference_declarator))),
      '=',
      field('default_value', $.expression),
    ),

    variadic_parameter_declaration: $ => seq(
      $._declaration_specifiers,
      field('declarator', choice(
        $.variadic_declarator,
        alias($.variadic_reference_declarator, $.reference_declarator),
      )),
    ),

    variadic_declarator: $ => seq(
      '...',
      optional($.identifier),
    ),

    variadic_reference_declarator: $ => seq(
      choice('&&', '&'),
      $.variadic_declarator,
    ),

    init_declarator: ($, original) => choice(
      original,
      seq(
        field('declarator', $._declarator),
        field('value', choice(
          $.argument_list,
          $.initializer_list,
        )),
      ),
    ),

    operator_cast: $ => prec.right(1, seq(
      'operator',
      $._declaration_specifiers,
      field('declarator', $._abstract_declarator),
    )),

    // Avoid ambiguity between compound statement and initializer list in a construct like:
    //   A b {};
    compound_statement: (_, original) => prec(-1, original),

    field_initializer_list: $ => seq(
      ':',
      commaSep1($.field_initializer),
    ),

    field_initializer: $ => prec(1, seq(
      choice(
        $._field_identifier,
        $.template_method,
        alias($.qualified_field_identifier, $.qualified_identifier),
      ),
      choice($.initializer_list, $.argument_list),
      optional('...'),
    )),

    _field_declaration_list_item: ($, original) => choice(
      original,
      $.template_declaration,
      alias($.inline_method_definition, $.function_definition),
      alias($.constructor_or_destructor_definition, $.function_definition),
      alias($.constructor_or_destructor_declaration, $.declaration),
      alias($.operator_cast_definition, $.function_definition),
      alias($.operator_cast_declaration, $.declaration),
      $.friend_declaration,
      seq($.access_specifier, ':'),
      $.alias_declaration,
      $.using_declaration,
      $.type_definition,
      $.static_assert_declaration,
      ';',
    ),

    field_declaration: $ => seq(
      $._declaration_specifiers,
      commaSep(seq(
        field('declarator', $._field_declarator),
        optional(choice(
          $.bitfield_clause,
          field('default_value', $.initializer_list),
          seq('=', field('default_value', choice($.expression, $.initializer_list))),
        )),
      )),
      optional($.attribute_specifier),
      ';',
    ),

    inline_method_definition: $ => seq(
      $._declaration_specifiers,
      field('declarator', $._field_declarator),
      choice(
        field('body', choice($.compound_statement, $.try_statement)),
        $.default_method_clause,
        $.delete_method_clause,
        $.pure_virtual_clause,
      ),
    ),

    _constructor_specifiers: $ => choice(
      $._declaration_modifiers,
      $.explicit_function_specifier,
    ),

    operator_cast_definition: $ => seq(
      repeat($._constructor_specifiers),
      field('declarator', choice(
        $.operator_cast,
        alias($.qualified_operator_cast_identifier, $.qualified_identifier),
      )),
      field('body', choice($.compound_statement, $.try_statement)),
    ),

    operator_cast_declaration: $ => prec(1, seq(
      repeat($._constructor_specifiers),
      field('declarator', choice(
        $.operator_cast,
        alias($.qualified_operator_cast_identifier, $.qualified_identifier),
      )),
      optional(seq('=', field('default_value', $.expression))),
      ';',
    )),

    constructor_try_statement: $ => seq(
      'try',
      optional($.field_initializer_list),
      field('body', $.compound_statement),
      repeat1($.catch_clause),
    ),

    constructor_or_destructor_definition: $ => seq(
      repeat($._constructor_specifiers),
      field('declarator', $.function_declarator),
      choice(
        seq(
          optional($.field_initializer_list),
          field('body', $.compound_statement),
        ),
        alias($.constructor_try_statement, $.try_statement),
        $.default_method_clause,
        $.delete_method_clause,
        $.pure_virtual_clause,
      ),
    ),

    constructor_or_destructor_declaration: $ => seq(
      repeat($._constructor_specifiers),
      field('declarator', $.function_declarator),
      ';',
    ),

    default_method_clause: _ => seq('=', 'default', ';'),
    delete_method_clause: _ => seq('=', 'delete', ';'),
    pure_virtual_clause: _ => seq('=', /0/, ';'),

    friend_declaration: $ => seq(
      optional('constexpr'),
      'friend',
      choice(
        $.declaration,
        $.function_definition,
        seq(
          optional(choice(
            'class',
            'struct',
            'union',
          )),
          $._class_name, ';',
        ),
      ),
    ),

    access_specifier: _ => choice(
      'public',
      'private',
      'protected',
    ),

    _declarator: ($, original) => choice(
      original,
      $.reference_declarator,
      $.qualified_identifier,
      $.template_function,
      $.operator_name,
      $.destructor_name,
      $.structured_binding_declarator,
    ),

    _field_declarator: ($, original) => choice(
      original,
      alias($.reference_field_declarator, $.reference_declarator),
      $.template_method,
      $.operator_name,
    ),

    _type_declarator: ($, original) => choice(
      original,
      alias($.reference_type_declarator, $.reference_declarator),
    ),

    _abstract_declarator: ($, original) => choice(
      original,
      $.abstract_reference_declarator,
    ),

    reference_declarator: $ => prec.dynamic(1, prec.right(seq(choice('&', '&&'), $._declarator))),
    reference_field_declarator: $ => prec.dynamic(1, prec.right(seq(choice('&', '&&'), $._field_declarator))),
    reference_type_declarator: $ => prec.dynamic(1, prec.right(seq(choice('&', '&&'), $._type_declarator))),
    abstract_reference_declarator: $ => prec.right(seq(choice('&', '&&'), optional($._abstract_declarator))),

    structured_binding_declarator: $ => prec.dynamic(PREC.STRUCTURED_BINDING, seq(
      '[', commaSep1($.identifier), ']',
    )),

    ref_qualifier: _ => choice('&', '&&'),

    _function_declarator_seq: $ => seq(
      field('parameters', $.parameter_list),
      optional($._function_attributes_start),
      optional($.ref_qualifier),
      optional($._function_exception_specification),
      optional($._function_attributes_end),
      optional($.trailing_return_type),
      optional($._function_postfix),
    ),

    _function_attributes_start: $ => prec(1, choice(
      seq(repeat1($.attribute_specifier), repeat($.type_qualifier)),
      seq(repeat($.attribute_specifier), repeat1($.type_qualifier)),
    )),

    _function_exception_specification: $ => choice(
      $.noexcept,
      $.throw_specifier,
    ),

    _function_attributes_end: $ => prec.right(seq(
      optional($.gnu_asm_expression),
      choice(
        seq(repeat1($.attribute_specifier), repeat($.attribute_declaration)),
        seq(repeat($.attribute_specifier), repeat1($.attribute_declaration)),
      ),
    )),

    _function_postfix: $ => prec.right(choice(
      repeat1($.virtual_specifier),
      $.requires_clause,
    )),

    function_declarator: $ => prec.dynamic(1, seq(
      field('declarator', $._declarator),
      $._function_declarator_seq,
    )),

    function_field_declarator: $ => prec.dynamic(1, seq(
      field('declarator', $._field_declarator),
      $._function_declarator_seq,
    )),

    abstract_function_declarator: $ => seq(
      field('declarator', optional($._abstract_declarator)),
      $._function_declarator_seq,
    ),

    trailing_return_type: $ => seq('->', $.type_descriptor),

    noexcept: $ => prec.right(seq(
      'noexcept',
      optional(
        seq(
          '(',
          optional($.expression),
          ')',
        ),
      ),
    )),

    throw_specifier: $ => seq(
      'throw',
      seq(
        '(',
        commaSep($.type_descriptor),
        ')',
      ),
    ),

    template_type: $ => seq(
      field('name', $._type_identifier),
      field('arguments', $.template_argument_list),
    ),

    template_method: $ => seq(
      field('name', choice($._field_identifier, $.operator_name)),
      field('arguments', $.template_argument_list),
    ),

    template_function: $ => seq(
      field('name', $.identifier),
      field('arguments', $.template_argument_list),
    ),

    template_argument_list: $ => seq(
      '<',
      commaSep(choice(
        prec.dynamic(3, $.type_descriptor),
        prec.dynamic(2, alias($.type_parameter_pack_expansion, $.parameter_pack_expansion)),
        prec.dynamic(1, $.expression),
      )),
      alias(token(prec(1, '>')), '>'),
    ),

    namespace_definition: $ => seq(
      optional('inline'),
      'namespace',
      optional($.attribute_declaration),
      field('name', optional(
        choice(
          $._namespace_identifier,
          $.nested_namespace_specifier,
        ))),
      field('body', $.declaration_list),
    ),

    namespace_alias_definition: $ => seq(
      'namespace',
      field('name', $._namespace_identifier),
      '=',
      choice(
        $._namespace_identifier,
        $.nested_namespace_specifier,
      ),
      ';',
    ),

    _namespace_specifier: $ => seq(
      optional('inline'),
      $._namespace_identifier,
    ),

    nested_namespace_specifier: $ => prec(1, seq(
      optional($._namespace_specifier),
      '::',
      choice(
        $.nested_namespace_specifier,
        $._namespace_specifier,
      ),
    )),

    using_declaration: $ => seq(
      repeat($.attribute_declaration),
      'using',
      optional(choice('namespace', 'enum')),
      choice(
        $.identifier,
        $.qualified_identifier,
      ),
      ';',
    ),

    alias_declaration: $ => seq(
      'using',
      field('name', $._type_identifier),
      repeat($.attribute_declaration),
      '=',
      field('type', $.type_descriptor),
      ';',
    ),

    static_assert_declaration: $ => seq(
      'static_assert',
      '(',
      field('condition', $.expression),
      optional(seq(
        ',',
        field('message', $._string),
      )),
      ')',
      ';',
    ),

    concept_definition: $ => seq(
      'concept',
      field('name', $.identifier),
      '=',
      $.expression,
      ';',
    ),

    // Statements

    _top_level_statement: ($, original) => choice(
      original,
      $.co_return_statement,
      $.co_yield_statement,
      $.for_range_loop,
      $.try_statement,
      $.throw_statement,
    ),

    _non_case_statement: ($, original) => choice(
      original,
      $.co_return_statement,
      $.co_yield_statement,
      $.for_range_loop,
      $.try_statement,
      $.throw_statement,
    ),

    switch_statement: $ => seq(
      'switch',
      field('condition', $.condition_clause),
      field('body', $.compound_statement),
    ),

    while_statement: $ => seq(
      'while',
      field('condition', $.condition_clause),
      field('body', $.statement),
    ),

    if_statement: $ => prec.right(seq(
      'if',
      optional('constexpr'),
      field('condition', $.condition_clause),
      field('consequence', $.statement),
      optional(field('alternative', $.else_clause)),
    )),

    // Using prec(1) instead of prec.dynamic(1) causes issues with the
    // range loop's declaration specifiers if `int` is passed in, it'll
    // always prefer the standard for loop and give us a parse error.
    _for_statement_body: ($, original) => prec.dynamic(1, original),
    for_range_loop: $ => seq(
      'for',
      '(',
      $._for_range_loop_body,
      ')',
      field('body', $.statement),
    ),
    _for_range_loop_body: $ => seq(
      field('initializer', optional($.init_statement)),
      $._declaration_specifiers,
      field('declarator', $._declarator),
      ':',
      field('right', choice(
        $.expression,
        $.initializer_list,
      )),
    ),

    init_statement: $ => choice(
      $.alias_declaration,
      $.type_definition,
      $.declaration,
      $.expression_statement,
    ),

    condition_clause: $ => seq(
      '(',
      field('initializer', optional($.init_statement)),
      field('value', choice(
        $.expression,
        $.comma_expression,
        alias($.condition_declaration, $.declaration),
      )),
      ')',
    ),

    condition_declaration: $ => seq(
      $._declaration_specifiers,
      field('declarator', $._declarator),
      choice(
        seq(
          '=',
          field('value', $.expression),
        ),
        field('value', $.initializer_list),
      ),
    ),

    return_statement: ($, original) => seq(
      choice(
        original,
        seq('return', $.initializer_list, ';'),
      ),
    ),

    co_return_statement: $ => seq(
      'co_return',
      optional($.expression),
      ';',
    ),

    co_yield_statement: $ => seq(
      'co_yield',
      $.expression,
      ';',
    ),

    throw_statement: $ => seq(
      'throw',
      optional($.expression),
      ';',
    ),

    try_statement: $ => seq(
      'try',
      field('body', $.compound_statement),
      repeat1($.catch_clause),
    ),

    catch_clause: $ => seq(
      'catch',
      field('parameters', $.parameter_list),
      field('body', $.compound_statement),
    ),

    // Expressions

    _expression_not_binary: ($, original) => choice(
      original,
      $.co_await_expression,
      $.requires_expression,
      $.requires_clause,
      $.template_function,
      $.qualified_identifier,
      $.new_expression,
      $.delete_expression,
      $.lambda_expression,
      $.parameter_pack_expansion,
      $.this,
      $.user_defined_literal,
      $.fold_expression,
    ),

    _string: $ => choice(
      $.string_literal,
      $.raw_string_literal,
      $.concatenated_string,
    ),

    raw_string_literal: $ => seq(
      choice('R"', 'LR"', 'uR"', 'UR"', 'u8R"'),
      choice(
        seq(
          field('delimiter', $.raw_string_delimiter),
          '(',
          $.raw_string_content,
          ')',
          $.raw_string_delimiter,
        ),
        seq('(', $.raw_string_content, ')'),
      ),
      '"',
    ),

    subscript_expression: $ => prec(PREC.SUBSCRIPT, seq(
      field('argument', $.expression),
      field('indices', $.subscript_argument_list),
    )),

    subscript_argument_list: $ => seq(
      '[',
      commaSep(choice($.expression, $.initializer_list)),
      ']',
    ),

    call_expression: ($, original) => choice(original, seq(
      field('function', $.primitive_type),
      field('arguments', $.argument_list),
    )),

    co_await_expression: $ => prec.left(PREC.UNARY, seq(
      field('operator', 'co_await'),
      field('argument', $.expression),
    )),

    new_expression: $ => prec.right(PREC.NEW, seq(
      optional('::'),
      'new',
      field('placement', optional($.argument_list)),
      field('type', $.type_specifier),
      field('declarator', optional($.new_declarator)),
      field('arguments', optional(choice(
        $.argument_list,
        $.initializer_list,
      ))),
    )),

    new_declarator: $ => prec.right(seq(
      '[',
      field('length', $.expression),
      ']',
      optional($.new_declarator),
    )),

    delete_expression: $ => seq(
      optional('::'),
      'delete',
      optional(seq('[', ']')),
      $.expression,
    ),

    field_expression: $ => seq(
      prec(PREC.FIELD, seq(
        field('argument', $.expression),
        field('operator', choice('.', '.*', '->')),
      )),
      field('field', choice(
        prec.dynamic(1, $._field_identifier),
        alias($.qualified_field_identifier, $.qualified_identifier),
        $.destructor_name,
        $.template_method,
        alias($.dependent_field_identifier, $.dependent_name),
      )),
    ),

    type_requirement: $ => seq('typename', $._class_name),

    compound_requirement: $ => seq(
      '{', $.expression, '}',
      optional('noexcept'),
      optional($.trailing_return_type),
      ';',
    ),

    _requirement: $ => choice(
      alias($.expression_statement, $.simple_requirement),
      $.type_requirement,
      $.compound_requirement,
    ),

    requirement_seq: $ => seq('{', repeat($._requirement), '}'),

    constraint_conjunction: $ => prec.left(PREC.LOGICAL_AND, seq(
      field('left', $._requirement_clause_constraint),
      field('operator', choice('&&', 'and')),
      field('right', $._requirement_clause_constraint)),
    ),

    constraint_disjunction: $ => prec.left(PREC.LOGICAL_OR, seq(
      field('left', $._requirement_clause_constraint),
      field('operator', choice('||', 'or')),
      field('right', $._requirement_clause_constraint)),
    ),

    _requirement_clause_constraint: $ => choice(
      // Primary expressions"
      $.true,
      $.false,
      $._class_name,
      $.fold_expression,
      $.lambda_expression,
      $.requires_expression,

      // Parenthesized expressions
      seq('(', $.expression, ')'),

      // conjunction or disjunction of the above
      $.constraint_conjunction,
      $.constraint_disjunction,
    ),

    requires_clause: $ => seq(
      'requires',
      field('constraint', $._requirement_clause_constraint),
    ),

    requires_parameter_list: $ => seq(
      '(',
      commaSep(choice(
        $.parameter_declaration,
        $.optional_parameter_declaration,
        $.variadic_parameter_declaration,
      )),
      ')',
    ),

    requires_expression: $ => seq(
      'requires',
      field('parameters', optional(alias($.requires_parameter_list, $.parameter_list))),
      field('requirements', $.requirement_seq),
    ),

    lambda_specifier: $ => choice(
      'static',
      'constexpr',
      'consteval',
      'mutable',
    ),

    lambda_declarator: $ => choice(
      // main declarator form, includes parameter list
      seq(
        repeat($.attribute_declaration),
        field('parameters', $.parameter_list),
        repeat($.lambda_specifier),
        optional($._function_exception_specification),
        repeat($.attribute_declaration),
        optional($.trailing_return_type),
        optional($.requires_clause),
      ),

      // forms supporting omitted parameter list
      repeat1($.attribute_declaration),
      seq(
        repeat($.attribute_declaration),
        $.trailing_return_type,
      ),
      seq(
        repeat($.attribute_declaration),
        $._function_exception_specification,
        repeat($.attribute_declaration),
        optional($.trailing_return_type),
      ),
      seq(
        repeat($.attribute_declaration),
        repeat1($.lambda_specifier),
        optional($._function_exception_specification),
        repeat($.attribute_declaration),
        optional($.trailing_return_type),
      ),
    ),

    lambda_expression: $ => seq(
      field('captures', $.lambda_capture_specifier),
      optional(seq(
        field('template_parameters', $.template_parameter_list),
        optional(field('constraint', $.requires_clause)),
      )),
      optional(field('declarator', $.lambda_declarator)),
      field('body', $.compound_statement),
    ),

    lambda_capture_specifier: $ => prec(PREC.LAMBDA, seq(
      '[',
      choice(
        $.lambda_default_capture,
        commaSep($._lambda_capture),
        seq(
          $.lambda_default_capture,
          ',', commaSep1($._lambda_capture),
        ),
      ),
      ']',
    )),

    lambda_default_capture: _ => choice('=', '&'),

    _lambda_capture_identifier: $ => seq(
      optional('&'),
      choice(
        $.identifier,
        $.qualified_identifier,
        alias($.identifier_parameter_pack_expansion, $.parameter_pack_expansion),
      ),
    ),

    lambda_capture_initializer: $ => seq(
      optional('&'),
      optional('...'),
      field('left', $.identifier),
      '=',
      field('right', $.expression),
    ),

    _lambda_capture: $ => choice(
      seq(optional('*'), $.this),
      $._lambda_capture_identifier,
      $.lambda_capture_initializer,
    ),

    _fold_operator: _ => choice(...FOLD_OPERATORS),
    _binary_fold_operator: _ => choice(...FOLD_OPERATORS.map((operator) => seq(field('operator', operator), '...', operator))),

    _unary_left_fold: $ => seq(
      field('left', '...'),
      field('operator', $._fold_operator),
      field('right', $.expression),
    ),
    _unary_right_fold: $ => seq(
      field('left', $.expression),
      field('operator', $._fold_operator),
      field('right', '...'),
    ),
    _binary_fold: $ => seq(
      field('left', $.expression),
      $._binary_fold_operator,
      field('right', $.expression),
    ),

    fold_expression: $ => seq(
      '(',
      choice(
        $._unary_right_fold,
        $._unary_left_fold,
        $._binary_fold,
      ),
      ')',
    ),

    parameter_pack_expansion: $ => prec(-1, seq(
      field('pattern', $.expression),
      '...',
    )),

    type_parameter_pack_expansion: $ => seq(
      field('pattern', $.type_descriptor),
      '...',
    ),

    identifier_parameter_pack_expansion: $ => seq(
      field('pattern', $.identifier),
      '...',
    ),

    sizeof_expression: ($, original) => prec.right(PREC.SIZEOF, choice(
      original,
      seq(
        'sizeof', '...',
        '(',
        field('value', $.identifier),
        ')',
      ),
    )),

    unary_expression: ($, original) => choice(
      original,
      prec.left(PREC.UNARY, seq(
        field('operator', choice('not', 'compl')),
        field('argument', $.expression),
      )),
    ),

    binary_expression: ($, original) => {
      const table = [
        ['<=>', PREC.THREE_WAY],
        ['or', PREC.LOGICAL_OR],
        ['and', PREC.LOGICAL_AND],
        ['bitor', PREC.INCLUSIVE_OR],
        ['xor', PREC.EXCLUSIVE_OR],
        ['bitand', PREC.BITWISE_AND],
        ['not_eq', PREC.EQUAL],
      ];

      return choice(
        original,
        ...table.map(([operator, precedence]) => {
          return prec.left(precedence, seq(
            field('left', $.expression),
            // @ts-ignore
            field('operator', operator),
            field('right', $.expression),
          ));
        }));
    },

    // The compound_statement is added to parse macros taking statements as arguments, e.g. MYFORLOOP(1, 10, i, { foo(i); bar(i); })
    argument_list: $ => seq(
      '(',
      commaSep(choice($.expression, $.initializer_list, $.compound_statement)),
      ')',
    ),

    destructor_name: $ => prec(1, seq('~', $.identifier)),

    compound_literal_expression: ($, original) => choice(
      original,
      seq(
        field('type', choice($._class_name, $.primitive_type)),
        field('value', $.initializer_list),
      ),
    ),

    dependent_identifier: $ => seq('template', $.template_function),
    dependent_field_identifier: $ => seq('template', $.template_method),
    dependent_type_identifier: $ => seq('template', $.template_type),

    _scope_resolution: $ => prec(1, seq(
      field('scope', optional(choice(
        $._namespace_identifier,
        $.template_type,
        $.decltype,
        alias($.dependent_type_identifier, $.dependent_name),
      ))),
      '::',
    )),

    qualified_field_identifier: $ => seq(
      $._scope_resolution,
      field('name', choice(
        alias($.dependent_field_identifier, $.dependent_name),
        alias($.qualified_field_identifier, $.qualified_identifier),
        $.template_method,
        prec.dynamic(1, $._field_identifier),
      )),
    ),

    qualified_identifier: $ => seq(
      $._scope_resolution,
      field('name', choice(
        alias($.dependent_identifier, $.dependent_name),
        $.qualified_identifier,
        $.template_function,
        seq(optional('template'), $.identifier),
        $.operator_name,
        $.destructor_name,
        $.pointer_type_declarator,
      )),
    ),

    qualified_type_identifier: $ => seq(
      $._scope_resolution,
      field('name', choice(
        alias($.dependent_type_identifier, $.dependent_name),
        alias($.qualified_type_identifier, $.qualified_identifier),
        $.template_type,
        $._type_identifier,
      )),
    ),

    qualified_operator_cast_identifier: $ => seq(
      $._scope_resolution,
      field('name', choice(
        alias($.qualified_operator_cast_identifier, $.qualified_identifier),
        $.operator_cast,
      )),
    ),

    _assignment_left_expression: ($, original) => choice(
      original,
      $.qualified_identifier,
      $.user_defined_literal,
    ),

    assignment_expression: $ => prec.right(PREC.ASSIGNMENT, seq(
      field('left', $._assignment_left_expression),
      field('operator', choice(...ASSIGNMENT_OPERATORS)),
      field('right', choice($.expression, $.initializer_list)),
    )),

    _assignment_expression_lhs: $ => seq(
      field('left', $.expression),
      field('operator', choice(...ASSIGNMENT_OPERATORS)),
      field('right', choice($.expression, $.initializer_list)),
    ),

    // This prevents an ambiguity between fold expressions
    // and assignment expressions within parentheses.
    parenthesized_expression: ($, original) => choice(
      original,
      seq('(', alias($._assignment_expression_lhs, $.assignment_expression), ')'),
    ),

    operator_name: $ => prec(1, seq(
      'operator',
      choice(
        'co_await',
        '+', '-', '*', '/', '%',
        '^', '&', '|', '~',
        '!', '=', '<', '>',
        '+=', '-=', '*=', '/=', '%=', '^=', '&=', '|=',
        '<<', '>>', '>>=', '<<=',
        '==', '!=', '<=', '>=',
        '<=>',
        '&&', '||',
        '++', '--',
        ',',
        '->*',
        '->',
        '()', '[]',
        'xor', 'bitand', 'bitor', 'compl',
        'not', 'xor_eq', 'and_eq', 'or_eq', 'not_eq',
        'and', 'or',
        seq(choice('new', 'delete'), optional('[]')),
        seq('""', $.identifier),
      ),
    )),

    this: _ => 'this',

    concatenated_string: $ => prec.right(seq(
      choice($.identifier, $.string_literal, $.raw_string_literal),
      choice($.string_literal, $.raw_string_literal),
      repeat(choice($.identifier, $.string_literal, $.raw_string_literal)),
    )),

    number_literal: $ => {
      const sign = /[-\+]/;
      const separator = '\'';
      const binary = /[01]/;
      const binaryDigits = seq(repeat1(binary), repeat(seq(separator, repeat1(binary))));
      const decimal = /[0-9]/;
      const firstDecimal = /[1-9]/;
      const intDecimalDigits = seq(firstDecimal, repeat(decimal), repeat(seq(separator, repeat1(decimal))));
      const floatDecimalDigits = seq(repeat1(decimal), repeat(seq(separator, repeat1(decimal))));
      const hex = /[0-9a-fA-F]/;
      const hexDigits = seq(repeat1(hex), repeat(seq(separator, repeat1(hex))));
      const octal = /[0-7]/;
      const octalDigits = seq('0', repeat(octal), repeat(seq(separator, repeat1(octal))));
      const hexExponent = seq(/[pP]/, optional(sign), floatDecimalDigits);
      const decimalExponent = seq(/[eE]/, optional(sign), floatDecimalDigits);
      const intSuffix = /(ll|LL)[uU]?|[uU](ll|LL)?|[uU][lL]?|[uU][zZ]?|[lL][uU]?|[zZ][uU]?/;
      const floatSuffix = /([fF](16|32|64|128)?)|[lL]|(bf16|BF16)/;

      return token(seq(
        optional(sign),
        choice(
          seq(
            choice(
              seq(choice('0b', '0B'), binaryDigits),
              intDecimalDigits,
              seq(choice('0x', '0X'), hexDigits),
              octalDigits,
            ),
            optional(intSuffix),
          ),
          seq(
            choice(
              seq(floatDecimalDigits, decimalExponent),
              seq(floatDecimalDigits, '.', optional(floatDecimalDigits), optional(decimalExponent)),
              seq('.', floatDecimalDigits, optional(decimalExponent)),
              seq(
                choice('0x', '0X'),
                choice(
                  hexDigits,
                  seq(hexDigits, '.', optional(hexDigits)),
                  seq('.', hexDigits)),
                hexExponent,
              ),
            ),
            optional(floatSuffix),
          ),
        ),
      ));
    },

    literal_suffix: _ => token.immediate(/[a-zA-Z_]\w*/),

    user_defined_literal: $ => seq(
      choice(
        $.number_literal,
        $.char_literal,
        $._string,
      ),
      $.literal_suffix,
    ),

    _namespace_identifier: $ => alias($.identifier, $.namespace_identifier),
  },
});

/**
 * Creates a rule to optionally match one or more of the rules separated by a comma
 *
 * @param {Rule} rule
 *
 * @returns {ChoiceRule}
 */
function commaSep(rule) {
  return optional(commaSep1(rule));
}

/**
 * Creates a rule to match one or more of the rules separated by a comma
 *
 * @param {Rule} rule
 *
 * @returns {SeqRule}
 */
function commaSep1(rule) {
  return seq(rule, repeat(seq(',', rule)));
}



================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2014 Max Brunsfeld

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.



================================================
FILE: Makefile
================================================
ifeq ($(OS),Windows_NT)
$(error Windows is not supported)
endif

LANGUAGE_NAME := tree-sitter-cpp
HOMEPAGE_URL := https://github.com/tree-sitter/tree-sitter-cpp
VERSION := 0.23.4

# repository
SRC_DIR := src

TS ?= tree-sitter

# install directory layout
PREFIX ?= /usr/local
INCLUDEDIR ?= $(PREFIX)/include
LIBDIR ?= $(PREFIX)/lib
PCLIBDIR ?= $(LIBDIR)/pkgconfig

# source/object files
PARSER := $(SRC_DIR)/parser.c
EXTRAS := $(filter-out $(PARSER),$(wildcard $(SRC_DIR)/*.c))
OBJS := $(patsubst %.c,%.o,$(PARSER) $(EXTRAS))

# flags
ARFLAGS ?= rcs
override CFLAGS += -I$(SRC_DIR) -std=c11 -fPIC

# ABI versioning
SONAME_MAJOR = $(shell sed -n 's/\#define LANGUAGE_VERSION //p' $(PARSER))
SONAME_MINOR = $(word 1,$(subst ., ,$(VERSION)))

# OS-specific bits
ifeq ($(shell uname),Darwin)
	SOEXT = dylib
	SOEXTVER_MAJOR = $(SONAME_MAJOR).$(SOEXT)
	SOEXTVER = $(SONAME_MAJOR).$(SONAME_MINOR).$(SOEXT)
	LINKSHARED = -dynamiclib -Wl,-install_name,$(LIBDIR)/lib$(LANGUAGE_NAME).$(SOEXTVER),-rpath,@executable_path/../Frameworks
else
	SOEXT = so
	SOEXTVER_MAJOR = $(SOEXT).$(SONAME_MAJOR)
	SOEXTVER = $(SOEXT).$(SONAME_MAJOR).$(SONAME_MINOR)
	LINKSHARED = -shared -Wl,-soname,lib$(LANGUAGE_NAME).$(SOEXTVER)
endif
ifneq ($(filter $(shell uname),FreeBSD NetBSD DragonFly),)
	PCLIBDIR := $(PREFIX)/libdata/pkgconfig
endif

all: lib$(LANGUAGE_NAME).a lib$(LANGUAGE_NAME).$(SOEXT) $(LANGUAGE_NAME).pc

lib$(LANGUAGE_NAME).a: $(OBJS)
	$(AR) $(ARFLAGS) $@ $^

lib$(LANGUAGE_NAME).$(SOEXT): $(OBJS)
	$(CC) $(LDFLAGS) $(LINKSHARED) $^ $(LDLIBS) -o $@
ifneq ($(STRIP),)
	$(STRIP) $@
endif

$(LANGUAGE_NAME).pc: bindings/c/$(LANGUAGE_NAME).pc.in
	sed -e 's|@PROJECT_VERSION@|$(VERSION)|' \
		-e 's|@CMAKE_INSTALL_LIBDIR@|$(LIBDIR:$(PREFIX)/%=%)|' \
		-e 's|@CMAKE_INSTALL_INCLUDEDIR@|$(INCLUDEDIR:$(PREFIX)/%=%)|' \
		-e 's|@PROJECT_DESCRIPTION@|$(DESCRIPTION)|' \
		-e 's|@PROJECT_HOMEPAGE_URL@|$(HOMEPAGE_URL)|' \
		-e 's|@CMAKE_INSTALL_PREFIX@|$(PREFIX)|' $< > $@

$(PARSER): $(SRC_DIR)/grammar.json
	$(TS) generate $^

install: all
	install -d '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter '$(DESTDIR)$(PCLIBDIR)' '$(DESTDIR)$(LIBDIR)'
	install -m644 bindings/c/$(LANGUAGE_NAME).h '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/$(LANGUAGE_NAME).h
	install -m644 $(LANGUAGE_NAME).pc '$(DESTDIR)$(PCLIBDIR)'/$(LANGUAGE_NAME).pc
	install -m644 lib$(LANGUAGE_NAME).a '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).a
	install -m755 lib$(LANGUAGE_NAME).$(SOEXT) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER)
	ln -sf lib$(LANGUAGE_NAME).$(SOEXTVER) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR)
	ln -sf lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXT)

uninstall:
	$(RM) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).a \
		'$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER) \
		'$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) \
		'$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXT) \
		'$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/$(LANGUAGE_NAME).h \
		'$(DESTDIR)$(PCLIBDIR)'/$(LANGUAGE_NAME).pc

clean:
	$(RM) $(OBJS) $(LANGUAGE_NAME).pc lib$(LANGUAGE_NAME).a lib$(LANGUAGE_NAME).$(SOEXT)

test:
	$(TS) test

.PHONY: all install uninstall clean test



================================================
FILE: package.json
================================================
{
  "name": "tree-sitter-cpp",
  "version": "0.23.4",
  "description": "C++ grammar for tree-sitter",
  "repository": "https://github.com/tree-sitter/tree-sitter-cpp",
  "license": "MIT",
  "author": {
    "name": "Max Brunsfeld",
    "email": "maxbrunsfeld@gmail.com"
  },
  "maintainers": [
    {
      "name": "Amaan Qureshi",
      "email": "amaanq12@gmail.com"
    }
  ],
  "main": "bindings/node",
  "types": "bindings/node",
  "keywords": [
    "incremental",
    "parsing",
    "tree-sitter",
    "c++"
  ],
  "files": [
    "grammar.js",
    "tree-sitter.json",
    "binding.gyp",
    "prebuilds/**",
    "bindings/node/*",
    "queries/*",
    "src/**",
    "*.wasm"
  ],
  "dependencies": {
    "node-addon-api": "^8.2.1",
    "node-gyp-build": "^4.8.2",
    "tree-sitter-c": "^0.23.6"
  },
  "devDependencies": {
    "eslint": "^9.12.0",
    "eslint-config-treesitter": "^1.0.2",
    "prebuildify": "^6.0.1",
    "tree-sitter-cli": "^0.25.0"
  },
  "peerDependencies": {
    "tree-sitter": "^0.22.4"
  },
  "peerDependenciesMeta": {
    "tree-sitter": {
      "optional": true
    }
  },
  "scripts": {
    "install": "node-gyp-build",
    "lint": "eslint grammar.js",
    "prestart": "tree-sitter build --wasm",
    "start": "tree-sitter playground",
    "test": "node --test bindings/node/*_test.js"
  }
}



================================================
FILE: Package.resolved
================================================
{
  "object": {
    "pins": [
      {
        "package": "SwiftTreeSitter",
        "repositoryURL": "https://github.com/tree-sitter/swift-tree-sitter",
        "state": {
          "branch": null,
          "revision": "08ef81eb8620617b55b08868126707ad72bf754f",
          "version": "0.25.0"
        }
      },
      {
        "package": "TreeSitter",
        "repositoryURL": "https://github.com/tree-sitter/tree-sitter",
        "state": {
          "branch": null,
          "revision": "bf655c0beaf4943573543fa77c58e8006ff34971",
          "version": "0.25.6"
        }
      }
    ]
  },
  "version": 1
}



================================================
FILE: Package.swift
================================================
// swift-tools-version:5.3
import PackageDescription

let package = Package(
    name: "TreeSitterCPP",
    products: [
        .library(name: "TreeSitterCPP", targets: ["TreeSitterCPP"]),
    ],
    dependencies: [
        .package(url: "https://github.com/tree-sitter/swift-tree-sitter", from: "0.9.0"),
    ],
    targets: [
        .target(
            name: "TreeSitterCPP",
            dependencies: [],
            path: ".",
            sources: [
                "src/parser.c",
                "src/scanner.c",
            ],
            resources: [
                .copy("queries")
            ],
            publicHeadersPath: "bindings/swift",
            cSettings: [.headerSearchPath("src")]
        ),
        .testTarget(
            name: "TreeSitterCPPTests",
            dependencies: [
                .product(name: "SwiftTreeSitter", package: "swift-tree-sitter"),
                "TreeSitterCPP",
            ],
            path: "bindings/swift/TreeSitterCPPTests"
        )
    ],
    cLanguageStandard: .c11
)



================================================
FILE: pyproject.toml
================================================
[build-system]
requires = ["setuptools>=42", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "tree-sitter-cpp"
description = "C++ grammar for tree-sitter"
version = "0.23.4"
keywords = ["incremental", "parsing", "tree-sitter", "cpp"]
classifiers = [
  "Intended Audience :: Developers",
  "License :: OSI Approved :: MIT License",
  "Topic :: Software Development :: Compilers",
  "Topic :: Text Processing :: Linguistic",
  "Typing :: Typed",
]
authors = [
  { name = "Max Brunsfeld", email = "maxbrunsfeld@gmail.com" },
  { name = "Amaan Qureshi", email = "amaanq12@gmail.com" },
]
requires-python = ">=3.9"
license.text = "MIT"
readme = "README.md"

[project.urls]
Homepage = "https://github.com/tree-sitter/tree-sitter-cpp"

[project.optional-dependencies]
core = ["tree-sitter~=0.22"]

[tool.cibuildwheel]
build = "cp39-*"
build-frontend = "build"



================================================
FILE: setup.py
================================================
from os.path import isdir, join
from platform import system

from setuptools import Extension, find_packages, setup
from setuptools.command.build import build
from wheel.bdist_wheel import bdist_wheel


class Build(build):
    def run(self):
        if isdir("queries"):
            dest = join(self.build_lib, "tree_sitter_cpp", "queries")
            self.copy_tree("queries", dest)
        super().run()


class BdistWheel(bdist_wheel):
    def get_tag(self):
        python, abi, platform = super().get_tag()
        if python.startswith("cp"):
            python, abi = "cp39", "abi3"
        return python, abi, platform


setup(
    packages=find_packages("bindings/python"),
    package_dir={"": "bindings/python"},
    package_data={
        "tree_sitter_cpp": ["*.pyi", "py.typed"],
        "tree_sitter_cpp.queries": ["*.scm"],
    },
    ext_package="tree_sitter_cpp",
    ext_modules=[
        Extension(
            name="_binding",
            sources=[
                "bindings/python/tree_sitter_cpp/binding.c",
                "src/parser.c",
                "src/scanner.c",
            ],
            extra_compile_args=[
                "-std=c11",
                "-fvisibility=hidden",
            ] if system() != "Windows" else [
                "/std:c11",
                "/utf-8",
            ],
            define_macros=[
                ("Py_LIMITED_API", "0x03090000"),
                ("PY_SSIZE_T_CLEAN", None),
                ("TREE_SITTER_HIDE_SYMBOLS", None),
            ],
            include_dirs=["src"],
            py_limited_api=True,
        )
    ],
    cmdclass={
        "build": Build,
        "bdist_wheel": BdistWheel
    },
    zip_safe=False
)



================================================
FILE: tree-sitter.json
================================================
{
  "grammars": [
    {
      "name": "cpp",
      "camelcase": "CPP",
      "scope": "source.cpp",
      "path": ".",
      "file-types": [
        "cc",
        "cpp",
        "cxx",
        "hpp",
        "hxx",
        "h"
      ],
      "highlights": [
        "node_modules/tree-sitter-c/queries/highlights.scm",
        "queries/highlights.scm"
      ],
      "injections": "queries/injections.scm",
      "tags": "queries/tags.scm",
      "injection-regex": "^(cc|cpp)$"
    }
  ],
  "metadata": {
    "version": "0.23.4",
    "license": "MIT",
    "description": "C++ grammar for tree-sitter",
    "authors": [
      {
        "name": "Max Brunsfeld",
        "email": "maxbrunsfeld@gmail.com"
      },
      {
        "name": "Amaan Qureshi",
        "email": "amaanq12@gmail.com"
      },
      {
        "name": "John Drouhard",
        "email": "john@drouhard.dev"
      }
    ],
    "links": {
      "repository": "https://github.com/tree-sitter/tree-sitter-cpp"
    }
  },
  "bindings": {
    "c": true,
    "go": true,
    "node": true,
    "python": true,
    "rust": true,
    "swift": true
  }
}



================================================
FILE: .editorconfig
================================================
root = true

[*]
charset = utf-8

[*.{json,toml,yml,gyp}]
indent_style = space
indent_size = 2

[*.js]
indent_style = space
indent_size = 2

[*.scm]
indent_style = space
indent_size = 2

[*.{c,cc,h}]
indent_style = space
indent_size = 4

[*.rs]
indent_style = space
indent_size = 4

[*.{py,pyi}]
indent_style = space
indent_size = 4

[*.swift]
indent_style = space
indent_size = 4

[*.go]
indent_style = tab
indent_size = 8

[Makefile]
indent_style = tab
indent_size = 8

[parser.c]
indent_size = 2

[{alloc,array,parser}.h]
indent_size = 2



================================================
FILE: bindings/c/tree-sitter-cpp.h
================================================
#ifndef TREE_SITTER_CPP_H_
#define TREE_SITTER_CPP_H_

typedef struct TSLanguage TSLanguage;

#ifdef __cplusplus
extern "C" {
#endif

const TSLanguage *tree_sitter_cpp(void);

#ifdef __cplusplus
}
#endif

#endif // TREE_SITTER_CPP_H_



================================================
FILE: bindings/c/tree-sitter-cpp.pc.in
================================================
prefix=@CMAKE_INSTALL_PREFIX@
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@

Name: tree-sitter-cpp
Description: @PROJECT_DESCRIPTION@
URL: @PROJECT_HOMEPAGE_URL@
Version: @PROJECT_VERSION@
Libs: -L${libdir} -ltree-sitter-cpp
Cflags: -I${includedir}



================================================
FILE: bindings/go/binding.go
================================================
package tree_sitter_cpp

// #cgo CFLAGS: -std=c11 -fPIC
// #include "../../src/parser.c"
// #include "../../src/scanner.c"
import "C"

import "unsafe"

// Get the tree-sitter Language for this grammar.
func Language() unsafe.Pointer {
	return unsafe.Pointer(C.tree_sitter_cpp())
}



================================================
FILE: bindings/go/binding_test.go
================================================
package tree_sitter_cpp_test

import (
	"testing"

	tree_sitter "github.com/tree-sitter/go-tree-sitter"
	tree_sitter_cpp "github.com/tree-sitter/tree-sitter-cpp/bindings/go"
)

func TestCanLoadGrammar(t *testing.T) {
	language := tree_sitter.NewLanguage(tree_sitter_cpp.Language())
	if language == nil {
		t.Errorf("Error loading C++ grammar")
	}
}



================================================
FILE: bindings/node/binding.cc
================================================
#include <napi.h>

typedef struct TSLanguage TSLanguage;

extern "C" TSLanguage *tree_sitter_cpp();

// "tree-sitter", "language" hashed with BLAKE2
const napi_type_tag LANGUAGE_TYPE_TAG = {
    0x8AF2E5212AD58ABF, 0xD5006CAD83ABBA16
};

Napi::Object Init(Napi::Env env, Napi::Object exports) {
    exports["name"] = Napi::String::New(env, "cpp");
    auto language = Napi::External<TSLanguage>::New(env, tree_sitter_cpp());
    language.TypeTag(&LANGUAGE_TYPE_TAG);
    exports["language"] = language;
    return exports;
}

NODE_API_MODULE(tree_sitter_cpp_binding, Init)



================================================
FILE: bindings/node/binding_test.js
================================================
const assert = require("node:assert");
const { test } = require("node:test");

const Parser = require("tree-sitter");

test("can load grammar", () => {
  const parser = new Parser();
  assert.doesNotThrow(() => parser.setLanguage(require(".")));
});



================================================
FILE: bindings/node/index.d.ts
================================================
type BaseNode = {
  type: string;
  named: boolean;
};

type ChildNode = {
  multiple: boolean;
  required: boolean;
  types: BaseNode[];
};

type NodeInfo =
  | (BaseNode & {
      subtypes: BaseNode[];
    })
  | (BaseNode & {
      fields: { [name: string]: ChildNode };
      children: ChildNode[];
    });

type Language = {
  name: string;
  language: unknown;
  nodeTypeInfo: NodeInfo[];
};

declare const language: Language;
export = language;



================================================
FILE: bindings/node/index.js
================================================
const root = require("path").join(__dirname, "..", "..");

module.exports =
  typeof process.versions.bun === "string"
    // Support `bun build --compile` by being statically analyzable enough to find the .node file at build-time
    ? require(`../../prebuilds/${process.platform}-${process.arch}/tree-sitter-cpp.node`)
    : require("node-gyp-build")(root);

try {
  module.exports.nodeTypeInfo = require("../../src/node-types.json");
} catch (_) {}



================================================
FILE: bindings/python/tests/test_binding.py
================================================
from unittest import TestCase

import tree_sitter, tree_sitter_cpp


class TestLanguage(TestCase):
    def test_can_load_grammar(self):
        try:
            tree_sitter.Language(tree_sitter_cpp.language())
        except Exception:
            self.fail("Error loading C++ grammar")



================================================
FILE: bindings/python/tree_sitter_cpp/__init__.py
================================================
"""C++ grammar for tree-sitter"""

from importlib.resources import files as _files

from ._binding import language


def _get_query(name, file):
    query = _files(f"{__package__}.queries") / file
    globals()[name] = query.read_text()
    return globals()[name]


def __getattr__(name):
    if name == "HIGHLIGHTS_QUERY":
        return _get_query("HIGHLIGHTS_QUERY", "highlights.scm")
    if name == "INJECTIONS_QUERY":
        return _get_query("INJECTIONS_QUERY", "injections.scm")
    if name == "TAGS_QUERY":
        return _get_query("TAGS_QUERY", "tags.scm")

    raise AttributeError(f"module {__name__!r} has no attribute {name!r}")


__all__ = [
    "language",
    "HIGHLIGHTS_QUERY",
    "INJECTIONS_QUERY",
    "TAGS_QUERY",
]


def __dir__():
    return sorted(__all__ + [
        "__all__", "__builtins__", "__cached__", "__doc__", "__file__",
        "__loader__", "__name__", "__package__", "__path__", "__spec__",
    ])



================================================
FILE: bindings/python/tree_sitter_cpp/__init__.pyi
================================================
from typing import Final

HIGHLIGHTS_QUERY: Final[str]
INJECTIONS_QUERY: Final[str]
TAGS_QUERY: Final[str]

def language() -> object: ...



================================================
FILE: bindings/python/tree_sitter_cpp/binding.c
================================================
#include <Python.h>

typedef struct TSLanguage TSLanguage;

TSLanguage *tree_sitter_cpp(void);

static PyObject* _binding_language(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) {
    return PyCapsule_New(tree_sitter_cpp(), "tree_sitter.Language", NULL);
}

static PyMethodDef methods[] = {
    {"language", _binding_language, METH_NOARGS,
     "Get the tree-sitter language for this grammar."},
    {NULL, NULL, 0, NULL}
};

static struct PyModuleDef module = {
    .m_base = PyModuleDef_HEAD_INIT,
    .m_name = "_binding",
    .m_doc = NULL,
    .m_size = -1,
    .m_methods = methods
};

PyMODINIT_FUNC PyInit__binding(void) {
    return PyModule_Create(&module);
}



================================================
FILE: bindings/python/tree_sitter_cpp/py.typed
================================================
[Empty file]


================================================
FILE: bindings/rust/build.rs
================================================
fn main() {
    let src_dir = std::path::Path::new("src");

    let mut c_config = cc::Build::new();
    c_config.std("c11").include(src_dir);

    #[cfg(target_env = "msvc")]
    c_config.flag("-utf-8");

    let parser_path = src_dir.join("parser.c");
    c_config.file(&parser_path);
    println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap());

    let scanner_path = src_dir.join("scanner.c");
    c_config.file(&scanner_path);
    println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());

    c_config.compile("tree-sitter-cpp");
}



================================================
FILE: bindings/rust/lib.rs
================================================
//! This crate provides C++ language support for the [tree-sitter][] parsing library.
//!
//! Typically, you will use the [LANGUAGE][] constant to add this language to a
//! tree-sitter [Parser][], and then use the parser to parse some code:
//!
//! ```
//! use tree_sitter::Parser;
//!
//! let code = r#"
//! int double(int x) {
//!     return x * 2;
//! }
//! "#;
//! let mut parser = tree_sitter::Parser::new();
//! let language = tree_sitter_cpp::LANGUAGE;
//! parser
//!     .set_language(&language.into())
//!     .expect("Error loading C++ parser");
//! let tree = parser.parse(code, None).unwrap();
//! assert!(!tree.root_node().has_error());
//! ```
//!
//! [Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html
//! [tree-sitter]: https://tree-sitter.github.io/

use tree_sitter_language::LanguageFn;

extern "C" {
    fn tree_sitter_cpp() -> *const ();
}

/// The tree-sitter [`LanguageFn`][LanguageFn] for this grammar.
///
/// [LanguageFn]: https://docs.rs/tree-sitter-language/*/tree_sitter_language/struct.LanguageFn.html
pub const LANGUAGE: LanguageFn = unsafe { LanguageFn::from_raw(tree_sitter_cpp) };

/// The content of the [`node-types.json`][] file for this grammar.
///
/// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types
pub const NODE_TYPES: &str = include_str!("../../src/node-types.json");

/// The syntax highlighting query for this language.
pub const HIGHLIGHT_QUERY: &str = include_str!("../../queries/highlights.scm");

/// The symbol tagging query for this language.
pub const TAGS_QUERY: &str = include_str!("../../queries/tags.scm");

#[cfg(test)]
mod tests {
    #[test]
    fn test_can_load_grammar() {
        let mut parser = tree_sitter::Parser::new();
        parser
            .set_language(&super::LANGUAGE.into())
            .expect("Error loading C++ parser");
    }
}



================================================
FILE: bindings/swift/TreeSitterCPP/cpp.h
================================================
#ifndef TREE_SITTER_CPP_H_
#define TREE_SITTER_CPP_H_

typedef struct TSLanguage TSLanguage;

#ifdef __cplusplus
extern "C" {
#endif

const TSLanguage *tree_sitter_cpp(void);

#ifdef __cplusplus
}
#endif

#endif // TREE_SITTER_CPP_H_



================================================
FILE: bindings/swift/TreeSitterCPPTests/TreeSitterCPPTests.swift
================================================
import XCTest
import SwiftTreeSitter
import TreeSitterCPP

final class TreeSitterCPPTests: XCTestCase {
    func testCanLoadGrammar() throws {
        let parser = Parser()
        let language = Language(language: tree_sitter_cpp())
        XCTAssertNoThrow(try parser.setLanguage(language),
                         "Error loading C++ grammar")
    }
}



================================================
FILE: examples/marker-index.h
================================================
#ifndef MARKER_INDEX_H_
#define MARKER_INDEX_H_

#include <random>
#include <unordered_map>
#include "flat_set.h"
#include "point.h"
#include "range.h"

class MarkerIndex {
public:
  using MarkerId = unsigned;
  using MarkerIdSet = flat_set<MarkerId>;

  struct SpliceResult {
    flat_set<MarkerId> touch;
    flat_set<MarkerId> inside;
    flat_set<MarkerId> overlap;
    flat_set<MarkerId> surround;
  };

  struct Boundary {
    Point position;
    flat_set<MarkerId> starting;
    flat_set<MarkerId> ending;
  };

  struct BoundaryQueryResult {
    std::vector<MarkerId> containing_start;
    std::vector<Boundary> boundaries;
  };

  MarkerIndex(unsigned seed = 0u);
  ~MarkerIndex();
  int generate_random_number();
  void insert(MarkerId id, Point start, Point end);
  void set_exclusive(MarkerId id, bool exclusive);
  void remove(MarkerId id);
  bool has(MarkerId id);
  SpliceResult splice(Point start, Point old_extent, Point new_extent);
  Point get_start(MarkerId id) const;
  Point get_end(MarkerId id) const;
  Range get_range(MarkerId id) const;

  int compare(MarkerId id1, MarkerId id2) const;
  flat_set<MarkerId> find_intersecting(Point start, Point end);
  flat_set<MarkerId> find_containing(Point start, Point end);
  flat_set<MarkerId> find_contained_in(Point start, Point end);
  flat_set<MarkerId> find_starting_in(Point start, Point end);
  flat_set<MarkerId> find_starting_at(Point position);
  flat_set<MarkerId> find_ending_in(Point start, Point end);
  flat_set<MarkerId> find_ending_at(Point position);
  BoundaryQueryResult find_boundaries_after(Point start, size_t max_count);

  std::unordered_map<MarkerId, Range> dump();

private:
  friend class Iterator;

  struct Node {
    Node *parent;
    Node *left;
    Node *right;
    Point left_extent;
    flat_set<MarkerId> left_marker_ids;
    flat_set<MarkerId> right_marker_ids;
    flat_set<MarkerId> start_marker_ids;
    flat_set<MarkerId> end_marker_ids;
    int priority;

    Node(Node *parent, Point left_extent);
    bool is_marker_endpoint();
  };

  class Iterator {
  public:
    Iterator(MarkerIndex *marker_index);
    void reset();
    Node* insert_marker_start(const MarkerId &id, const Point &start_position, const Point &end_position);
    Node* insert_marker_end(const MarkerId &id, const Point &start_position, const Point &end_position);
    Node* insert_splice_boundary(const Point &position, bool is_insertion_end);
    void find_intersecting(const Point &start, const Point &end, flat_set<MarkerId> *result);
    void find_contained_in(const Point &start, const Point &end, flat_set<MarkerId> *result);
    void find_starting_in(const Point &start, const Point &end, flat_set<MarkerId> *result);
    void find_ending_in(const Point &start, const Point &end, flat_set<MarkerId> *result);
    void find_boundaries_after(Point start, size_t max_count, BoundaryQueryResult *result);
    std::unordered_map<MarkerId, Range> dump();

  private:
    void ascend();
    void descend_left();
    void descend_right();
    void move_to_successor();
    void seek_to_first_node_greater_than_or_equal_to(const Point &position);
    void mark_right(const MarkerId &id, const Point &start_position, const Point &end_position);
    void mark_left(const MarkerId &id, const Point &start_position, const Point &end_position);
    Node* insert_left_child(const Point &position);
    Node* insert_right_child(const Point &position);
    void check_intersection(const Point &start, const Point &end, flat_set<MarkerId> *results);
    void cache_node_position() const;

    MarkerIndex *marker_index;
    Node *current_node;
    Point current_node_position;
    Point left_ancestor_position;
    Point right_ancestor_position;
    std::vector<Point> left_ancestor_position_stack;
    std::vector<Point> right_ancestor_position_stack;
  };

  Point get_node_position(const Node *node) const;
  void delete_node(Node *node);
  void delete_subtree(Node *node);
  void bubble_node_up(Node *node);
  void bubble_node_down(Node *node);
  void rotate_node_left(Node *pivot);
  void rotate_node_right(Node *pivot);
  void get_starting_and_ending_markers_within_subtree(const Node *node, flat_set<MarkerId> *starting, flat_set<MarkerId> *ending);
  void populate_splice_invalidation_sets(SpliceResult *invalidated, const Node *start_node, const Node *end_node, const flat_set<MarkerId> &starting_inside_splice, const flat_set<MarkerId> &ending_inside_splice);

  std::default_random_engine random_engine;
  std::uniform_int_distribution<int> random_distribution;
  Node *root;
  std::unordered_map<MarkerId, Node*> start_nodes_by_id;
  std::unordered_map<MarkerId, Node*> end_nodes_by_id;
  Iterator iterator;
  flat_set<MarkerId> exclusive_marker_ids;
  mutable std::unordered_map<const Node*, Point> node_position_cache;
};

#endif // MARKER_INDEX_H_



================================================
FILE: examples/rule.cc
================================================
#include "compiler/rule.h"
#include "compiler/util/hash_combine.h"

namespace tree_sitter {
namespace rules {

using std::move;
using std::vector;
using util::hash_combine;

Rule::Rule(const Rule &other) : blank_(Blank{}), type(BlankType) {
  *this = other;
}

Rule::Rule(Rule &&other) noexcept : blank_(Blank{}), type(BlankType) {
  *this = move(other);
}

static void destroy_value(Rule *rule) {
  switch (rule->type) {
    case Rule::BlankType: return rule->blank_.~Blank();
    case Rule::CharacterSetType: return rule->character_set_.~CharacterSet();
    case Rule::StringType: return rule->string_ .~String();
    case Rule::PatternType: return rule->pattern_ .~Pattern();
    case Rule::NamedSymbolType: return rule->named_symbol_.~NamedSymbol();
    case Rule::SymbolType: return rule->symbol_ .~Symbol();
    case Rule::ChoiceType: return rule->choice_ .~Choice();
    case Rule::MetadataType: return rule->metadata_ .~Metadata();
    case Rule::RepeatType: return rule->repeat_ .~Repeat();
    case Rule::SeqType: return rule->seq_ .~Seq();
  }
}

Rule &Rule::operator=(const Rule &other) {
  destroy_value(this);
  type = other.type;
  switch (type) {
    case BlankType:
      new (&blank_) Blank(other.blank_);
      break;
    case CharacterSetType:
      new (&character_set_) CharacterSet(other.character_set_);
      break;
    case StringType:
      new (&string_) String(other.string_);
      break;
    case PatternType:
      new (&pattern_) Pattern(other.pattern_);
      break;
    case NamedSymbolType:
      new (&named_symbol_) NamedSymbol(other.named_symbol_);
      break;
    case SymbolType:
      new (&symbol_) Symbol(other.symbol_);
      break;
    case ChoiceType:
      new (&choice_) Choice(other.choice_);
      break;
    case MetadataType:
      new (&metadata_) Metadata(other.metadata_);
      break;
    case RepeatType:
      new (&repeat_) Repeat(other.repeat_);
      break;
    case SeqType:
      new (&seq_) Seq(other.seq_);
      break;
  }
  return *this;
}

Rule &Rule::operator=(Rule &&other) noexcept {
  destroy_value(this);
  type = other.type;
  switch (type) {
    case BlankType:
      new (&blank_) Blank(move(other.blank_));
      break;
    case CharacterSetType:
      new (&character_set_) CharacterSet(move(other.character_set_));
      break;
    case StringType:
      new (&string_) String(move(other.string_));
      break;
    case PatternType:
      new (&pattern_) Pattern(move(other.pattern_));
      break;
    case NamedSymbolType:
      new (&named_symbol_) NamedSymbol(move(other.named_symbol_));
      break;
    case SymbolType:
      new (&symbol_) Symbol(move(other.symbol_));
      break;
    case ChoiceType:
      new (&choice_) Choice(move(other.choice_));
      break;
    case MetadataType:
      new (&metadata_) Metadata(move(other.metadata_));
      break;
    case RepeatType:
      new (&repeat_) Repeat(move(other.repeat_));
      break;
    case SeqType:
      new (&seq_) Seq(move(other.seq_));
      break;
  }
  other.type = BlankType;
  other.blank_ = Blank{};
  return *this;
}

Rule::~Rule() noexcept {
  destroy_value(this);
}

bool Rule::operator==(const Rule &other) const {
  if (type != other.type) return false;
  switch (type) {
    case Rule::CharacterSetType: return character_set_ == other.character_set_;
    case Rule::StringType: return string_ == other.string_;
    case Rule::PatternType: return pattern_ == other.pattern_;
    case Rule::NamedSymbolType: return named_symbol_ == other.named_symbol_;
    case Rule::SymbolType: return symbol_ == other.symbol_;
    case Rule::ChoiceType: return choice_ == other.choice_;
    case Rule::MetadataType: return metadata_ == other.metadata_;
    case Rule::RepeatType: return repeat_ == other.repeat_;
    case Rule::SeqType: return seq_ == other.seq_;
    default: return blank_ == other.blank_;
  }
}

template <>
bool Rule::is<Blank>() const { return type == BlankType; }

template <>
bool Rule::is<Symbol>() const { return type == SymbolType; }

template <>
bool Rule::is<Repeat>() const { return type == RepeatType; }

template <>
const Symbol & Rule::get_unchecked<Symbol>() const { return symbol_; }

static inline void add_choice_element(std::vector<Rule> *elements, const Rule &new_rule) {
  new_rule.match(
    [elements](Choice choice) {
      for (auto &element : choice.elements) {
        add_choice_element(elements, element);
      }
    },

    [elements](auto rule) {
      for (auto &element : *elements) {
        if (element == rule) return;
      }
      elements->push_back(rule);
    }
  );
}

Rule Rule::choice(const vector<Rule> &rules) {
  vector<Rule> elements;
  for (auto &element : rules) {
    add_choice_element(&elements, element);
  }
  return (elements.size() == 1) ? elements.front() : Choice{elements};
}

Rule Rule::repeat(const Rule &rule) {
  return rule.is<Repeat>() ? rule : Repeat{rule};
}

Rule Rule::seq(const vector<Rule> &rules) {
  Rule result;
  for (const auto &rule : rules) {
    rule.match(
      [](Blank) {},
      [&](Metadata metadata) {
        if (!metadata.rule->is<Blank>()) {
          result = Seq{result, rule};
        }
      },
      [&](auto) {
        if (result.is<Blank>()) {
          result = rule;
        } else {
          result = Seq{result, rule};
        }
      }
    );
  }
  return result;
}

}  // namespace rules
}  // namespace tree_sitter

namespace std {

size_t hash<Symbol>::operator()(const Symbol &symbol) const {
  auto result = hash<int>()(symbol.index);
  hash_combine(&result, hash<int>()(symbol.type));
  return result;
}

size_t hash<NamedSymbol>::operator()(const NamedSymbol &symbol) const {
  return hash<string>()(symbol.value);
}

size_t hash<Pattern>::operator()(const Pattern &symbol) const {
  return hash<string>()(symbol.value);
}

size_t hash<String>::operator()(const String &symbol) const {
  return hash<string>()(symbol.value);
}

size_t hash<CharacterSet>::operator()(const CharacterSet &character_set) const {
  size_t result = 0;
  hash_combine(&result, character_set.includes_all);
  hash_combine(&result, character_set.included_chars.size());
  for (uint32_t c : character_set.included_chars) {
    hash_combine(&result, c);
  }
  hash_combine(&result, character_set.excluded_chars.size());
  for (uint32_t c : character_set.excluded_chars) {
    hash_combine(&result, c);
  }
  return result;
}

size_t hash<Blank>::operator()(const Blank &blank) const {
  return 0;
}

size_t hash<Choice>::operator()(const Choice &choice) const {
  size_t result = 0;
  for (const auto &element : choice.elements) {
    symmetric_hash_combine(&result, element);
  }
  return result;
}

size_t hash<Repeat>::operator()(const Repeat &repeat) const {
  size_t result = 0;
  hash_combine(&result, *repeat.rule);
  return result;
}

size_t hash<Seq>::operator()(const Seq &seq) const {
  size_t result = 0;
  hash_combine(&result, *seq.left);
  hash_combine(&result, *seq.right);
  return result;
}

size_t hash<Metadata>::operator()(const Metadata &metadata) const {
  size_t result = 0;
  hash_combine(&result, *metadata.rule);
  hash_combine(&result, metadata.params.precedence);
  hash_combine<int>(&result, metadata.params.associativity);
  hash_combine(&result, metadata.params.has_precedence);
  hash_combine(&result, metadata.params.has_associativity);
  hash_combine(&result, metadata.params.is_token);
  hash_combine(&result, metadata.params.is_string);
  hash_combine(&result, metadata.params.is_active);
  hash_combine(&result, metadata.params.is_main_token);
  return result;
}

size_t hash<Rule>::operator()(const Rule &rule) const {
  size_t result = hash<int>()(rule.type);
  switch (rule.type) {
    case Rule::CharacterSetType: return result ^ hash<CharacterSet>()(rule.character_set_);
    case Rule::StringType: return result ^ hash<String>()(rule.string_);
    case Rule::PatternType: return result ^ hash<Pattern>()(rule.pattern_);
    case Rule::NamedSymbolType: return result ^ hash<NamedSymbol>()(rule.named_symbol_);
    case Rule::SymbolType: return result ^ hash<Symbol>()(rule.symbol_);
    case Rule::ChoiceType: return result ^ hash<Choice>()(rule.choice_);
    case Rule::MetadataType: return result ^ hash<Metadata>()(rule.metadata_);
    case Rule::RepeatType: return result ^ hash<Repeat>()(rule.repeat_);
    case Rule::SeqType: return result ^ hash<Seq>()(rule.seq_);
    default: return result ^ hash<Blank>()(rule.blank_);
  }
}

}  // namespace std


================================================
FILE: queries/highlights.scm
================================================
; Functions

(call_expression
  function: (qualified_identifier
    name: (identifier) @function))

(template_function
  name: (identifier) @function)

(template_method
  name: (field_identifier) @function)

(template_function
  name: (identifier) @function)

(function_declarator
  declarator: (qualified_identifier
    name: (identifier) @function))

(function_declarator
  declarator: (field_identifier) @function)

; Types

((namespace_identifier) @type
 (#match? @type "^[A-Z]"))

(auto) @type

; Constants

(this) @variable.builtin
(null "nullptr" @constant)

; Modules
(module_name
  (identifier) @module)

; Keywords

[
 "catch"
 "class"
 "co_await"
 "co_return"
 "co_yield"
 "constexpr"
 "constinit"
 "consteval"
 "delete"
 "explicit"
 "final"
 "friend"
 "mutable"
 "namespace"
 "noexcept"
 "new"
 "override"
 "private"
 "protected"
 "public"
 "template"
 "throw"
 "try"
 "typename"
 "using"
 "concept"
 "requires"
 "virtual"
 "import"
 "export"
 "module"
] @keyword

; Strings

(raw_string_literal) @string



================================================
FILE: queries/injections.scm
================================================
(raw_string_literal
  delimiter: (raw_string_delimiter) @injection.language
  (raw_string_content) @injection.content)



================================================
FILE: queries/tags.scm
================================================
(struct_specifier name: (type_identifier) @name body:(_)) @definition.class

(declaration type: (union_specifier name: (type_identifier) @name)) @definition.class

(function_declarator declarator: (identifier) @name) @definition.function

(function_declarator declarator: (field_identifier) @name) @definition.function

(function_declarator declarator: (qualified_identifier scope: (namespace_identifier) @local.scope name: (identifier) @name)) @definition.method

(type_definition declarator: (type_identifier) @name) @definition.type

(enum_specifier name: (type_identifier) @name) @definition.type

(class_specifier name: (type_identifier) @name) @definition.class



================================================
FILE: src/scanner.c
================================================
#include "tree_sitter/alloc.h"
#include "tree_sitter/parser.h"

#include <assert.h>
#include <string.h>
#include <wctype.h>

enum TokenType { RAW_STRING_DELIMITER, RAW_STRING_CONTENT };

/// The spec limits delimiters to 16 chars
#define MAX_DELIMITER_LENGTH 16

typedef struct {
    uint8_t delimiter_length;
    wchar_t delimiter[MAX_DELIMITER_LENGTH];
} Scanner;

static inline void advance(TSLexer *lexer) { lexer->advance(lexer, false); }

static inline void reset(Scanner *scanner) {
    scanner->delimiter_length = 0;
    memset(scanner->delimiter, 0, sizeof scanner->delimiter);
}

/// Scan the raw string delimiter in R"delimiter(content)delimiter"
static bool scan_raw_string_delimiter(Scanner *scanner, TSLexer *lexer) {
    if (scanner->delimiter_length > 0) {
        // Closing delimiter: must exactly match the opening delimiter.
        // We already checked this when scanning content, but this is how we
        // know when to stop. We can't stop at ", because R"""hello""" is valid.
        for (int i = 0; i < scanner->delimiter_length; ++i) {
            if (lexer->lookahead != scanner->delimiter[i]) {
                return false;
            }
            advance(lexer);
        }
        reset(scanner);
        return true;
    }

    // Opening delimiter: record the d-char-sequence up to (.
    // d-char is any basic character except parens, backslashes, and spaces.
    for (;;) {
        if (scanner->delimiter_length >= MAX_DELIMITER_LENGTH || lexer->eof(lexer) || lexer->lookahead == '\\' ||
            iswspace(lexer->lookahead)) {
            return false;
        }
        if (lexer->lookahead == '(') {
            // Rather than create a token for an empty delimiter, we fail and
            // let the grammar fall back to a delimiter-less rule.
            return scanner->delimiter_length > 0;
        }
        scanner->delimiter[scanner->delimiter_length++] = lexer->lookahead;
        advance(lexer);
    }
}

/// Scan the raw string content in R"delimiter(content)delimiter"
static bool scan_raw_string_content(Scanner *scanner, TSLexer *lexer) {
    // The progress made through the delimiter since the last ')'.
    // The delimiter may not contain ')' so a single counter suffices.
    for (int delimiter_index = -1;;) {
        // If we hit EOF, consider the content to terminate there.
        // This forms an incomplete raw_string_literal, and models the code
        // well.
        if (lexer->eof(lexer)) {
            lexer->mark_end(lexer);
            return true;
        }

        if (delimiter_index >= 0) {
            if (delimiter_index == scanner->delimiter_length) {
                if (lexer->lookahead == '"') {
                    return true;
                }
                delimiter_index = -1;
            } else {
                if (lexer->lookahead == scanner->delimiter[delimiter_index]) {
                    delimiter_index += 1;
                } else {
                    delimiter_index = -1;
                }
            }
        }

        if (delimiter_index == -1 && lexer->lookahead == ')') {
            // The content doesn't include the )delimiter" part.
            // We must still scan through it, but exclude it from the token.
            lexer->mark_end(lexer);
            delimiter_index = 0;
        }

        advance(lexer);
    }
}

void *tree_sitter_cpp_external_scanner_create() {
    Scanner *scanner = (Scanner *)ts_calloc(1, sizeof(Scanner));
    memset(scanner, 0, sizeof(Scanner));
    return scanner;
}

bool tree_sitter_cpp_external_scanner_scan(void *payload, TSLexer *lexer, const bool *valid_symbols) {
    Scanner *scanner = (Scanner *)payload;

    if (valid_symbols[RAW_STRING_DELIMITER] && valid_symbols[RAW_STRING_CONTENT]) {
        // we're in error recovery
        return false;
    }

    // No skipping leading whitespace: raw-string grammar is space-sensitive.
    if (valid_symbols[RAW_STRING_DELIMITER]) {
        lexer->result_symbol = RAW_STRING_DELIMITER;
        return scan_raw_string_delimiter(scanner, lexer);
    }

    if (valid_symbols[RAW_STRING_CONTENT]) {
        lexer->result_symbol = RAW_STRING_CONTENT;
        return scan_raw_string_content(scanner, lexer);
    }

    return false;
}

unsigned tree_sitter_cpp_external_scanner_serialize(void *payload, char *buffer) {
    static_assert(MAX_DELIMITER_LENGTH * sizeof(wchar_t) < TREE_SITTER_SERIALIZATION_BUFFER_SIZE,
                  "Serialized delimiter is too long!");

    Scanner *scanner = (Scanner *)payload;
    size_t size = scanner->delimiter_length * sizeof(wchar_t);
    memcpy(buffer, scanner->delimiter, size);
    return (unsigned)size;
}

void tree_sitter_cpp_external_scanner_deserialize(void *payload, const char *buffer, unsigned length) {
    assert(length % sizeof(wchar_t) == 0 && "Can't decode serialized delimiter!");

    Scanner *scanner = (Scanner *)payload;
    scanner->delimiter_length = length / sizeof(wchar_t);
    if (length > 0) {
        memcpy(&scanner->delimiter[0], buffer, length);
    }
}

void tree_sitter_cpp_external_scanner_destroy(void *payload) {
    Scanner *scanner = (Scanner *)payload;
    ts_free(scanner);
}



================================================
FILE: src/tree_sitter/alloc.h
================================================
#ifndef TREE_SITTER_ALLOC_H_
#define TREE_SITTER_ALLOC_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

// Allow clients to override allocation functions
#ifdef TREE_SITTER_REUSE_ALLOCATOR

extern void *(*ts_current_malloc)(size_t size);
extern void *(*ts_current_calloc)(size_t count, size_t size);
extern void *(*ts_current_realloc)(void *ptr, size_t size);
extern void (*ts_current_free)(void *ptr);

#ifndef ts_malloc
#define ts_malloc  ts_current_malloc
#endif
#ifndef ts_calloc
#define ts_calloc  ts_current_calloc
#endif
#ifndef ts_realloc
#define ts_realloc ts_current_realloc
#endif
#ifndef ts_free
#define ts_free    ts_current_free
#endif

#else

#ifndef ts_malloc
#define ts_malloc  malloc
#endif
#ifndef ts_calloc
#define ts_calloc  calloc
#endif
#ifndef ts_realloc
#define ts_realloc realloc
#endif
#ifndef ts_free
#define ts_free    free
#endif

#endif

#ifdef __cplusplus
}
#endif

#endif // TREE_SITTER_ALLOC_H_



================================================
FILE: src/tree_sitter/array.h
================================================
#ifndef TREE_SITTER_ARRAY_H_
#define TREE_SITTER_ARRAY_H_

#ifdef __cplusplus
extern "C" {
#endif

#include "./alloc.h"

#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4101)
#elif defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
#endif

#define Array(T)       \
  struct {             \
    T *contents;       \
    uint32_t size;     \
    uint32_t capacity; \
  }

/// Initialize an array.
#define array_init(self) \
  ((self)->size = 0, (self)->capacity = 0, (self)->contents = NULL)

/// Create an empty array.
#define array_new() \
  { NULL, 0, 0 }

/// Get a pointer to the element at a given `index` in the array.
#define array_get(self, _index) \
  (assert((uint32_t)(_index) < (self)->size), &(self)->contents[_index])

/// Get a pointer to the first element in the array.
#define array_front(self) array_get(self, 0)

/// Get a pointer to the last element in the array.
#define array_back(self) array_get(self, (self)->size - 1)

/// Clear the array, setting its size to zero. Note that this does not free any
/// memory allocated for the array's contents.
#define array_clear(self) ((self)->size = 0)

/// Reserve `new_capacity` elements of space in the array. If `new_capacity` is
/// less than the array's current capacity, this function has no effect.
#define array_reserve(self, new_capacity) \
  _array__reserve((Array *)(self), array_elem_size(self), new_capacity)

/// Free any memory allocated for this array. Note that this does not free any
/// memory allocated for the array's contents.
#define array_delete(self) _array__delete((Array *)(self))

/// Push a new `element` onto the end of the array.
#define array_push(self, element)                            \
  (_array__grow((Array *)(self), 1, array_elem_size(self)), \
   (self)->contents[(self)->size++] = (element))

/// Increase the array's size by `count` elements.
/// New elements are zero-initialized.
#define array_grow_by(self, count) \
  do { \
    if ((count) == 0) break; \
    _array__grow((Array *)(self), count, array_elem_size(self)); \
    memset((self)->contents + (self)->size, 0, (count) * array_elem_size(self)); \
    (self)->size += (count); \
  } while (0)

/// Append all elements from one array to the end of another.
#define array_push_all(self, other)                                       \
  array_extend((self), (other)->size, (other)->contents)

/// Append `count` elements to the end of the array, reading their values from the
/// `contents` pointer.
#define array_extend(self, count, contents)                    \
  _array__splice(                                               \
    (Array *)(self), array_elem_size(self), (self)->size, \
    0, count,  contents                                        \
  )

/// Remove `old_count` elements from the array starting at the given `index`. At
/// the same index, insert `new_count` new elements, reading their values from the
/// `new_contents` pointer.
#define array_splice(self, _index, old_count, new_count, new_contents)  \
  _array__splice(                                                       \
    (Array *)(self), array_elem_size(self), _index,                \
    old_count, new_count, new_contents                                 \
  )

/// Insert one `element` into the array at the given `index`.
#define array_insert(self, _index, element) \
  _array__splice((Array *)(self), array_elem_size(self), _index, 0, 1, &(element))

/// Remove one element from the array at the given `index`.
#define array_erase(self, _index) \
  _array__erase((Array *)(self), array_elem_size(self), _index)

/// Pop the last element off the array, returning the element by value.
#define array_pop(self) ((self)->contents[--(self)->size])

/// Assign the contents of one array to another, reallocating if necessary.
#define array_assign(self, other) \
  _array__assign((Array *)(self), (const Array *)(other), array_elem_size(self))

/// Swap one array with another
#define array_swap(self, other) \
  _array__swap((Array *)(self), (Array *)(other))

/// Get the size of the array contents
#define array_elem_size(self) (sizeof *(self)->contents)

/// Search a sorted array for a given `needle` value, using the given `compare`
/// callback to determine the order.
///
/// If an existing element is found to be equal to `needle`, then the `index`
/// out-parameter is set to the existing value's index, and the `exists`
/// out-parameter is set to true. Otherwise, `index` is set to an index where
/// `needle` should be inserted in order to preserve the sorting, and `exists`
/// is set to false.
#define array_search_sorted_with(self, compare, needle, _index, _exists) \
  _array__search_sorted(self, 0, compare, , needle, _index, _exists)

/// Search a sorted array for a given `needle` value, using integer comparisons
/// of a given struct field (specified with a leading dot) to determine the order.
///
/// See also `array_search_sorted_with`.
#define array_search_sorted_by(self, field, needle, _index, _exists) \
  _array__search_sorted(self, 0, _compare_int, field, needle, _index, _exists)

/// Insert a given `value` into a sorted array, using the given `compare`
/// callback to determine the order.
#define array_insert_sorted_with(self, compare, value) \
  do { \
    unsigned _index, _exists; \
    array_search_sorted_with(self, compare, &(value), &_index, &_exists); \
    if (!_exists) array_insert(self, _index, value); \
  } while (0)

/// Insert a given `value` into a sorted array, using integer comparisons of
/// a given struct field (specified with a leading dot) to determine the order.
///
/// See also `array_search_sorted_by`.
#define array_insert_sorted_by(self, field, value) \
  do { \
    unsigned _index, _exists; \
    array_search_sorted_by(self, field, (value) field, &_index, &_exists); \
    if (!_exists) array_insert(self, _index, value); \
  } while (0)

// Private

typedef Array(void) Array;

/// This is not what you're looking for, see `array_delete`.
static inline void _array__delete(Array *self) {
  if (self->contents) {
    ts_free(self->contents);
    self->contents = NULL;
    self->size = 0;
    self->capacity = 0;
  }
}

/// This is not what you're looking for, see `array_erase`.
static inline void _array__erase(Array *self, size_t element_size,
                                uint32_t index) {
  assert(index < self->size);
  char *contents = (char *)self->contents;
  memmove(contents + index * element_size, contents + (index + 1) * element_size,
          (self->size - index - 1) * element_size);
  self->size--;
}

/// This is not what you're looking for, see `array_reserve`.
static inline void _array__reserve(Array *self, size_t element_size, uint32_t new_capacity) {
  if (new_capacity > self->capacity) {
    if (self->contents) {
      self->contents = ts_realloc(self->contents, new_capacity * element_size);
    } else {
      self->contents = ts_malloc(new_capacity * element_size);
    }
    self->capacity = new_capacity;
  }
}

/// This is not what you're looking for, see `array_assign`.
static inline void _array__assign(Array *self, const Array *other, size_t element_size) {
  _array__reserve(self, element_size, other->size);
  self->size = other->size;
  memcpy(self->contents, other->contents, self->size * element_size);
}

/// This is not what you're looking for, see `array_swap`.
static inline void _array__swap(Array *self, Array *other) {
  Array swap = *other;
  *other = *self;
  *self = swap;
}

/// This is not what you're looking for, see `array_push` or `array_grow_by`.
static inline void _array__grow(Array *self, uint32_t count, size_t element_size) {
  uint32_t new_size = self->size + count;
  if (new_size > self->capacity) {
    uint32_t new_capacity = self->capacity * 2;
    if (new_capacity < 8) new_capacity = 8;
    if (new_capacity < new_size) new_capacity = new_size;
    _array__reserve(self, element_size, new_capacity);
  }
}

/// This is not what you're looking for, see `array_splice`.
static inline void _array__splice(Array *self, size_t element_size,
                                 uint32_t index, uint32_t old_count,
                                 uint32_t new_count, const void *elements) {
  uint32_t new_size = self->size + new_count - old_count;
  uint32_t old_end = index + old_count;
  uint32_t new_end = index + new_count;
  assert(old_end <= self->size);

  _array__reserve(self, element_size, new_size);

  char *contents = (char *)self->contents;
  if (self->size > old_end) {
    memmove(
      contents + new_end * element_size,
      contents + old_end * element_size,
      (self->size - old_end) * element_size
    );
  }
  if (new_count > 0) {
    if (elements) {
      memcpy(
        (contents + index * element_size),
        elements,
        new_count * element_size
      );
    } else {
      memset(
        (contents + index * element_size),
        0,
        new_count * element_size
      );
    }
  }
  self->size += new_count - old_count;
}

/// A binary search routine, based on Rust's `std::slice::binary_search_by`.
/// This is not what you're looking for, see `array_search_sorted_with` or `array_search_sorted_by`.
#define _array__search_sorted(self, start, compare, suffix, needle, _index, _exists) \
  do { \
    *(_index) = start; \
    *(_exists) = false; \
    uint32_t size = (self)->size - *(_index); \
    if (size == 0) break; \
    int comparison; \
    while (size > 1) { \
      uint32_t half_size = size / 2; \
      uint32_t mid_index = *(_index) + half_size; \
      comparison = compare(&((self)->contents[mid_index] suffix), (needle)); \
      if (comparison <= 0) *(_index) = mid_index; \
      size -= half_size; \
    } \
    comparison = compare(&((self)->contents[*(_index)] suffix), (needle)); \
    if (comparison == 0) *(_exists) = true; \
    else if (comparison < 0) *(_index) += 1; \
  } while (0)

/// Helper macro for the `_sorted_by` routines below. This takes the left (existing)
/// parameter by reference in order to work with the generic sorting function above.
#define _compare_int(a, b) ((int)*(a) - (int)(b))

#ifdef _MSC_VER
#pragma warning(pop)
#elif defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic pop
#endif

#ifdef __cplusplus
}
#endif

#endif  // TREE_SITTER_ARRAY_H_



================================================
FILE: src/tree_sitter/parser.h
================================================
#ifndef TREE_SITTER_PARSER_H_
#define TREE_SITTER_PARSER_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

#define ts_builtin_sym_error ((TSSymbol)-1)
#define ts_builtin_sym_end 0
#define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024

#ifndef TREE_SITTER_API_H_
typedef uint16_t TSStateId;
typedef uint16_t TSSymbol;
typedef uint16_t TSFieldId;
typedef struct TSLanguage TSLanguage;
typedef struct TSLanguageMetadata {
  uint8_t major_version;
  uint8_t minor_version;
  uint8_t patch_version;
} TSLanguageMetadata;
#endif

typedef struct {
  TSFieldId field_id;
  uint8_t child_index;
  bool inherited;
} TSFieldMapEntry;

// Used to index the field and supertype maps.
typedef struct {
  uint16_t index;
  uint16_t length;
} TSMapSlice;

typedef struct {
  bool visible;
  bool named;
  bool supertype;
} TSSymbolMetadata;

typedef struct TSLexer TSLexer;

struct TSLexer {
  int32_t lookahead;
  TSSymbol result_symbol;
  void (*advance)(TSLexer *, bool);
  void (*mark_end)(TSLexer *);
  uint32_t (*get_column)(TSLexer *);
  bool (*is_at_included_range_start)(const TSLexer *);
  bool (*eof)(const TSLexer *);
  void (*log)(const TSLexer *, const char *, ...);
};

typedef enum {
  TSParseActionTypeShift,
  TSParseActionTypeReduce,
  TSParseActionTypeAccept,
  TSParseActionTypeRecover,
} TSParseActionType;

typedef union {
  struct {
    uint8_t type;
    TSStateId state;
    bool extra;
    bool repetition;
  } shift;
  struct {
    uint8_t type;
    uint8_t child_count;
    TSSymbol symbol;
    int16_t dynamic_precedence;
    uint16_t production_id;
  } reduce;
  uint8_t type;
} TSParseAction;

typedef struct {
  uint16_t lex_state;
  uint16_t external_lex_state;
} TSLexMode;

typedef struct {
  uint16_t lex_state;
  uint16_t external_lex_state;
  uint16_t reserved_word_set_id;
} TSLexerMode;

typedef union {
  TSParseAction action;
  struct {
    uint8_t count;
    bool reusable;
  } entry;
} TSParseActionEntry;

typedef struct {
  int32_t start;
  int32_t end;
} TSCharacterRange;

struct TSLanguage {
  uint32_t abi_version;
  uint32_t symbol_count;
  uint32_t alias_count;
  uint32_t token_count;
  uint32_t external_token_count;
  uint32_t state_count;
  uint32_t large_state_count;
  uint32_t production_id_count;
  uint32_t field_count;
  uint16_t max_alias_sequence_length;
  const uint16_t *parse_table;
  const uint16_t *small_parse_table;
  const uint32_t *small_parse_table_map;
  const TSParseActionEntry *parse_actions;
  const char * const *symbol_names;
  const char * const *field_names;
  const TSMapSlice *field_map_slices;
  const TSFieldMapEntry *field_map_entries;
  const TSSymbolMetadata *symbol_metadata;
  const TSSymbol *public_symbol_map;
  const uint16_t *alias_map;
  const TSSymbol *alias_sequences;
  const TSLexerMode *lex_modes;
  bool (*lex_fn)(TSLexer *, TSStateId);
  bool (*keyword_lex_fn)(TSLexer *, TSStateId);
  TSSymbol keyword_capture_token;
  struct {
    const bool *states;
    const TSSymbol *symbol_map;
    void *(*create)(void);
    void (*destroy)(void *);
    bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist);
    unsigned (*serialize)(void *, char *);
    void (*deserialize)(void *, const char *, unsigned);
  } external_scanner;
  const TSStateId *primary_state_ids;
  const char *name;
  const TSSymbol *reserved_words;
  uint16_t max_reserved_word_set_size;
  uint32_t supertype_count;
  const TSSymbol *supertype_symbols;
  const TSMapSlice *supertype_map_slices;
  const TSSymbol *supertype_map_entries;
  TSLanguageMetadata metadata;
};

static inline bool set_contains(const TSCharacterRange *ranges, uint32_t len, int32_t lookahead) {
  uint32_t index = 0;
  uint32_t size = len - index;
  while (size > 1) {
    uint32_t half_size = size / 2;
    uint32_t mid_index = index + half_size;
    const TSCharacterRange *range = &ranges[mid_index];
    if (lookahead >= range->start && lookahead <= range->end) {
      return true;
    } else if (lookahead > range->end) {
      index = mid_index;
    }
    size -= half_size;
  }
  const TSCharacterRange *range = &ranges[index];
  return (lookahead >= range->start && lookahead <= range->end);
}

/*
 *  Lexer Macros
 */

#ifdef _MSC_VER
#define UNUSED __pragma(warning(suppress : 4101))
#else
#define UNUSED __attribute__((unused))
#endif

#define START_LEXER()           \
  bool result = false;          \
  bool skip = false;            \
  UNUSED                        \
  bool eof = false;             \
  int32_t lookahead;            \
  goto start;                   \
  next_state:                   \
  lexer->advance(lexer, skip);  \
  start:                        \
  skip = false;                 \
  lookahead = lexer->lookahead;

#define ADVANCE(state_value) \
  {                          \
    state = state_value;     \
    goto next_state;         \
  }

#define ADVANCE_MAP(...)                                              \
  {                                                                   \
    static const uint16_t map[] = { __VA_ARGS__ };                    \
    for (uint32_t i = 0; i < sizeof(map) / sizeof(map[0]); i += 2) {  \
      if (map[i] == lookahead) {                                      \
        state = map[i + 1];                                           \
        goto next_state;                                              \
      }                                                               \
    }                                                                 \
  }

#define SKIP(state_value) \
  {                       \
    skip = true;          \
    state = state_value;  \
    goto next_state;      \
  }

#define ACCEPT_TOKEN(symbol_value)     \
  result = true;                       \
  lexer->result_symbol = symbol_value; \
  lexer->mark_end(lexer);

#define END_STATE() return result;

/*
 *  Parse Table Macros
 */

#define SMALL_STATE(id) ((id) - LARGE_STATE_COUNT)

#define STATE(id) id

#define ACTIONS(id) id

#define SHIFT(state_value)            \
  {{                                  \
    .shift = {                        \
      .type = TSParseActionTypeShift, \
      .state = (state_value)          \
    }                                 \
  }}

#define SHIFT_REPEAT(state_value)     \
  {{                                  \
    .shift = {                        \
      .type = TSParseActionTypeShift, \
      .state = (state_value),         \
      .repetition = true              \
    }                                 \
  }}

#define SHIFT_EXTRA()                 \
  {{                                  \
    .shift = {                        \
      .type = TSParseActionTypeShift, \
      .extra = true                   \
    }                                 \
  }}

#define REDUCE(symbol_name, children, precedence, prod_id) \
  {{                                                       \
    .reduce = {                                            \
      .type = TSParseActionTypeReduce,                     \
      .symbol = symbol_name,                               \
      .child_count = children,                             \
      .dynamic_precedence = precedence,                    \
      .production_id = prod_id                             \
    },                                                     \
  }}

#define RECOVER()                    \
  {{                                 \
    .type = TSParseActionTypeRecover \
  }}

#define ACCEPT_INPUT()              \
  {{                                \
    .type = TSParseActionTypeAccept \
  }}

#ifdef __cplusplus
}
#endif

#endif  // TREE_SITTER_PARSER_H_



================================================
FILE: test/corpus/ambiguities.txt
================================================
================================================
template functions vs relational expressions
================================================

T1 a = b < c > d;
T2 e = f<T3>(g);
int a = std::get<0>(t);
if (x.y < z) break; // Not a template missing a '>'
if (x.y < x->y && x.y > 50) break;
if (x.foo < 0 || bar >= 1) break;
if (x.Base::foo < 0 || bar >= 1) {
  bool i = x.Base::foo < 0 || 1 > (5); // No way to tell
}

---

(translation_unit
  (declaration
    (type_identifier)
    (init_declarator
      (identifier)
      (binary_expression
        (binary_expression (identifier) (identifier))
        (identifier))))
  (declaration
    (type_identifier)
    (init_declarator
      (identifier)
      (call_expression
        (template_function (identifier) (template_argument_list
          (type_descriptor (type_identifier))))
        (argument_list (identifier)))))
  (declaration
    (primitive_type)
    (init_declarator
      (identifier)
      (call_expression
        (qualified_identifier
          (namespace_identifier)
          (template_function
            (identifier)
            (template_argument_list (number_literal))))
        (argument_list (identifier)))))
  (if_statement
    (condition_clause
      (binary_expression
        (field_expression
          (identifier)
          (field_identifier))
        (identifier)))
    (break_statement))
  (comment)
  (if_statement
    (condition_clause
      (binary_expression
        (binary_expression
          (field_expression
            (identifier)
            (field_identifier))
          (field_expression
            (identifier)
            (field_identifier)))
        (binary_expression
          (field_expression
            (identifier)
            (field_identifier))
          (number_literal))))
    (break_statement))
  (if_statement
    (condition_clause
      (binary_expression
        (binary_expression
          (field_expression
            (identifier)
            (field_identifier))
          (number_literal))
        (binary_expression
          (identifier)
          (number_literal))))
    (break_statement))
  (if_statement
    (condition_clause
      (binary_expression
        (binary_expression
          (field_expression
            (identifier)
            (qualified_identifier
              (namespace_identifier)
              (field_identifier)))
          (number_literal))
        (binary_expression
          (identifier)
          (number_literal))))
    (compound_statement
      (declaration
        (primitive_type)
        (init_declarator
          (identifier)
          (binary_expression
            (binary_expression
              (field_expression
                (identifier)
                (qualified_identifier
                  (namespace_identifier)
                  (field_identifier)))
              (number_literal))
            (binary_expression
              (number_literal)
              (parenthesized_expression
                (number_literal))))))
    (comment))))

=================================================
function declarations vs variable initializations
=================================================

// Function declarations
T1 a(T2 *b);
T3 c(T4 &d, T5 &&e);

// Variable declarations with initializers
T7 f(g.h);
T6 i{j};

---

(translation_unit
  (comment)
  (declaration
    (type_identifier)
    (function_declarator
      (identifier)
      (parameter_list (parameter_declaration (type_identifier) (pointer_declarator (identifier))))))
  (declaration
    (type_identifier)
    (function_declarator
      (identifier)
      (parameter_list
        (parameter_declaration (type_identifier) (reference_declarator (identifier)))
        (parameter_declaration (type_identifier) (reference_declarator (identifier))))))

  (comment)
  (declaration
    (type_identifier)
    (init_declarator
      (identifier)
      (argument_list (field_expression (identifier) (field_identifier)))))
  (declaration
    (type_identifier)
    (init_declarator
      (identifier)
      (initializer_list (identifier)))))

================================================
template classes vs relational expressions
================================================

int main() {
  T1<T2> v1;
  T1<T2> v2 = v3;
}

---

(translation_unit (function_definition
  (primitive_type)
  (function_declarator (identifier) (parameter_list))
  (compound_statement
    (declaration
      (template_type (type_identifier)
        (template_argument_list (type_descriptor (type_identifier))))
      (identifier))
    (declaration
      (template_type (type_identifier)
        (template_argument_list (type_descriptor (type_identifier))))
      (init_declarator (identifier) (identifier))))))



================================================
FILE: test/corpus/concepts.txt
================================================
================================================================================
Concept definition
================================================================================

template <class T, class U>
concept Derived = std::is_base_of<U, T>::value;
--------------------------------------------------------------------------------

(translation_unit
  (template_declaration
    (template_parameter_list
      (type_parameter_declaration
        (type_identifier))
      (type_parameter_declaration
        (type_identifier)))
    (concept_definition
      (identifier)
      (qualified_identifier
        (namespace_identifier)
        (qualified_identifier
          (template_type
            (type_identifier)
            (template_argument_list
              (type_descriptor
                (type_identifier))
              (type_descriptor
                (type_identifier))))
          (identifier))))))

================================================================================
Concept definition with requires expression
================================================================================

template<typename T>
concept Hashable = requires(T a) {
    { std::hash<T>{}(a) } -> std::convertible_to<std::size_t>;
};
--------------------------------------------------------------------------------

(translation_unit
  (template_declaration
    (template_parameter_list
      (type_parameter_declaration
        (type_identifier)))
    (concept_definition
      (identifier)
      (requires_expression
        (parameter_list
          (parameter_declaration
            (type_identifier)
            (identifier)))
        (requirement_seq
          (compound_requirement
            (call_expression
              (compound_literal_expression
                (qualified_identifier
                  (namespace_identifier)
                  (template_type
                    (type_identifier)
                    (template_argument_list
                      (type_descriptor
                        (type_identifier)))))
                (initializer_list))
              (argument_list
                (identifier)))
            (trailing_return_type
              (type_descriptor
                (qualified_identifier
                  (namespace_identifier)
                  (template_type
                    (type_identifier)
                    (template_argument_list
                      (type_descriptor
                        (qualified_identifier
                          (namespace_identifier)
                          (type_identifier))))))))))))))

================================================================================
Requires clauses and expressions
================================================================================

template<typename T>
void f(T&&) requires Eq<T>; // can appear as the last element of a function declarator

template<typename T> requires Addable<T> // or right after a template parameter list
T add(T a, T b) { return a + b; }

template<typename T>
concept Addable = requires (T x) { x + x; }; // requires-expression

template<typename T>
    requires requires (T x) { x + x; } // ad-hoc constraint, note keyword used twice
T add(T a, T b) { return a + b; }

template<typename T>
    requires (!std::is_same_v<T, bool>) // parenthesized expressions are allowed
void f(T);

template<typename T> requires Addable<T> && Subtractable<T> // conjunctions
T f(T);

template<typename T> requires Addable<T> and Subtractable<T> // conjunctions
T f(T);

template<typename T> requires Addable<T> || Subtractable<T> // disjunctions
T f(T);

template<typename T> requires Addable<T> or Subtractable<T> // conjunctions
T f(T);

template<typename T> requires false || true // boolean literals
T f(T);

template<typename... T> requires (... && Addable<T>) // fold expressions
T f(T);

--------------------------------------------------------------------------------

(translation_unit
  (template_declaration
    (template_parameter_list
      (type_parameter_declaration
        (type_identifier)))
    (declaration
      (primitive_type)
      (function_declarator
        (identifier)
        (parameter_list
          (parameter_declaration
            (type_identifier)
            (abstract_reference_declarator)))
        (requires_clause
          (template_type
            (type_identifier)
            (template_argument_list
              (type_descriptor
                (type_identifier))))))))
  (comment)
  (template_declaration
    (template_parameter_list
      (type_parameter_declaration
        (type_identifier)))
    (requires_clause
      (template_type
        (type_identifier)
        (template_argument_list
          (type_descriptor
            (type_identifier)))))
    (comment)
    (function_definition
      (type_identifier)
      (function_declarator
        (identifier)
        (parameter_list
          (parameter_declaration
            (type_identifier)
            (identifier))
          (parameter_declaration
            (type_identifier)
            (identifier))))
      (compound_statement
        (return_statement
          (binary_expression
            (identifier)
            (identifier))))))
  (template_declaration
    (template_parameter_list
      (type_parameter_declaration
        (type_identifier)))
    (concept_definition
      (identifier)
      (requires_expression
        (parameter_list
          (parameter_declaration
            (type_identifier)
            (identifier)))
        (requirement_seq
          (simple_requirement
            (binary_expression
              (identifier)
              (identifier)))))))
  (comment)
  (template_declaration
    (template_parameter_list
      (type_parameter_declaration
        (type_identifier)))
    (requires_clause
      (requires_expression
        (parameter_list
          (parameter_declaration
            (type_identifier)
            (identifier)))
        (requirement_seq
          (simple_requirement
            (binary_expression
              (identifier)
              (identifier))))))
    (comment)
    (function_definition
      (type_identifier)
      (function_declarator
        (identifier)
        (parameter_list
          (parameter_declaration
            (type_identifier)
            (identifier))
          (parameter_declaration
            (type_identifier)
            (identifier))))
      (compound_statement
        (return_statement
          (binary_expression
            (identifier)
            (identifier))))))
      (template_declaration
        (template_parameter_list
          (type_parameter_declaration
            (type_identifier)))
        (requires_clause
          (unary_expression
            (qualified_identifier
              (namespace_identifier)
              (template_function
                (identifier)
                (template_argument_list
                  (type_descriptor
                    (type_identifier))
                  (type_descriptor
                    (primitive_type)))))))
        (comment)
        (declaration
          (primitive_type)
          (function_declarator
            (identifier)
            (parameter_list
              (parameter_declaration
                (type_identifier))))))
      (template_declaration
        (template_parameter_list
          (type_parameter_declaration
            (type_identifier)))
        (requires_clause
          (constraint_conjunction
            (template_type
              (type_identifier)
              (template_argument_list
                (type_descriptor
                  (type_identifier))))
            (template_type
              (type_identifier)
              (template_argument_list
                (type_descriptor
                  (type_identifier))))))
        (comment)
        (declaration
          (type_identifier)
          (function_declarator
            (identifier)
            (parameter_list
              (parameter_declaration
                (type_identifier))))))
      (template_declaration
        (template_parameter_list
          (type_parameter_declaration
            (type_identifier)))
        (requires_clause
          (constraint_conjunction
            (template_type
              (type_identifier)
              (template_argument_list
                (type_descriptor
                  (type_identifier))))
            (template_type
              (type_identifier)
              (template_argument_list
                (type_descriptor
                  (type_identifier))))))
        (comment)
        (declaration
          (type_identifier)
          (function_declarator
            (identifier)
            (parameter_list
              (parameter_declaration
                (type_identifier))))))
      (template_declaration
        (template_parameter_list
          (type_parameter_declaration
            (type_identifier)))
        (requires_clause
          (constraint_disjunction
            (template_type
              (type_identifier)
              (template_argument_list
                (type_descriptor
                  (type_identifier))))
            (template_type
              (type_identifier)
              (template_argument_list
                (type_descriptor
                  (type_identifier))))))
        (comment)
        (declaration
          (type_identifier)
          (function_declarator
            (identifier)
            (parameter_list
              (parameter_declaration
                (type_identifier))))))
      (template_declaration
        (template_parameter_list
          (type_parameter_declaration
            (type_identifier)))
        (requires_clause
          (constraint_disjunction
            (template_type
              (type_identifier)
              (template_argument_list
                (type_descriptor
                  (type_identifier))))
            (template_type
              (type_identifier)
              (template_argument_list
                (type_descriptor
                  (type_identifier))))))
        (comment)
        (declaration
          (type_identifier)
          (function_declarator
            (identifier)
            (parameter_list
              (parameter_declaration
                (type_identifier))))))
      (template_declaration
        (template_parameter_list
          (type_parameter_declaration
            (type_identifier)))
        (requires_clause
          (constraint_disjunction
            (false)
            (true)))
        (comment)
        (declaration
          (type_identifier)
          (function_declarator
            (identifier)
            (parameter_list
              (parameter_declaration
                (type_identifier))))))
      (template_declaration
        (template_parameter_list
          (variadic_type_parameter_declaration
            (type_identifier)))
        (requires_clause
          (fold_expression
            (template_function
              (identifier)
              (template_argument_list
                (type_descriptor
                  (type_identifier))))))
        (comment)
        (declaration
          (type_identifier)
          (function_declarator
            (identifier)
            (parameter_list
              (parameter_declaration
                (type_identifier)))))))

================================================================================
Compound requirements
================================================================================

template<typename T> concept C2 =
requires(T x) {
    {*x} -> std::convertible_to<typename T::inner>; // the expression *x must be valid
                                                    // AND the type T::inner must be valid
                                                    // AND the result of *x must be convertible to T::inner
    {x + 1} -> std::same_as<int>; // the expression x + 1 must be valid
                               // AND std::same_as<decltype((x + 1)), int> must be satisfied
                               // i.e., (x + 1) must be a prvalue of type int
    {x * 1} -> std::convertible_to<T>; // the expression x * 1 must be valid
                                       // AND its result must be convertible to T
};

--------------------------------------------------------------------------------

(translation_unit
  (template_declaration
    (template_parameter_list
      (type_parameter_declaration
        (type_identifier)))
    (concept_definition
      (identifier)
      (requires_expression
        (parameter_list
          (parameter_declaration
            (type_identifier)
            (identifier)))
        (requirement_seq
          (compound_requirement
            (pointer_expression
              (identifier))
            (trailing_return_type
              (type_descriptor
                (qualified_identifier
                  (namespace_identifier)
                  (template_type
                    (type_identifier)
                    (template_argument_list
                      (type_descriptor
                        (dependent_type
                          (qualified_identifier
                            (namespace_identifier)
                            (type_identifier))))))))))
          (comment)
          (comment)
          (comment)
          (compound_requirement
            (binary_expression
              (identifier)
              (number_literal))
            (trailing_return_type
              (type_descriptor
                (qualified_identifier
                  (namespace_identifier)
                  (template_type
                    (type_identifier)
                    (template_argument_list
                      (type_descriptor
                        (primitive_type))))))))
          (comment)
          (comment)
          (comment)
          (compound_requirement
            (binary_expression
              (identifier)
              (number_literal))
            (trailing_return_type
              (type_descriptor
                (qualified_identifier
                  (namespace_identifier)
                  (template_type
                    (type_identifier)
                    (template_argument_list
                      (type_descriptor
                        (type_identifier))))))))
          (comment)
          (comment))))))

================================================================================
Nested requirements
================================================================================

template <class T>
concept Semiregular = DefaultConstructible<T> &&
    CopyConstructible<T> && Destructible<T> && CopyAssignable<T> &&
requires(T a, size_t n) {
    requires Same<T*, decltype(&a)>;  // nested: "Same<...> evaluates to true"
    { a.~T() } noexcept;  // compound: "a.~T()" is a valid expression that doesn't throw
    requires Same<T*, decltype(new T)>; // nested: "Same<...> evaluates to true"
    requires Same<T*, decltype(new T[n])>; // nested
    { delete new T };  // compound
    { delete new T[n] }; // compound
};
--------------------------------------------------------------------------------

(translation_unit
  (template_declaration
    (template_parameter_list
      (type_parameter_declaration
        (type_identifier)))
    (concept_definition
      (identifier)
      (binary_expression
        (binary_expression
          (binary_expression
            (binary_expression
              (template_function
                (identifier)
                (template_argument_list
                  (type_descriptor
                    (type_identifier))))
              (template_function
                (identifier)
                (template_argument_list
                  (type_descriptor
                    (type_identifier)))))
            (template_function
              (identifier)
              (template_argument_list
                (type_descriptor
                  (type_identifier)))))
          (template_function
            (identifier)
            (template_argument_list
              (type_descriptor
                (type_identifier)))))
        (requires_expression
          (parameter_list
            (parameter_declaration
              (type_identifier)
              (identifier))
            (parameter_declaration
              (primitive_type)
              (identifier)))
          (requirement_seq
            (simple_requirement
              (requires_clause
                (template_type
                  (type_identifier)
                  (template_argument_list
                    (type_descriptor
                      (type_identifier)
                      (abstract_pointer_declarator))
                    (type_descriptor
                      (decltype
                        (pointer_expression
                          (identifier))))))))
            (comment)
            (compound_requirement
              (call_expression
                (field_expression
                  (identifier)
                  (destructor_name
                    (identifier)))
                (argument_list)))
            (comment)
            (simple_requirement
              (requires_clause
                (template_type
                  (type_identifier)
                  (template_argument_list
                    (type_descriptor
                      (type_identifier)
                      (abstract_pointer_declarator))
                    (type_descriptor
                      (decltype
                        (new_expression
                          (type_identifier))))))))
            (comment)
            (simple_requirement
              (requires_clause
                (template_type
                  (type_identifier)
                  (template_argument_list
                    (type_descriptor
                      (type_identifier)
                      (abstract_pointer_declarator))
                    (type_descriptor
                      (decltype
                        (new_expression
                          (type_identifier)
                          (new_declarator
                            (identifier)))))))))
            (comment)
            (compound_requirement
              (delete_expression
                (new_expression
                  (type_identifier))))
            (comment)
            (compound_requirement
              (delete_expression
                (new_expression
                  (type_identifier)
                  (new_declarator
                    (identifier)))))
            (comment)))))))

================================================================================
Constraints
================================================================================

template <EqualityComparable T>
void f(const T&); // constrained function template declaration

void f(const EqualityComparable auto&); // constrained function template declaration

Sortable auto foo = f();
Sortable<T> auto bar = g();
NS::Concept<T> auto baz = h();

Sortable decltype(auto) foo = i();

---

(translation_unit
  (template_declaration
    (template_parameter_list
      (parameter_declaration
        (type_identifier)
        (identifier)))
    (declaration
      (primitive_type)
      (function_declarator
        (identifier)
        (parameter_list
          (parameter_declaration
            (type_qualifier)
            (type_identifier)
            (abstract_reference_declarator))))))
  (comment)
  (declaration
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list
        (parameter_declaration
          (type_qualifier)
          (placeholder_type_specifier
            (type_identifier)
            (auto))
          (abstract_reference_declarator)))))
  (comment)
  (declaration
    (placeholder_type_specifier
      (type_identifier)
      (auto))
    (init_declarator
      (identifier)
      (call_expression
        (identifier)
        (argument_list))))
  (declaration
    (placeholder_type_specifier
      (template_type
        (type_identifier)
        (template_argument_list
          (type_descriptor
            (type_identifier))))
      (auto))
    (init_declarator
      (identifier)
      (call_expression
        (identifier)
        (argument_list))))
  (declaration
    (placeholder_type_specifier
      (qualified_identifier
        (namespace_identifier)
        (template_type
          (type_identifier)
          (template_argument_list
            (type_descriptor
              (type_identifier)))))
      (auto))
    (init_declarator
      (identifier)
      (call_expression
        (identifier)
        (argument_list))))
  (declaration
    (placeholder_type_specifier
      (type_identifier)
      (decltype
        (auto)))
    (init_declarator
      (identifier)
      (call_expression
        (identifier)
        (argument_list)))))



================================================
FILE: test/corpus/definitions.txt
================================================
================================================================================
Scoped function definitions
================================================================================

int T::foo() { return 1; }
int T::foo() const { return 0; }

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (qualified_identifier
        (namespace_identifier)
        (identifier))
      (parameter_list))
    (compound_statement
      (return_statement
        (number_literal))))
  (function_definition
    (primitive_type)
    (function_declarator
      (qualified_identifier
        (namespace_identifier)
        (identifier))
      (parameter_list)
      (type_qualifier))
    (compound_statement
      (return_statement
        (number_literal)))))

================================================================================
Constructor definitions
================================================================================

T::T() {}

T::T() : f1(0), f2(1, 2) {
  puts("HI");
}

T::T() : Base<T>() {}

T::T() try : f1(0) {} catch(...) {}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (function_declarator
      (qualified_identifier
        (namespace_identifier)
        (identifier))
      (parameter_list))
    (compound_statement))
  (function_definition
    (function_declarator
      (qualified_identifier
        (namespace_identifier)
        (identifier))
      (parameter_list))
    (field_initializer_list
      (field_initializer
        (field_identifier)
        (argument_list
          (number_literal)))
      (field_initializer
        (field_identifier)
        (argument_list
          (number_literal)
          (number_literal))))
    (compound_statement
      (expression_statement
        (call_expression
          (identifier)
          (argument_list
            (string_literal
              (string_content)))))))
  (function_definition
    (function_declarator
      (qualified_identifier
        (namespace_identifier)
        (identifier))
      (parameter_list))
    (field_initializer_list
      (field_initializer
        (template_method
          (field_identifier)
          (template_argument_list
            (type_descriptor
              (type_identifier))))
        (argument_list)))
    (compound_statement))
  (function_definition
    (function_declarator
      (qualified_identifier
        (namespace_identifier)
        (identifier))
      (parameter_list))
    (try_statement
      (field_initializer_list
        (field_initializer
          (field_identifier)
          (argument_list
            (number_literal))))
      (compound_statement)
      (catch_clause
        (parameter_list)
        (compound_statement)))))

================================================================================
Explicit constructor definitions
================================================================================

class C {
  explicit C(int f) : f_(f) {}

 private:
  int f_;
};

--------------------------------------------------------------------------------

(translation_unit
  (class_specifier
    (type_identifier)
    (field_declaration_list
      (function_definition
        (explicit_function_specifier)
        (function_declarator
          (identifier)
          (parameter_list
            (parameter_declaration
              (primitive_type)
              (identifier))))
        (field_initializer_list
          (field_initializer
            (field_identifier)
            (argument_list
              (identifier))))
        (compound_statement))
      (access_specifier)
      (field_declaration
        (primitive_type)
        (field_identifier)))))

================================================================================
Explicit constructor declaration
================================================================================

class C {
  explicit C(int f);
  explicit(true) C(long f);
};

--------------------------------------------------------------------------------

(translation_unit
  (class_specifier
    (type_identifier)
    (field_declaration_list
      (declaration
        (explicit_function_specifier)
        (function_declarator
          (identifier)
          (parameter_list
            (parameter_declaration
              (primitive_type)
              (identifier)))))
      (declaration
        (explicit_function_specifier
          (true))
        (function_declarator
          (identifier)
          (parameter_list
            (parameter_declaration
              (sized_type_specifier)
              (identifier))))))))

================================================================================
Default, delete, and pure virtual methods
================================================================================

class A : public B {
  A() = default;
  A(A &&) = delete;
  void f() = delete;
  A& operator=(const A&) = default;
  A& operator=(A&&) = delete;
  ~A() = 0;
};

--------------------------------------------------------------------------------

(translation_unit
  (class_specifier
    (type_identifier)
    (base_class_clause
      (access_specifier)
      (type_identifier))
    (field_declaration_list
      (function_definition
        (function_declarator
          (identifier)
          (parameter_list))
        (default_method_clause))
      (function_definition
        (function_declarator
          (identifier)
          (parameter_list
            (parameter_declaration
              (type_identifier)
              (abstract_reference_declarator))))
        (delete_method_clause))
      (function_definition
        (primitive_type)
        (function_declarator
          (field_identifier)
          (parameter_list))
        (delete_method_clause))
      (function_definition
        (type_identifier)
        (reference_declarator
          (function_declarator
            (operator_name)
            (parameter_list
              (parameter_declaration
                (type_qualifier)
                (type_identifier)
                (abstract_reference_declarator)))))
        (default_method_clause))
      (function_definition
        (type_identifier)
        (reference_declarator
          (function_declarator
            (operator_name)
            (parameter_list
              (parameter_declaration
                (type_identifier)
                (abstract_reference_declarator)))))
        (delete_method_clause))
      (function_definition
        (function_declarator
          (destructor_name
            (identifier))
          (parameter_list))
        (pure_virtual_clause)))))

================================================================================
Destructor definitions
================================================================================

~T() {}
T::~T() {}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (function_declarator
      (destructor_name
        (identifier))
      (parameter_list))
    (compound_statement))
  (function_definition
    (function_declarator
      (qualified_identifier
        (namespace_identifier)
        (destructor_name
          (identifier)))
      (parameter_list))
    (compound_statement)))

================================================================================
Function-try-block definitions
================================================================================

void foo() try {} catch(...) {}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (try_statement
      (compound_statement)
      (catch_clause
        (parameter_list)
        (compound_statement)))))

================================================================================
Conversion operator definitions
================================================================================

T::operator int() try { throw 1; } catch (...) { return 2; }

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (qualified_identifier
      (namespace_identifier)
      (operator_cast
        (primitive_type)
        (abstract_function_declarator
          (parameter_list))))
    (try_statement
      (compound_statement
        (throw_statement
          (number_literal)))
      (catch_clause
        (parameter_list)
        (compound_statement
          (return_statement
            (number_literal)))))))



================================================
FILE: test/corpus/expressions.txt
================================================
================================================================================
Scoped function calls
================================================================================

int main() {
  abc::def("hello", "world");
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (expression_statement
        (call_expression
          (qualified_identifier
            (namespace_identifier)
            (identifier))
          (argument_list
            (string_literal
              (string_content))
            (string_literal
              (string_content))))))))

================================================================================
Compound literals without parentheses
================================================================================

T x = T{0};
U<V> y = U<V>{0};
int x = int{1};

--------------------------------------------------------------------------------

(translation_unit
  (declaration
    (type_identifier)
    (init_declarator
      (identifier)
      (compound_literal_expression
        (type_identifier)
        (initializer_list
          (number_literal)))))
  (declaration
    (template_type
      (type_identifier)
      (template_argument_list
        (type_descriptor
          (type_identifier))))
    (init_declarator
      (identifier)
      (compound_literal_expression
        (template_type
          (type_identifier)
          (template_argument_list
            (type_descriptor
              (type_identifier))))
        (initializer_list
          (number_literal)))))
  (declaration
    (primitive_type)
    (init_declarator
      (identifier)
      (compound_literal_expression
        (primitive_type)
        (initializer_list
          (number_literal))))))

================================================================================
Explicit destructor calls
================================================================================

int main() {
  foo.~Foo();
  bar->~Bar();
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (expression_statement
        (call_expression
          (field_expression
            (identifier)
            (destructor_name
              (identifier)))
          (argument_list)))
      (expression_statement
        (call_expression
          (field_expression
            (identifier)
            (destructor_name
              (identifier)))
          (argument_list))))))

================================================================================
New and Delete expressions
================================================================================

int main() {
  auto a = new T();
  auto b = new U::V<W, X>{};
  auto c = new (&d) T;
  auto d = new T[5][3]();
  auto e = new int[5];
  d = new(2, f) T;
  delete a;
  ::delete[] c;
  ::new (foo(x)) T(this, x);
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (declaration
        (placeholder_type_specifier
          (auto))
        (init_declarator
          (identifier)
          (new_expression
            (type_identifier)
            (argument_list))))
      (declaration
        (placeholder_type_specifier
          (auto))
        (init_declarator
          (identifier)
          (new_expression
            (qualified_identifier
              (namespace_identifier)
              (template_type
                (type_identifier)
                (template_argument_list
                  (type_descriptor
                    (type_identifier))
                  (type_descriptor
                    (type_identifier)))))
            (initializer_list))))
      (declaration
        (placeholder_type_specifier
          (auto))
        (init_declarator
          (identifier)
          (new_expression
            (argument_list
              (pointer_expression
                (identifier)))
            (type_identifier))))
      (declaration
        (placeholder_type_specifier
          (auto))
        (init_declarator
          (identifier)
          (new_expression
            (type_identifier)
            (new_declarator
              (number_literal)
              (new_declarator
                (number_literal)))
            (argument_list))))
      (declaration
        (placeholder_type_specifier
          (auto))
        (init_declarator
          (identifier)
          (new_expression
            (primitive_type)
            (new_declarator
              (number_literal)))))
      (expression_statement
        (assignment_expression
          (identifier)
          (new_expression
            (argument_list
              (number_literal)
              (identifier))
            (type_identifier))))
      (expression_statement
        (delete_expression
          (identifier)))
      (expression_statement
        (delete_expression
          (identifier)))
      (expression_statement
        (new_expression
          (argument_list
            (call_expression
              (identifier)
              (argument_list
                (identifier))))
          (type_identifier)
          (argument_list
            (this)
            (identifier)))))))

================================================================================
Initializer lists as arguments
================================================================================

int main() {
  pairs.push_back({true, false});
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (expression_statement
        (call_expression
          (field_expression
            (identifier)
            (field_identifier))
          (argument_list
            (initializer_list
              (true)
              (false))))))))

================================================================================
Initializer list as assignment expression RHS
================================================================================

void test() {
    int b = int{1};
    b = int{2};
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (declaration
        (primitive_type)
        (init_declarator
          (identifier)
          (compound_literal_expression
            (primitive_type)
            (initializer_list
              (number_literal)))))
      (expression_statement
        (assignment_expression
          (identifier)
          (compound_literal_expression
            (primitive_type)
            (initializer_list
              (number_literal))))))))

================================================================================
Lambda expressions
================================================================================

auto f = [&](int x) -> bool {
  return true;
};

auto f = [x, y](int z) {
  return false;
};

auto f = [] {
  return false;
};

auto f = [] <typename T> () {
  return T();
};

auto f = [] <typename T> requires Hashable<T> {
  return T();
};

auto f = [... args = std::forward<Args>(args)](auto &&func) mutable {
  return std::invoke(std::forward<decltype(func)>(func), std::forward<Args>(args)...);
};

auto f = [&arg, &...etc = etc] {};

auto f = [=, *this, &args...] {};

auto f = [] -> int {};

auto f = [s = S{}] mutable {};

auto f = [] [[noreturn]] (int i) { throw 1; };

auto f = [](int i) consteval static noexcept -> int { return i + 1; }(5);

--------------------------------------------------------------------------------

(translation_unit
  (declaration
    (placeholder_type_specifier
      (auto))
    (init_declarator
      (identifier)
      (lambda_expression
        (lambda_capture_specifier
          (lambda_default_capture))
        (lambda_declarator
          (parameter_list
            (parameter_declaration
              (primitive_type)
              (identifier)))
          (trailing_return_type
            (type_descriptor
              (primitive_type))))
        (compound_statement
          (return_statement
            (true))))))
  (declaration
    (placeholder_type_specifier
      (auto))
    (init_declarator
      (identifier)
      (lambda_expression
        (lambda_capture_specifier
          (identifier)
          (identifier))
        (lambda_declarator
          (parameter_list
            (parameter_declaration
              (primitive_type)
              (identifier))))
        (compound_statement
          (return_statement
            (false))))))
  (declaration
    (placeholder_type_specifier
      (auto))
    (init_declarator
      (identifier)
      (lambda_expression
        (lambda_capture_specifier)
        (compound_statement
          (return_statement
            (false))))))
  (declaration
    (placeholder_type_specifier
      (auto))
    (init_declarator
      (identifier)
      (lambda_expression
        (lambda_capture_specifier)
        (template_parameter_list
          (type_parameter_declaration
            (type_identifier)))
        (lambda_declarator
          (parameter_list))
        (compound_statement
          (return_statement
            (call_expression
              (identifier)
              (argument_list)))))))
  (declaration
    (placeholder_type_specifier
      (auto))
    (init_declarator
      (identifier)
      (lambda_expression
        (lambda_capture_specifier)
        (template_parameter_list
          (type_parameter_declaration
            (type_identifier)))
        (requires_clause
          (template_type
            (type_identifier)
            (template_argument_list
              (type_descriptor
                (type_identifier)))))
        (compound_statement
          (return_statement
            (call_expression
              (identifier)
              (argument_list)))))))
  (declaration
    (placeholder_type_specifier
      (auto))
    (init_declarator
      (identifier)
      (lambda_expression
        (lambda_capture_specifier
          (lambda_capture_initializer
            (identifier)
            (call_expression
              (qualified_identifier
                (namespace_identifier)
                (template_function
                  (identifier)
                  (template_argument_list
                    (type_descriptor
                      (type_identifier)))))
              (argument_list
                (identifier)))))
        (lambda_declarator
          (parameter_list
            (parameter_declaration
              (placeholder_type_specifier
                (auto))
              (reference_declarator
                (identifier))))
          (lambda_specifier))
        (compound_statement
          (return_statement
            (call_expression
              (qualified_identifier
                (namespace_identifier)
                (identifier))
              (argument_list
                (call_expression
                  (qualified_identifier
                    (namespace_identifier)
                    (template_function
                      (identifier)
                      (template_argument_list
                        (type_descriptor
                          (decltype
                            (identifier))))))
                  (argument_list
                    (identifier)))
                (parameter_pack_expansion
                  (call_expression
                    (qualified_identifier
                      (namespace_identifier)
                      (template_function
                        (identifier)
                        (template_argument_list
                          (type_descriptor
                            (type_identifier)))))
                    (argument_list
                      (identifier)))))))))))
  (declaration
    (placeholder_type_specifier
      (auto))
    (init_declarator
      (identifier)
      (lambda_expression
        (lambda_capture_specifier
          (identifier)
          (lambda_capture_initializer
            (identifier)
            (identifier)))
        (compound_statement))))
  (declaration
    (placeholder_type_specifier
      (auto))
    (init_declarator
      (identifier)
      (lambda_expression
        (lambda_capture_specifier
          (lambda_default_capture)
          (this)
          (parameter_pack_expansion
            (identifier)))
        (compound_statement))))
  (declaration
    (placeholder_type_specifier
      (auto))
    (init_declarator
      (identifier)
      (lambda_expression
        (lambda_capture_specifier)
        (lambda_declarator
          (trailing_return_type
            (type_descriptor
              (primitive_type))))
        (compound_statement))))
  (declaration
    (placeholder_type_specifier
      (auto))
    (init_declarator
      (identifier)
      (lambda_expression
        (lambda_capture_specifier
          (lambda_capture_initializer
            (identifier)
            (compound_literal_expression
              (type_identifier)
              (initializer_list))))
        (lambda_declarator
          (lambda_specifier))
        (compound_statement))))
  (declaration
    (placeholder_type_specifier
      (auto))
    (init_declarator
      (identifier)
      (lambda_expression
        (lambda_capture_specifier)
        (lambda_declarator
          (attribute_declaration
            (attribute
              (identifier)))
          (parameter_list
            (parameter_declaration
              (primitive_type)
              (identifier))))
        (compound_statement
          (throw_statement
                (number_literal))))))
      (declaration
        (placeholder_type_specifier
          (auto))
        (init_declarator
          (identifier)
          (call_expression
            (lambda_expression
              (lambda_capture_specifier)
              (lambda_declarator
                (parameter_list
                  (parameter_declaration
                    (primitive_type)
                    (identifier)))
                (lambda_specifier)
                (lambda_specifier)
                (noexcept)
                (trailing_return_type
                  (type_descriptor
                    (primitive_type))))
              (compound_statement
                (return_statement
                  (binary_expression
                    (identifier)
                    (number_literal)))))
            (argument_list
              (number_literal))))))

================================================================================
Nested template calls
================================================================================

class A {
  A() : T::template Nested<int>::type() {}
  A() : T::template Nested<int>::template Nested2<float>::type() {}

  B<C::D<E, F>>::G field;
  using B<C>::template D<int>;

  H<I<J>> method() {
    K::L<M<N>> variable1 = K::L<M<N>>{};
    typename K::template L<M<N>>::type variable2;
    typename K::template L<M<N>>::template O<P>::type variable3;
  }

  typename Z::template Nested<int>::type x;
  typename X::template Nested<int>::Y::template Nested2<D> x;
};

--------------------------------------------------------------------------------

(translation_unit
  (class_specifier
    (type_identifier)
    (field_declaration_list
      (function_definition
        (function_declarator
          (identifier)
          (parameter_list))
        (field_initializer_list
          (field_initializer
            (qualified_identifier
              (namespace_identifier)
              (qualified_identifier
                (dependent_name
                  (template_type
                    (type_identifier)
                    (template_argument_list
                      (type_descriptor
                        (primitive_type)))))
                (field_identifier)))
            (argument_list)))
        (compound_statement))
      (function_definition
        (function_declarator
          (identifier)
          (parameter_list))
        (field_initializer_list
          (field_initializer
            (qualified_identifier
              (namespace_identifier)
              (qualified_identifier
                (dependent_name
                  (template_type
                    (type_identifier)
                    (template_argument_list
                      (type_descriptor
                        (primitive_type)))))
                (qualified_identifier
                  (dependent_name
                    (template_type
                      (type_identifier)
                      (template_argument_list
                        (type_descriptor
                          (primitive_type)))))
                  (field_identifier))))
            (argument_list)))
        (compound_statement))
      (field_declaration
        (qualified_identifier
          (template_type
            (type_identifier)
            (template_argument_list
              (type_descriptor
                (qualified_identifier
                  (namespace_identifier)
                  (template_type
                    (type_identifier)
                    (template_argument_list
                      (type_descriptor
                        (type_identifier))
                      (type_descriptor
                        (type_identifier))))))))
          (type_identifier))
        (field_identifier))
      (using_declaration
        (qualified_identifier
          (template_type
            (type_identifier)
            (template_argument_list
              (type_descriptor
                (type_identifier))))
          (dependent_name
            (template_function
              (identifier)
              (template_argument_list
                (type_descriptor
                  (primitive_type)))))))
      (function_definition
        (template_type
          (type_identifier)
          (template_argument_list
            (type_descriptor
              (template_type
                (type_identifier)
                (template_argument_list
                  (type_descriptor
                    (type_identifier)))))))
        (function_declarator
          (field_identifier)
          (parameter_list))
        (compound_statement
          (declaration
            (qualified_identifier
              (namespace_identifier)
              (template_type
                (type_identifier)
                (template_argument_list
                  (type_descriptor
                    (template_type
                      (type_identifier)
                      (template_argument_list
                        (type_descriptor
                          (type_identifier))))))))
            (init_declarator
              (identifier)
              (compound_literal_expression
                (qualified_identifier
                  (namespace_identifier)
                  (template_type
                    (type_identifier)
                    (template_argument_list
                      (type_descriptor
                        (template_type
                          (type_identifier)
                          (template_argument_list
                            (type_descriptor
                              (type_identifier))))))))
                (initializer_list))))
          (declaration
            (dependent_type
              (qualified_identifier
                (namespace_identifier)
                (qualified_identifier
                  (dependent_name
                    (template_type
                      (type_identifier)
                      (template_argument_list
                        (type_descriptor
                          (template_type
                            (type_identifier)
                            (template_argument_list
                              (type_descriptor
                                (type_identifier))))))))
                  (type_identifier))))
            (identifier))
          (declaration
            (dependent_type
              (qualified_identifier
                (namespace_identifier)
                (qualified_identifier
                  (dependent_name
                    (template_type
                      (type_identifier)
                      (template_argument_list
                        (type_descriptor
                          (template_type
                            (type_identifier)
                            (template_argument_list
                              (type_descriptor
                                (type_identifier))))))))
                  (qualified_identifier
                    (dependent_name
                      (template_type
                        (type_identifier)
                        (template_argument_list
                          (type_descriptor
                            (type_identifier)))))
                    (type_identifier)))))
            (identifier))))
      (field_declaration
        (dependent_type
          (qualified_identifier
            (namespace_identifier)
            (qualified_identifier
              (dependent_name
                (template_type
                  (type_identifier)
                  (template_argument_list
                    (type_descriptor
                      (primitive_type)))))
              (type_identifier))))
        (field_identifier))
      (field_declaration
        (dependent_type
          (qualified_identifier
            (namespace_identifier)
            (qualified_identifier
              (dependent_name
                (template_type
                  (type_identifier)
                  (template_argument_list
                    (type_descriptor
                      (primitive_type)))))
              (qualified_identifier
                (namespace_identifier)
                (dependent_name
                  (template_type
                    (type_identifier)
                    (template_argument_list
                      (type_descriptor
                        (type_identifier)))))))))
        (field_identifier)))))

================================================================================
Comma expressions at the start of blocks
================================================================================

int main() { a(), b(); }

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (expression_statement
        (comma_expression
          (call_expression
            (identifier)
            (argument_list))
          (call_expression
            (identifier)
            (argument_list)))))))

================================================================================
Nullptr
================================================================================

void *x = nullptr;

--------------------------------------------------------------------------------

(translation_unit
  (declaration
    (primitive_type)
    (init_declarator
      (pointer_declarator
        (identifier))
      (null))))

================================================================================
Raw string literals
================================================================================

const char *s1 = R"(
  This is a string. It ends with ')' and a quote.
)";

const char *s2 = R"FOO(
  This is a string. It ends with ')FOO' and a quote.
)FOO";

const char *s3 = uR"FOO(
  This is a string. It ends with ')FOO' and a quote.
)FOO";

const char *s4 = UR"FOO(
  This is a string. It ends with ')FOO' and a quote.
)FOO";

const char *s5 = u8R"FOO(
  This is a string. It ends with ')FOO' and a quote.
)FOO";

const char *s6 = LR"FOO(
  This is a string. It ends with ')FOO' and a quote.
)FOO";

--------------------------------------------------------------------------------

(translation_unit
  (declaration
    (type_qualifier)
    (primitive_type)
    (init_declarator
      (pointer_declarator
        (identifier))
      (raw_string_literal
        (raw_string_content))))
  (declaration
    (type_qualifier)
    (primitive_type)
    (init_declarator
      (pointer_declarator
        (identifier))
      (raw_string_literal
        (raw_string_delimiter)
        (raw_string_content)
        (raw_string_delimiter))))
  (declaration
    (type_qualifier)
    (primitive_type)
    (init_declarator
      (pointer_declarator
        (identifier))
      (raw_string_literal
        (raw_string_delimiter)
        (raw_string_content)
        (raw_string_delimiter))))
  (declaration
    (type_qualifier)
    (primitive_type)
    (init_declarator
      (pointer_declarator
        (identifier))
      (raw_string_literal
        (raw_string_delimiter)
        (raw_string_content)
        (raw_string_delimiter))))
  (declaration
    (type_qualifier)
    (primitive_type)
    (init_declarator
      (pointer_declarator
        (identifier))
      (raw_string_literal
        (raw_string_delimiter)
        (raw_string_content)
        (raw_string_delimiter))))
  (declaration
    (type_qualifier)
    (primitive_type)
    (init_declarator
      (pointer_declarator
        (identifier))
      (raw_string_literal
        (raw_string_delimiter)
        (raw_string_content)
        (raw_string_delimiter)))))

================================================================================
Template calls
================================================================================

int main() {
  // '<' and '>' as template argument list delimiters
  if (a<b && c>()) {}

  // '<' and '>' as binary operators
  if (a < b && c >= d) {}

  Q::template R<S>();
  this->template f<T>();
  foo.template f<U>();
}
--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (comment)
      (if_statement
        (condition_clause
          (call_expression
            (template_function
              (identifier)
              (template_argument_list
                (binary_expression
                  (identifier)
                  (identifier))))
            (argument_list)))
        (compound_statement))
      (comment)
      (if_statement
        (condition_clause
          (binary_expression
            (binary_expression
              (identifier)
              (identifier))
            (binary_expression
              (identifier)
              (identifier))))
        (compound_statement))
      (expression_statement
        (call_expression
          (qualified_identifier
            (namespace_identifier)
            (dependent_name
              (template_function
                (identifier)
                (template_argument_list
                  (type_descriptor
                    (type_identifier))))))
          (argument_list)))
      (expression_statement
        (call_expression
          (field_expression
            (this)
            (dependent_name
              (template_method
                (field_identifier)
                (template_argument_list
                  (type_descriptor
                    (type_identifier))))))
          (argument_list)))
      (expression_statement
        (call_expression
          (field_expression
            (identifier)
            (dependent_name
              (template_method
                (field_identifier)
                (template_argument_list
                  (type_descriptor
                    (type_identifier))))))
          (argument_list))))))

================================================================================
Parameter pack expansions
================================================================================

container<A,B,C...> t1;
container<C...,A,B> t2;

typedef Tuple<Pair<Args1, Args2>...> type;

f(&args...); // expands to f(&E1, &E2, &E3)
f(n, ++args...); // expands to f(n, ++E1, ++E2, ++E3);
f(++args..., n); // expands to f(++E1, ++E2, ++E3, n);
f(const_cast<const Args*>(&args)...); // f(const_cast<const E1*>(&X1), const_cast<const E2*>(&X2), const_cast<const E3*>(&X3))
f(h(args...) + args...); // expands to f(h(E1,E2,E3) + E1, h(E1,E2,E3) + E2, h(E1,E2,E3) + E3)

const int size = sizeof...(args) + 2;
int res[size] = {1,args...,2};
int dummy[sizeof...(Ts)] = { (std::cout << args, 0)... };

auto lm = [&, args...] { return g(args...); };

class X : public Mixins... {
public:
    X(const Mixins&... mixins) : Mixins(mixins)... { }
};

template <typename... Args>
void wrap(Args&&... args) {
    f(forward<Args>(args)...);
}

void f(T...) {}

--------------------------------------------------------------------------------

(translation_unit
  (declaration
    type: (template_type
      name: (type_identifier)
      arguments: (template_argument_list
        (type_descriptor
          type: (type_identifier))
        (type_descriptor
          type: (type_identifier))
        (parameter_pack_expansion
          pattern: (type_descriptor
            type: (type_identifier)))))
    declarator: (identifier))
  (declaration
    type: (template_type
      name: (type_identifier)
      arguments: (template_argument_list
        (parameter_pack_expansion
          pattern: (type_descriptor
            type: (type_identifier)))
        (type_descriptor
          type: (type_identifier))
        (type_descriptor
          type: (type_identifier))))
    declarator: (identifier))
  (type_definition
    type: (template_type
      name: (type_identifier)
      arguments: (template_argument_list
        (parameter_pack_expansion
          pattern: (type_descriptor
            type: (template_type
              name: (type_identifier)
              arguments: (template_argument_list
                (type_descriptor
                  type: (type_identifier))
                (type_descriptor
                  type: (type_identifier))))))))
    declarator: (type_identifier))
  (expression_statement
    (call_expression
      function: (identifier)
      arguments: (argument_list
        (parameter_pack_expansion
          pattern: (pointer_expression
            argument: (identifier))))))
  (comment)
  (expression_statement
    (call_expression
      function: (identifier)
      arguments: (argument_list
        (identifier)
        (parameter_pack_expansion
          pattern: (update_expression
            argument: (identifier))))))
  (comment)
  (expression_statement
    (call_expression
      function: (identifier)
      arguments: (argument_list
        (parameter_pack_expansion
          pattern: (update_expression
            argument: (identifier)))
        (identifier))))
  (comment)
  (expression_statement
    (call_expression
      function: (identifier)
      arguments: (argument_list
        (parameter_pack_expansion
          pattern: (call_expression
            function: (template_function
              name: (identifier)
              arguments: (template_argument_list
                (type_descriptor
                  (type_qualifier)
                  type: (type_identifier)
                  declarator: (abstract_pointer_declarator))))
            arguments: (argument_list
              (pointer_expression
                argument: (identifier))))))))
  (comment)
  (expression_statement
    (call_expression
      function: (identifier)
      arguments: (argument_list
        (parameter_pack_expansion
          pattern: (binary_expression
            left: (call_expression
              function: (identifier)
              arguments: (argument_list
                (parameter_pack_expansion
                  pattern: (identifier))))
            right: (identifier))))))
  (comment)
  (declaration
    (type_qualifier)
    type: (primitive_type)
    declarator: (init_declarator
      declarator: (identifier)
      value: (binary_expression
        left: (sizeof_expression
          value: (identifier))
        right: (number_literal))))
  (declaration
    type: (primitive_type)
    declarator: (init_declarator
      declarator: (array_declarator
        declarator: (identifier)
        size: (identifier))
      value: (initializer_list
        (number_literal)
        (parameter_pack_expansion
          pattern: (identifier))
        (number_literal))))
  (declaration
    type: (primitive_type)
    declarator: (init_declarator
      declarator: (array_declarator
        declarator: (identifier)
        size: (sizeof_expression
          value: (identifier)))
      value: (initializer_list
        (parameter_pack_expansion
          pattern: (parenthesized_expression
            (comma_expression
              left: (binary_expression
                left: (qualified_identifier
                  scope: (namespace_identifier)
                  name: (identifier))
                right: (identifier))
              right: (number_literal)))))))
  (declaration
    type: (placeholder_type_specifier
      (auto))
    declarator: (init_declarator
      declarator: (identifier)
      value: (lambda_expression
        captures: (lambda_capture_specifier
          (lambda_default_capture)
          (parameter_pack_expansion
            pattern: (identifier)))
        body: (compound_statement
          (return_statement
            (call_expression
              function: (identifier)
              arguments: (argument_list
                (parameter_pack_expansion
                  pattern: (identifier)))))))))
  (class_specifier
    name: (type_identifier)
    (base_class_clause
      (access_specifier)
      (type_identifier))
    body: (field_declaration_list
      (access_specifier)
      (function_definition
        declarator: (function_declarator
          declarator: (identifier)
          parameters: (parameter_list
            (variadic_parameter_declaration
              (type_qualifier)
              type: (type_identifier)
              declarator: (reference_declarator
                (variadic_declarator
                  (identifier))))))
        (field_initializer_list
          (field_initializer
            (field_identifier)
            (argument_list
              (identifier))))
        body: (compound_statement))))
  (template_declaration
    parameters: (template_parameter_list
      (variadic_type_parameter_declaration
        (type_identifier)))
    (function_definition
      type: (primitive_type)
      declarator: (function_declarator
        declarator: (identifier)
        parameters: (parameter_list
          (variadic_parameter_declaration
            type: (type_identifier)
            declarator: (reference_declarator
              (variadic_declarator
                (identifier))))))
      body: (compound_statement
        (expression_statement
          (call_expression
            function: (identifier)
            arguments: (argument_list
              (parameter_pack_expansion
                pattern: (call_expression
                  function: (template_function
                    name: (identifier)
                    arguments: (template_argument_list
                      (type_descriptor
                        type: (type_identifier))))
                  arguments: (argument_list
                    (identifier))))))))))
  (function_definition
    type: (primitive_type)
    declarator: (function_declarator
      declarator: (identifier)
      parameters: (parameter_list
        (variadic_parameter_declaration
          type: (type_identifier)
          declarator: (variadic_declarator))))
    body: (compound_statement)))

================================================================================
Concatenated string literals
================================================================================

"a" "b" "c";
R"(a)" R"(b)" R"(c)";
"a" R"(b)" L"c" R"FOO(d)FOO";
--------------------------------------------------------------------------------

(translation_unit
  (expression_statement
    (concatenated_string
      (string_literal
        (string_content))
      (string_literal
        (string_content))
      (string_literal
        (string_content))))
  (expression_statement
    (concatenated_string
      (raw_string_literal
        (raw_string_content))
      (raw_string_literal
        (raw_string_content))
      (raw_string_literal
        (raw_string_content))))
  (expression_statement
    (concatenated_string
      (string_literal
        (string_content))
      (raw_string_literal
        (raw_string_content))
      (string_literal
        (string_content))
      (raw_string_literal
        (raw_string_delimiter)
        (raw_string_content)
        (raw_string_delimiter)))))

================================================================================
User-defined literals
================================================================================

1.2_km;
"foo" "bar"_baz;
--------------------------------------------------------------------------------

(translation_unit
  (expression_statement
    (user_defined_literal
      (number_literal)
      (literal_suffix)))
  (expression_statement
    (user_defined_literal
      (concatenated_string
        (string_literal
          (string_content))
        (string_literal
          (string_content)))
      (literal_suffix))))

================================================================================
Primitive types ctor
================================================================================

x = int(1);
x = new int(1);
x = (int(1) + float(2));

--------------------------------------------------------------------------------

(translation_unit
  (expression_statement
    (assignment_expression
      (identifier)
      (call_expression
        (primitive_type)
        (argument_list
          (number_literal)))))
  (expression_statement
    (assignment_expression
      (identifier)
      (new_expression
        (primitive_type)
        (argument_list
          (number_literal)))))
  (expression_statement
    (assignment_expression
      (identifier)
      (parenthesized_expression
        (binary_expression
          (call_expression
            (primitive_type)
            (argument_list
              (number_literal)))
          (call_expression
            (primitive_type)
            (argument_list
              (number_literal))))))))

================================================================================
Array assignment expression
================================================================================

array_[i] = s[i];
array_[{i}] = s[{1,2,3}];

--------------------------------------------------------------------------------

(translation_unit
  (expression_statement
    (assignment_expression
      (subscript_expression
        (identifier)
        (subscript_argument_list
          (identifier)))
      (subscript_expression
        (identifier)
        (subscript_argument_list
          (identifier)))))
  (expression_statement
    (assignment_expression
      (subscript_expression
        (identifier)
        (subscript_argument_list
          (initializer_list
            (identifier))))
      (subscript_expression
        (identifier)
        (subscript_argument_list
          (initializer_list
            (number_literal)
            (number_literal)
            (number_literal)))))))

================================================================================
Coroutines
================================================================================

co_await fn();
co_await var;

--------------------------------------------------------------------------------

(translation_unit
  (expression_statement
    (co_await_expression
      (call_expression
        (identifier)
        (argument_list))))
  (expression_statement
    (co_await_expression
      (identifier))))

================================================================================
Three-way comparison
================================================================================

auto x = a <=> b;

bool y = 0 > a <=> b;

--------------------------------------------------------------------------------

(translation_unit
  (declaration
    (placeholder_type_specifier
      (auto))
    (init_declarator
      (identifier)
      (binary_expression
        (identifier)
        (identifier))))
  (declaration
    (primitive_type)
    (init_declarator
      (identifier)
      (binary_expression
        (number_literal)
        (binary_expression
          (identifier)
          (identifier))))))

================================================================================
Fold Expressions
================================================================================

bool t  = (... + IndexOf<T>);
bool t2 = (IndexOf<T> + ...);
bool t3 = (1 + ... + IndexOf<T>);
bool t3 = (IndexOf<T> + ... + 1);

--------------------------------------------------------------------------------

(translation_unit
  (declaration
    (primitive_type)
    (init_declarator
      (identifier)
      (fold_expression
        (template_function
          (identifier)
          (template_argument_list
            (type_descriptor
              (type_identifier)))))))
  (declaration
    (primitive_type)
    (init_declarator
      (identifier)
      (fold_expression
        (template_function
          (identifier)
          (template_argument_list
            (type_descriptor
              (type_identifier)))))))
  (declaration
    (primitive_type)
    (init_declarator
      (identifier)
      (fold_expression
        (number_literal)
        (template_function
          (identifier)
          (template_argument_list
            (type_descriptor
              (type_identifier)))))))
  (declaration
    (primitive_type)
    (init_declarator
      (identifier)
      (fold_expression
        (template_function
          (identifier)
          (template_argument_list
            (type_descriptor
              (type_identifier))))
        (number_literal)))))

================================================================================
Alternative tokens (digraphs)
================================================================================

if (not marked and (x < left or right < x)) {}

operator not_eq(int) { return true; }

foo and_eq bar();

--------------------------------------------------------------------------------

(translation_unit
  (if_statement
    (condition_clause
      (binary_expression
        (unary_expression
          (identifier))
        (parenthesized_expression
          (binary_expression
            (binary_expression
              (identifier)
              (identifier))
            (binary_expression
              (identifier)
              (identifier))))))
    (compound_statement))
  (function_definition
    (function_declarator
      (operator_name)
      (parameter_list
        (parameter_declaration
          (primitive_type))))
    (compound_statement
      (return_statement
        (true))))
  (expression_statement
    (assignment_expression
      (identifier)
      (call_expression
        (identifier)
        (argument_list)))))

================================================================================
Subscript expression
================================================================================

auto x = a[1, 2, 3];

--------------------------------------------------------------------------------

(translation_unit
  (declaration
    (placeholder_type_specifier
      (auto))
    (init_declarator
      (identifier)
      (subscript_expression
        (identifier)
        (subscript_argument_list
          (number_literal)
          (number_literal)
          (number_literal))))))

================================================================================
Dependent operator templates
================================================================================

x.template operator()<int>();

--------------------------------------------------------------------------------

(translation_unit
  (expression_statement
    (call_expression
      (field_expression
        (identifier)
        (dependent_name
          (template_method
            (operator_name)
            (template_argument_list
              (type_descriptor
                (primitive_type))))))
      (argument_list))))

================================================================================
Numeric literals
================================================================================

void f() {
  0123'4567;
  0b1001'0110;
  0B10;
  0xabcd'1234;
  0XABCD;
  1'234;
  -123;
  123l;
  123u;
  123ULL;
  123z;
  123UZ;

  1.0;
  -1.0;
  1.f;
  .1f;
  1.0l;
  1.0f16;
  1.0bf16;
  1.e1;
  1.0e1;
  0xa.bp1;
  0xap-1;
  0x.ap-1;
}
--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (expression_statement
        (number_literal))
      (expression_statement
        (number_literal))
      (expression_statement
        (number_literal))
      (expression_statement
        (number_literal))
      (expression_statement
        (number_literal))
      (expression_statement
        (number_literal))
      (expression_statement
        (number_literal))
      (expression_statement
        (number_literal))
      (expression_statement
        (number_literal))
      (expression_statement
        (number_literal))
      (expression_statement
        (number_literal))
      (expression_statement
        (number_literal))
      (expression_statement
        (number_literal))
      (expression_statement
        (number_literal))
      (expression_statement
        (number_literal))
      (expression_statement
        (number_literal))
      (expression_statement
        (number_literal))
      (expression_statement
        (number_literal))
      (expression_statement
        (number_literal))
      (expression_statement
        (number_literal))
      (expression_statement
        (number_literal))
      (expression_statement
        (number_literal))
      (expression_statement
        (number_literal))
      (expression_statement
        (number_literal)))))

================================================================================
While with assignment expression
================================================================================

while ((a = b)) {}

--------------------------------------------------------------------------------

(translation_unit
  (while_statement
    (condition_clause
      (parenthesized_expression
        (assignment_expression
          (identifier)
          (identifier))))
    (compound_statement)))

================================================================================
Parenthesized Expressions that are not Fold Expressions
================================================================================

int main() {
  if ((a = a + 1)) {
    (a += 1) %= 2;
  }
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (if_statement
        (condition_clause
          (parenthesized_expression
            (assignment_expression
              (identifier)
              (binary_expression
                (identifier)
                (number_literal)))))
        (compound_statement
          (expression_statement
            (assignment_expression
              (parenthesized_expression
                (assignment_expression
                  (identifier)
                  (number_literal)))
              (number_literal))))))))

================================================================================
Complex fold expression
================================================================================

template <typename... Args> void negateValues(Args... args) {
  ((std::cout << !args << " "), ...);
}

--------------------------------------------------------------------------------

(translation_unit
  (template_declaration
    (template_parameter_list
      (variadic_type_parameter_declaration
        (type_identifier)))
    (function_definition
      (primitive_type)
      (function_declarator
        (identifier)
        (parameter_list
          (variadic_parameter_declaration
            (type_identifier)
            (variadic_declarator
              (identifier)))))
      (compound_statement
        (expression_statement
          (fold_expression
            (parenthesized_expression
              (binary_expression
                (binary_expression
                  (qualified_identifier
                    (namespace_identifier)
                    (identifier))
                  (unary_expression
                    (identifier)))
                (string_literal
                  (string_content))))))))))



================================================
FILE: test/corpus/microsoft.txt
================================================
================================
declaration specs
================================

struct __declspec(dllexport) s2
{
};

union __declspec(noinline) u2 {
};

class __declspec(uuid) u2 {
};

int __cdecl f2();
---

(translation_unit
  (struct_specifier
    (ms_declspec_modifier
      (identifier))
    name: (type_identifier)
    body: (field_declaration_list))
  (union_specifier
    (ms_declspec_modifier
      (identifier))
    name: (type_identifier)
    body: (field_declaration_list))
  (class_specifier
    (ms_declspec_modifier
      (identifier))
    name: (type_identifier)
    body: (field_declaration_list))
  (declaration
    type: (primitive_type)
    declarator: (ms_call_modifier)
    declarator: (function_declarator
      declarator: (identifier)
      parameters: (parameter_list))))



================================================
FILE: test/corpus/modules.txt
================================================
================================================================================
Module Definition
================================================================================

module mod;
--------------------------------------------------------------------------------
(translation_unit
     (module_declaration
       (module_name
         (identifier))))

================================================================================
Module Definition with Export
================================================================================

export module mod;
--------------------------------------------------------------------------------
(translation_unit
     (module_declaration
       (module_name
         (identifier))))

================================================================================
Module Definition with Export and Partition
================================================================================

export module mod:mod;
--------------------------------------------------------------------------------

(translation_unit
     (module_declaration
       (module_name
         (identifier))
      (module_partition
       (module_name
         (identifier)))))

================================================================================
Module Definition with Export, Partition and Attribute
================================================================================

export module mod:mod [[attribute]];
--------------------------------------------------------------------------------

(translation_unit
  (module_declaration
    name: (module_name
      (identifier))
    partition: (module_partition
      (module_name
        (identifier)))
    (attribute_declaration
      (attribute
        name: (identifier)))))

================================================================================
import Declaration
================================================================================

import mod;
--------------------------------------------------------------------------------

(translation_unit
  (import_declaration
    name: (module_name
      (identifier))))

================================================================================
import Declaration with export
================================================================================

export import mod;
--------------------------------------------------------------------------------

(translation_unit
  (import_declaration
    name: (module_name
      (identifier))))

================================================================================
import Declaration partition with export
================================================================================

export import :mod;
--------------------------------------------------------------------------------

(translation_unit
  (import_declaration
    partition: (module_partition
      (module_name
        (identifier)))))

================================================================================
import Declaration headerunit with export
================================================================================

export import <iostream>;
--------------------------------------------------------------------------------

(translation_unit
  (import_declaration
    header: (system_lib_string)))

================================================================================
global module fragment
================================================================================

module;
--------------------------------------------------------------------------------

(translation_unit
  (global_module_fragment_declaration))

================================================================================
private module fragment
================================================================================

module :private;
--------------------------------------------------------------------------------

(translation_unit
  (private_module_fragment_declaration))


================================================================================
export declaration
================================================================================

export module A;

export char const* hello() { return "hello"; }

char const* world() { return "world"; }

export {
  int one() { return 1; }
  int zero() { return 0; }
}

export namespace hi {
char const* english() { return "Hi!"; }
char const* french() { return "Salut!"; }
}
--------------------------------------------------------------------------------

(translation_unit
  (module_declaration
    name: (module_name
      (identifier)))
  (export_declaration
    (function_definition
      type: (primitive_type)
      (type_qualifier)
      declarator: (pointer_declarator
        declarator: (function_declarator
          declarator: (identifier)
          parameters: (parameter_list)))
      body: (compound_statement
        (return_statement
          (string_literal
            (string_content))))))
  (function_definition
    type: (primitive_type)
    (type_qualifier)
    declarator: (pointer_declarator
      declarator: (function_declarator
        declarator: (identifier)
        parameters: (parameter_list)))
    body: (compound_statement
      (return_statement
        (string_literal
          (string_content)))))
  (export_declaration
    (function_definition
      type: (primitive_type)
      declarator: (function_declarator
        declarator: (identifier)
        parameters: (parameter_list))
      body: (compound_statement
        (return_statement
          (number_literal))))
    (function_definition
      type: (primitive_type)
      declarator: (function_declarator
        declarator: (identifier)
        parameters: (parameter_list))
      body: (compound_statement
        (return_statement
          (number_literal)))))
  (export_declaration
    (namespace_definition
      name: (namespace_identifier)
      body: (declaration_list
        (function_definition
          type: (primitive_type)
          (type_qualifier)
          declarator: (pointer_declarator
            declarator: (function_declarator
              declarator: (identifier)
              parameters: (parameter_list)))
          body: (compound_statement
            (return_statement
              (string_literal
                (string_content)))))
        (function_definition
          type: (primitive_type)
          (type_qualifier)
          declarator: (pointer_declarator
            declarator: (function_declarator
              declarator: (identifier)
              parameters: (parameter_list)))
          body: (compound_statement
            (return_statement
              (string_literal
                (string_content)))))))))



================================================
FILE: test/corpus/statements.txt
================================================
================================================================================
Returning braced initializer lists
================================================================================

T main() {
  return {0, 5};
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (type_identifier)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (return_statement
        (initializer_list
          (number_literal)
          (number_literal))))))

================================================================================
Range-based for loops
================================================================================

T main() {
  for (Value &value : values) {
    cout << value;
  }

  for (const auto &value : values) {
    cout << value;
  }

  for (const auto &value : {1, 2, 3}) {
    cout << value;
  }

  for (auto n = v.size(); auto i : v) {
    cout << --n + i << ' ';
  }

  for (using elem_t = T::value_type; elem_t i : v) {
    cout << --n + i << ' ';
  }

  for (int x; int v : {1}) {}
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    type: (type_identifier)
    declarator: (function_declarator
      declarator: (identifier)
      parameters: (parameter_list))
    body: (compound_statement
      (for_range_loop
        type: (type_identifier)
        declarator: (reference_declarator
          (identifier))
        right: (identifier)
        body: (compound_statement
          (expression_statement
            (binary_expression
              left: (identifier)
              right: (identifier)))))
      (for_range_loop
        (type_qualifier)
        type: (placeholder_type_specifier
          (auto))
        declarator: (reference_declarator
          (identifier))
        right: (identifier)
        body: (compound_statement
          (expression_statement
            (binary_expression
              left: (identifier)
              right: (identifier)))))
      (for_range_loop
        (type_qualifier)
        type: (placeholder_type_specifier
          (auto))
        declarator: (reference_declarator
          (identifier))
        right: (initializer_list
          (number_literal)
          (number_literal)
          (number_literal))
        body: (compound_statement
          (expression_statement
            (binary_expression
              left: (identifier)
              right: (identifier)))))
      (for_range_loop
        initializer: (init_statement
          (declaration
            type: (placeholder_type_specifier
              (auto))
            declarator: (init_declarator
              declarator: (identifier)
              value: (call_expression
                function: (field_expression
                  argument: (identifier)
                  field: (field_identifier))
                arguments: (argument_list)))))
        type: (placeholder_type_specifier
          (auto))
        declarator: (identifier)
        right: (identifier)
        body: (compound_statement
          (expression_statement
            (binary_expression
              left: (binary_expression
                left: (identifier)
                right: (binary_expression
                  left: (update_expression
                    argument: (identifier))
                  right: (identifier)))
              right: (char_literal
                (character))))))
      (for_range_loop
        initializer: (init_statement
          (alias_declaration
            name: (type_identifier)
            type: (type_descriptor
              type: (qualified_identifier
                scope: (namespace_identifier)
                name: (type_identifier)))))
        type: (type_identifier)
        declarator: (identifier)
        right: (identifier)
        body: (compound_statement
          (expression_statement
            (binary_expression
              left: (binary_expression
                left: (identifier)
                right: (binary_expression
                  left: (update_expression
                    argument: (identifier))
                  right: (identifier)))
              right: (char_literal
                (character))))))
      (for_range_loop
        initializer: (init_statement
          (declaration
            type: (primitive_type)
            declarator: (identifier)))
        type: (primitive_type)
        declarator: (identifier)
        right: (initializer_list
          (number_literal))
        body: (compound_statement)))))

================================================================================
Constexpr if statements
================================================================================

T f() {
  if constexpr (std::is_pointer_v<T>)
    return *t;
  else
    return t;
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    type: (type_identifier)
    declarator: (function_declarator
      declarator: (identifier)
      parameters: (parameter_list))
    body: (compound_statement
      (if_statement
        condition: (condition_clause
          value: (qualified_identifier
            scope: (namespace_identifier)
            name: (template_function
              name: (identifier)
              arguments: (template_argument_list
                (type_descriptor
                  type: (type_identifier))))))
        consequence: (return_statement
          (pointer_expression
            argument: (identifier)))
        alternative: (else_clause
          (return_statement
            (identifier)))))))

================================================================================
If statements with declarations
================================================================================

void f() {
  if (const int x = foo()) { }
  if (const int x { foo() }) { }
  if (const int x = foo(); x != 0) { }
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    type: (primitive_type)
    declarator: (function_declarator
      declarator: (identifier)
      parameters: (parameter_list))
    body: (compound_statement
      (if_statement
        condition: (condition_clause
          value: (declaration
            (type_qualifier)
            type: (primitive_type)
            declarator: (identifier)
            value: (call_expression
              function: (identifier)
              arguments: (argument_list))))
        consequence: (compound_statement))
      (if_statement
        condition: (condition_clause
          value: (declaration
            (type_qualifier)
            type: (primitive_type)
            declarator: (identifier)
            value: (initializer_list
              (call_expression
                function: (identifier)
                arguments: (argument_list)))))
        consequence: (compound_statement))
      (if_statement
        condition: (condition_clause
          initializer: (init_statement
            (declaration
              (type_qualifier)
              type: (primitive_type)
              declarator: (init_declarator
                declarator: (identifier)
                value: (call_expression
                  function: (identifier)
                  arguments: (argument_list)))))
          value: (binary_expression
            left: (identifier)
            right: (number_literal)))
        consequence: (compound_statement)))))

================================================================================
Try/catch statements
================================================================================

void main() {
  try {
      f();
  } catch (const std::overflow_error) {
      // f() throws std::overflow_error (same type rule)
  } catch (const exception &e) {
      // f() throws std::logic_error (base class rule)
  } catch (...) {
      // f() throws std::string or int or any other unrelated type
  }
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (try_statement
        (compound_statement
          (expression_statement
            (call_expression
              (identifier)
              (argument_list))))
        (catch_clause
          (parameter_list
            (parameter_declaration
              (type_qualifier)
              (qualified_identifier
                (namespace_identifier)
                (type_identifier))))
          (compound_statement
            (comment)))
        (catch_clause
          (parameter_list
            (parameter_declaration
              (type_qualifier)
              (type_identifier)
              (reference_declarator
                (identifier))))
          (compound_statement
            (comment)))
        (catch_clause
          (parameter_list)
          (compound_statement
            (comment)))))))

================================================================================
Throw statements
================================================================================

void main() {
     throw e;
     throw x + 1;
     throw "exception";
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (throw_statement
        (identifier))
      (throw_statement
        (binary_expression
          (identifier)
          (number_literal)))
      (throw_statement
        (string_literal
          (string_content))))))

================================================================================
Noexcept specifier
================================================================================

void foo() noexcept;
void foo() noexcept(true);
template<class T> T foo() noexcept(sizeof(T) < 4);

--------------------------------------------------------------------------------

(translation_unit
  (declaration
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list)
      (noexcept)))
  (declaration
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list)
      (noexcept
        (true))))
  (template_declaration
    (template_parameter_list
      (type_parameter_declaration
        (type_identifier)))
    (declaration
      (type_identifier)
      (function_declarator
        (identifier)
        (parameter_list)
        (noexcept
          (binary_expression
            (sizeof_expression
              (parenthesized_expression
                (identifier)))
            (number_literal)))))))

================================================================================
Throw specifier
================================================================================

void foo() throw();
void foo() throw(int);
void foo() throw(std::string, char *);
void foo() throw(float) { }

--------------------------------------------------------------------------------

(translation_unit
  (declaration
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list)
      (throw_specifier)))
  (declaration
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list)
      (throw_specifier
        (type_descriptor
          (primitive_type)))))
  (declaration
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list)
      (throw_specifier
        (type_descriptor
          (qualified_identifier
            (namespace_identifier)
            (type_identifier)))
        (type_descriptor
          (primitive_type)
          (abstract_pointer_declarator)))))
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list)
      (throw_specifier
        (type_descriptor
          (primitive_type))))
    (compound_statement)))

================================================================================
Assignment
================================================================================

a::b::c = 1;

--------------------------------------------------------------------------------

(translation_unit
  (expression_statement
    (assignment_expression
      (qualified_identifier
        (namespace_identifier)
        (qualified_identifier
          (namespace_identifier)
          (identifier)))
      (number_literal))))

================================================================================
Attributes
================================================================================

void f() {
  [[a]] switch (b) {
   [[c]] case 1: {}
  }
  [[a]] while (true) {}
  [[a]] if (true) {}
  [[a]] for (auto x : y) {}
  [[a]] for (;;) {}
  [[a]] return;
  [[a]] a;
  [[a]];
  [[a]] label: {}
  [[a]] goto label;
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (attributed_statement
        (attribute_declaration
          (attribute
            (identifier)))
        (switch_statement
          (condition_clause
            (identifier))
          (compound_statement
            (attributed_statement
              (attribute_declaration
                (attribute
                  (identifier)))
              (case_statement
                (number_literal)
                (compound_statement))))))
      (attributed_statement
        (attribute_declaration
          (attribute
            (identifier)))
        (while_statement
          (condition_clause
            (true))
          (compound_statement)))
      (attributed_statement
        (attribute_declaration
          (attribute
            (identifier)))
        (if_statement
          (condition_clause
            (true))
          (compound_statement)))
      (attributed_statement
        (attribute_declaration
          (attribute
            (identifier)))
        (for_range_loop
          (placeholder_type_specifier
            (auto))
          (identifier)
          (identifier)
          (compound_statement)))
      (attributed_statement
        (attribute_declaration
          (attribute
            (identifier)))
        (for_statement
          (compound_statement)))
      (attributed_statement
        (attribute_declaration
          (attribute
            (identifier)))
        (return_statement))
      (attributed_statement
        (attribute_declaration
          (attribute
            (identifier)))
        (expression_statement
          (identifier)))
      (attributed_statement
        (attribute_declaration
          (attribute
            (identifier)))
        (expression_statement))
      (attributed_statement
        (attribute_declaration
          (attribute
            (identifier)))
        (labeled_statement
          (statement_identifier)
          (compound_statement)))
      (attributed_statement
        (attribute_declaration
          (attribute
            (identifier)))
        (goto_statement
          (statement_identifier))))))

================================================================================
Coroutines
================================================================================

co_return 1;
co_return;
co_yield 1;

--------------------------------------------------------------------------------

(translation_unit
  (co_return_statement
    (number_literal))
  (co_return_statement)
  (co_yield_statement
    (number_literal)))

================================================================================
Switch statements
================================================================================

void foo(int a) {
  switch (a) {
    case 1:
      for (auto i : vec) {}
    case 2:
      try {
        // do something
      } catch(...) {}
      throw 1;
    case 3:
      co_return;
    default:
      co_yield a;
  }
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list
        (parameter_declaration
          (primitive_type)
          (identifier))))
    (compound_statement
      (switch_statement
        (condition_clause
          (identifier))
        (compound_statement
          (case_statement
            (number_literal)
            (for_range_loop
              (placeholder_type_specifier
                (auto))
              (identifier)
              (identifier)
              (compound_statement)))
          (case_statement
            (number_literal)
            (try_statement
              (compound_statement
                (comment))
              (catch_clause
                (parameter_list)
                (compound_statement)))
            (throw_statement
              (number_literal)))
          (case_statement
            (number_literal)
            (co_return_statement))
          (case_statement
            (co_yield_statement
              (identifier))))))))



================================================
FILE: test/corpus/types.txt
================================================
==========================================
The auto type
==========================================

void foo() {
  auto x = 1;
}

---

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator (identifier) (parameter_list))
    (compound_statement
      (declaration (placeholder_type_specifier (auto)) (init_declarator (identifier) (number_literal))))))

==========================================
Namespaced types
==========================================

std::string my_string;
std::vector<int>::size_typ my_string;

---

(translation_unit
  (declaration
    (qualified_identifier (namespace_identifier) (type_identifier))
    (identifier))
  (declaration
    (qualified_identifier
      (namespace_identifier)
      (qualified_identifier
        (template_type
          (type_identifier)
          (template_argument_list (type_descriptor (primitive_type))))
        (type_identifier)))
    (identifier)))

==========================================
Dependent type names
==========================================

template<typename T>
struct X : B<T>
{
    typename T::A* pa;
};

---

(translation_unit
  (template_declaration
    (template_parameter_list (type_parameter_declaration (type_identifier)))
    (struct_specifier
      (type_identifier)
      (base_class_clause
        (template_type (type_identifier) (template_argument_list (type_descriptor (type_identifier)))))
      (field_declaration_list
        (field_declaration
          (dependent_type (qualified_identifier (namespace_identifier) (type_identifier)))
          (pointer_declarator (field_identifier)))))))

==========================================
Template types with empty argument lists
==========================================

use_future_t<> use_future;

---

(translation_unit
  (declaration (template_type (type_identifier) (template_argument_list)) (identifier)))

================================
Function types as template arguments
================================

typedef std::function<T(int)> MyFunc;
typedef std::function<void(int)> b;

---

(translation_unit
  (type_definition
    (qualified_identifier
      (namespace_identifier)
      (template_type
        (type_identifier)
        (template_argument_list
          (type_descriptor
            (type_identifier)
            (abstract_function_declarator (parameter_list
              (parameter_declaration (primitive_type))))))))
    (type_identifier))
  (type_definition
    (qualified_identifier
      (namespace_identifier)
      (template_type
        (type_identifier)
        (template_argument_list
          (type_descriptor
            (primitive_type)
            (abstract_function_declarator (parameter_list
              (parameter_declaration (primitive_type))))))))
    (type_identifier)))

====================================================
Decltype
====================================================

decltype(A) x;
decltype(B) foo(void x, decltype(C) y);
template<typename T, typename U> auto add(T t, U u) -> decltype(t + u);
array<decltype(foo)::type, 5> arr;

---

(translation_unit
  (declaration
    (decltype (identifier))
    (identifier))
  (declaration
    (decltype (identifier))
    (function_declarator (identifier)
      (parameter_list
        (parameter_declaration (primitive_type) (identifier))
        (parameter_declaration (decltype (identifier)) (identifier)))))
  (template_declaration
    (template_parameter_list
      (type_parameter_declaration (type_identifier)) (type_parameter_declaration (type_identifier)))
    (declaration
      (placeholder_type_specifier (auto))
      (function_declarator
        (identifier)
        (parameter_list
          (parameter_declaration (type_identifier) (identifier))
          (parameter_declaration (type_identifier) (identifier)))
        (trailing_return_type
          (type_descriptor
            (decltype (binary_expression (identifier) (identifier))))))))
  (declaration
    (template_type
      (type_identifier)
      (template_argument_list
        (type_descriptor
          (qualified_identifier
            (decltype (identifier))
            (type_identifier)))
        (number_literal)))
    (identifier)))

====================================================
Trailing return type
====================================================

auto a::foo() const -> const A<B>& {}
auto b::foo() const -> A<B> const& {}

---

(translation_unit
  (function_definition
    (placeholder_type_specifier (auto))
    (function_declarator
      (qualified_identifier (namespace_identifier) (identifier))
      (parameter_list)
      (type_qualifier)
      (trailing_return_type
        (type_descriptor
          (type_qualifier)
          (template_type (type_identifier) (template_argument_list (type_descriptor (type_identifier))))
          (abstract_reference_declarator))))
      (compound_statement))
  (function_definition
    (placeholder_type_specifier (auto))
    (function_declarator
      (qualified_identifier (namespace_identifier) (identifier))
      (parameter_list)
      (type_qualifier)
      (trailing_return_type
        (type_descriptor
          (template_type (type_identifier) (template_argument_list (type_descriptor (type_identifier))))
          (type_qualifier)
          (abstract_reference_declarator))))
    (compound_statement))
)



================================================
FILE: test/corpus/c/ambiguities.txt
================================================
================================================================================
pointer declarations vs expressions
================================================================================

TSLanguage *(*lang_parser)(void);

char (*ptr_to_array)[];

int main() {
  // declare a function pointer
  T1 * b(T2 a);

  // evaluate expressions
  c * d(5);
  e(f * g);
}

--------------------------------------------------------------------------------

(translation_unit
  (declaration
    (type_identifier)
    (pointer_declarator
      (function_declarator
        (parenthesized_declarator
          (pointer_declarator
            (identifier)))
        (parameter_list
          (parameter_declaration
            (primitive_type))))))
  (expression_statement
    (subscript_expression
      (call_expression
        (primitive_type)
        (argument_list
          (pointer_expression
            (identifier))))
      (subscript_argument_list)))
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (comment)
      (declaration
        (type_identifier)
        (pointer_declarator
          (function_declarator
            (identifier)
            (parameter_list
              (parameter_declaration
                (type_identifier)
                (identifier))))))
      (comment)
      (expression_statement
        (binary_expression
          (identifier)
          (call_expression
            (identifier)
            (argument_list
              (number_literal)))))
      (expression_statement
        (call_expression
          (identifier)
          (argument_list
            (binary_expression
              (identifier)
              (identifier))))))))

================================================================================
casts vs multiplications
================================================================================

/*
 * ambiguities
 */

int main() {
  // cast
  a((B *)c);

  // parenthesized product
  d((e * f));
}

--------------------------------------------------------------------------------

(translation_unit
  (comment)
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (comment)
      (expression_statement
        (call_expression
          (identifier)
          (argument_list
            (cast_expression
              (type_descriptor
                (type_identifier)
                (abstract_pointer_declarator))
              (identifier)))))
      (comment)
      (expression_statement
        (call_expression
          (identifier)
          (argument_list
            (parenthesized_expression
              (binary_expression
                (identifier)
                (identifier)))))))))

================================================================================
function calls vs parenthesized declarators vs macro types
================================================================================

int main() {
  /*
   * Could be either:
   *   - function call
   *   - declaration w/ parenthesized declarator
   *   - declaration w/ macro type, no declarator
   */
  ABC(d);

  /*
   * Normal declaration
   */
  efg hij;
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (comment)
      (expression_statement
        (call_expression
          (identifier)
          (argument_list
            (identifier))))
      (comment)
      (declaration
        (type_identifier)
        (identifier)))))

================================================================================
Call expressions vs empty declarations w/ macros as types
================================================================================

int main() {
  int a = 1;
  b(a);
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (declaration
        (primitive_type)
        (init_declarator
          (identifier)
          (number_literal)))
      (expression_statement
        (call_expression
          (identifier)
          (argument_list
            (identifier)))))))

================================================================================
Comments after for loops with ambiguities
================================================================================

int main() {
  for (a *b = c; d; e) {
    aff;
  }

  // a-comment

  g;
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (for_statement
        (declaration
          (type_identifier)
          (init_declarator
            (pointer_declarator
              (identifier))
            (identifier)))
        (identifier)
        (identifier)
        (compound_statement
          (expression_statement
            (identifier))))
      (comment)
      (expression_statement
        (identifier)))))

================================================================================
Top-level macro invocations
================================================================================

DEFINE_SOMETHING(THING_A, "this is a thing a");
DEFINE_SOMETHING(THING_B, "this is a thing b", "thanks");

--------------------------------------------------------------------------------

(translation_unit
  (expression_statement
    (call_expression
      (identifier)
      (argument_list
        (identifier)
        (string_literal
          (string_content)))))
  (expression_statement
    (call_expression
      (identifier)
      (argument_list
        (identifier)
        (string_literal
          (string_content))
        (string_literal
          (string_content))))))



================================================
FILE: test/corpus/c/crlf.txt
================================================
============================================
Line comments with escaped CRLF line endings
============================================

// hello \
   this is still a comment
this_is_not a_comment;

---

(translation_unit
  (comment)
  (declaration (type_identifier) (identifier)))



================================================
FILE: test/corpus/c/declarations.txt
================================================
================================================================================
Struct declarations
================================================================================

struct s1;

struct s2 {
  int x;
  float y : 5;
};

struct s3 {
  int x : 1, y : 2;
};

--------------------------------------------------------------------------------

(translation_unit
  (struct_specifier
    name: (type_identifier))
  (struct_specifier
    name: (type_identifier)
    body: (field_declaration_list
      (field_declaration
        type: (primitive_type)
        declarator: (field_identifier))
      (field_declaration
        type: (primitive_type)
        declarator: (field_identifier)
        (bitfield_clause
          (number_literal)))))
  (struct_specifier
    name: (type_identifier)
    body: (field_declaration_list
      (field_declaration
        type: (primitive_type)
        declarator: (field_identifier)
        (bitfield_clause
          (number_literal))
        declarator: (field_identifier)
        (bitfield_clause
          (number_literal))))))

================================================================================
Union declarations
================================================================================

union u1;

union s2 {
  int x;
  float y;
};

--------------------------------------------------------------------------------

(translation_unit
  (union_specifier
    name: (type_identifier))
  (union_specifier
    name: (type_identifier)
    body: (field_declaration_list
      (field_declaration
        type: (primitive_type)
        declarator: (field_identifier))
      (field_declaration
        type: (primitive_type)
        declarator: (field_identifier)))))

================================================================================
Enum declarations
================================================================================

enum e1;

enum e2 {
  val1,
  val2 = 5,
  val3
};

enum e3 {
  val1,
};

enum e4: int {
  val1,
};

--------------------------------------------------------------------------------

(translation_unit
  (enum_specifier
    name: (type_identifier))
  (enum_specifier
    name: (type_identifier)
    body: (enumerator_list
      (enumerator
        name: (identifier))
      (enumerator
        name: (identifier)
        value: (number_literal))
      (enumerator
        name: (identifier))))
  (enum_specifier
    name: (type_identifier)
    body: (enumerator_list
      (enumerator
        name: (identifier))))
  (enum_specifier
    name: (type_identifier)
    base: (primitive_type)
    body: (enumerator_list
      (enumerator
        name: (identifier)))))

================================================================================
Struct declarations containing preprocessor directives
================================================================================

struct s {
  #define A 5
  int b[a];
  #undef A
};

--------------------------------------------------------------------------------

(translation_unit
  (struct_specifier
    (type_identifier)
    (field_declaration_list
      (preproc_def
        (identifier)
        (preproc_arg))
      (field_declaration
        (primitive_type)
        (array_declarator
          (field_identifier)
          (identifier)))
      (preproc_call
        (preproc_directive)
        (preproc_arg)))))

================================================================================
Primitive-typed variable declarations
================================================================================

unsigned short int a;
long int b, c = 5, d;
float d, e;
unsigned f;
short g, h;

--------------------------------------------------------------------------------

(translation_unit
  (declaration
    type: (sized_type_specifier
      type: (primitive_type))
    declarator: (identifier))
  (declaration
    type: (sized_type_specifier
      type: (primitive_type))
    declarator: (identifier)
    declarator: (init_declarator
      declarator: (identifier)
      value: (number_literal))
    declarator: (identifier))
  (declaration
    type: (primitive_type)
    declarator: (identifier)
    declarator: (identifier))
  (declaration
    type: (sized_type_specifier)
    declarator: (identifier))
  (declaration
    type: (sized_type_specifier)
    declarator: (identifier)
    declarator: (identifier)))

================================================================================
Variable storage classes
================================================================================

int a;
extern int b, c;
register int e;
static int f;
register uint64_t rd_ asm("x" "10");

--------------------------------------------------------------------------------

(translation_unit
  (declaration
    (primitive_type)
    (identifier))
  (declaration
    (storage_class_specifier)
    (primitive_type)
    (identifier)
    (identifier))
  (declaration
    (storage_class_specifier)
    (primitive_type)
    (identifier))
  (declaration
    (storage_class_specifier)
    (primitive_type)
    (identifier))
  (declaration
    (storage_class_specifier)
    (primitive_type)
    (identifier)
    (gnu_asm_expression
      (concatenated_string
        (string_literal
          (string_content))
        (string_literal
          (string_content))))))

================================================================================
Composite-typed variable declarations
================================================================================

struct b c;
union { int e; } f;
enum { g, h } i;

--------------------------------------------------------------------------------

(translation_unit
  (declaration
    type: (struct_specifier
      name: (type_identifier))
    declarator: (identifier))
  (declaration
    type: (union_specifier
      body: (field_declaration_list
        (field_declaration
          type: (primitive_type)
          declarator: (field_identifier))))
    declarator: (identifier))
  (declaration
    type: (enum_specifier
      body: (enumerator_list
        (enumerator
          name: (identifier))
        (enumerator
          name: (identifier))))
    declarator: (identifier)))

================================================================================
Pointer variable declarations
================================================================================

char *the_string;
const char **the_strings;
int const * const restrict x;

--------------------------------------------------------------------------------

(translation_unit
  (declaration
    type: (primitive_type)
    declarator: (pointer_declarator
      declarator: (identifier)))
  (declaration
    (type_qualifier)
    type: (primitive_type)
    declarator: (pointer_declarator
      declarator: (pointer_declarator
        declarator: (identifier))))
  (declaration
    type: (primitive_type)
    (type_qualifier)
    declarator: (pointer_declarator
      (type_qualifier)
      (type_qualifier)
      declarator: (identifier))))

================================================================================
Typedefs
================================================================================

typedef int my_int;

typedef struct {
  int x;
} *a;

typedef void my_callback(void *, size_t);

typedef struct A {
  int i;
} a, b;

typedef void const *voidpc;
typedef void volatile *voidpv;
typedef void const volatile *const voidpcv;

typedef unsigned long int;
typedef unsigned short ptrdiff_t;
typedef short charptr_t;
typedef unsigned nullptr_t;
typedef signed max_align_t;

typedef unsigned long ulong_t;
typedef long long_t;
typedef unsigned short ushort_t;
typedef short short_t;
typedef unsigned unsigned_t;
typedef signed signed_t;

typedef long long;
typedef short short;
typedef unsigned int uint;
typedef unsigned short ushort;
typedef unsigned unsigned short;
typedef signed signed short;
typedef signed signed unsigned;

typedef int register_t __attribute__((__mode__(__word__)));

__extension__ typedef long int greg_t;

__extension__ typedef struct {
    long long int quot;
    long long int rem;
} lldiv_t;

--------------------------------------------------------------------------------

(translation_unit
  (type_definition
    type: (primitive_type)
    declarator: (type_identifier))
  (type_definition
    type: (struct_specifier
      body: (field_declaration_list
        (field_declaration
          type: (primitive_type)
          declarator: (field_identifier))))
    declarator: (pointer_declarator
      declarator: (type_identifier)))
  (type_definition
    type: (primitive_type)
    declarator: (function_declarator
      declarator: (type_identifier)
      parameters: (parameter_list
        (parameter_declaration
          type: (primitive_type)
          declarator: (abstract_pointer_declarator))
        (parameter_declaration
          type: (primitive_type)))))
  (type_definition
    type: (struct_specifier
      name: (type_identifier)
      body: (field_declaration_list
        (field_declaration
          type: (primitive_type)
          declarator: (field_identifier))))
    declarator: (type_identifier)
    declarator: (type_identifier))
  (type_definition
    type: (primitive_type)
    (type_qualifier)
    declarator: (pointer_declarator
      declarator: (type_identifier)))
  (type_definition
    type: (primitive_type)
    (type_qualifier)
    declarator: (pointer_declarator
      declarator: (type_identifier)))
  (type_definition
    type: (primitive_type)
    (type_qualifier)
    (type_qualifier)
    declarator: (pointer_declarator
      (type_qualifier)
      declarator: (type_identifier)))
  (type_definition
    type: (sized_type_specifier)
    declarator: (primitive_type))
  (type_definition
    type: (sized_type_specifier)
    declarator: (primitive_type))
  (type_definition
    type: (sized_type_specifier)
    declarator: (primitive_type))
  (type_definition
    type: (sized_type_specifier)
    declarator: (primitive_type))
  (type_definition
    type: (sized_type_specifier)
    declarator: (primitive_type))
  (type_definition
    type: (sized_type_specifier)
    declarator: (type_identifier))
  (type_definition
    type: (sized_type_specifier)
    declarator: (type_identifier))
  (type_definition
    type: (sized_type_specifier)
    declarator: (type_identifier))
  (type_definition
    type: (sized_type_specifier)
    declarator: (type_identifier))
  (type_definition
    type: (sized_type_specifier)
    declarator: (type_identifier))
  (type_definition
    type: (sized_type_specifier)
    declarator: (type_identifier))
  (type_definition
    type: (sized_type_specifier)
    declarator: (primitive_type))
  (type_definition
    type: (sized_type_specifier)
    declarator: (primitive_type))
  (type_definition
    type: (sized_type_specifier
      type: (primitive_type))
    declarator: (type_identifier))
  (type_definition
    type: (sized_type_specifier)
    declarator: (type_identifier))
  (type_definition
    type: (sized_type_specifier)
    declarator: (primitive_type))
  (type_definition
    type: (sized_type_specifier)
    declarator: (primitive_type))
  (type_definition
    type: (sized_type_specifier)
    declarator: (primitive_type))
  (type_definition
    type: (primitive_type)
    declarator: (type_identifier)
    (attribute_specifier
      (argument_list
        (call_expression
          function: (identifier)
          arguments: (argument_list
            (identifier))))))
  (type_definition
    type: (sized_type_specifier
      type: (primitive_type))
    declarator: (type_identifier))
  (type_definition
    type: (struct_specifier
      body: (field_declaration_list
        (field_declaration
          type: (sized_type_specifier
            type: (primitive_type))
          declarator: (field_identifier))
        (field_declaration
          type: (sized_type_specifier
            type: (primitive_type))
          declarator: (field_identifier))))
    declarator: (type_identifier)))

================================================================================
Function declarations
================================================================================

int main(int argc, const char **argv);
static foo bar();
static baz quux(...);

--------------------------------------------------------------------------------

(translation_unit
  (declaration
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list
        (parameter_declaration
          (primitive_type)
          (identifier))
        (parameter_declaration
          (type_qualifier)
          (primitive_type)
          (pointer_declarator
            (pointer_declarator
              (identifier)))))))
  (declaration
    (storage_class_specifier)
    (type_identifier)
    (function_declarator
      (identifier)
      (parameter_list)))
  (declaration
    (storage_class_specifier)
    (type_identifier)
    (function_declarator
      (identifier)
      (parameter_list))))

================================================================================
Function definitions
================================================================================

void * do_stuff(int arg1) {
  return 5;
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    type: (primitive_type)
    declarator: (pointer_declarator
      declarator: (function_declarator
        declarator: (identifier)
        parameters: (parameter_list
          (parameter_declaration
            type: (primitive_type)
            declarator: (identifier)))))
    body: (compound_statement
      (return_statement
        (number_literal)))))

================================================================================
Function specifiers after types
================================================================================

int static inline do_stuff(int arg1) {
  return 5;
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (storage_class_specifier)
    (storage_class_specifier)
    (function_declarator
      (identifier)
      (parameter_list
        (parameter_declaration
          (primitive_type)
          (identifier))))
    (compound_statement
      (return_statement
        (number_literal)))))

================================================================================
Linkage specifications
================================================================================

extern "C" int foo();

extern "C" int foo() { return 0; }

extern "C" {
  int bar();
  int baz();
}

--------------------------------------------------------------------------------

(translation_unit
  (linkage_specification
    (string_literal
      (string_content))
    (declaration
      (primitive_type)
      (function_declarator
        (identifier)
        (parameter_list))))
  (linkage_specification
    (string_literal
      (string_content))
    (function_definition
      (primitive_type)
      (function_declarator
        (identifier)
        (parameter_list))
      (compound_statement
        (return_statement
          (number_literal)))))
  (linkage_specification
    (string_literal
      (string_content))
    (declaration_list
      (declaration
        (primitive_type)
        (function_declarator
          (identifier)
          (parameter_list)))
      (declaration
        (primitive_type)
        (function_declarator
          (identifier)
          (parameter_list))))))

================================================================================
Type qualifiers
================================================================================

const _Atomic unsigned long int x = 5;
restrict int y = 6;
volatile int z = 7;
constexpr int a = 8;
__thread int c = 9;
noreturn void b() {}
 __extension__ extern int ffsll (long long int __ll)
     __attribute__ ((__nothrow__ )) __attribute__ ((__const__));

--------------------------------------------------------------------------------

(translation_unit
  (declaration
    (type_qualifier)
    (type_qualifier)
    (sized_type_specifier
      (primitive_type))
    (init_declarator
      (identifier)
      (number_literal)))
  (declaration
    (type_qualifier)
    (primitive_type)
    (init_declarator
      (identifier)
      (number_literal)))
  (declaration
    (type_qualifier)
    (primitive_type)
    (init_declarator
      (identifier)
      (number_literal)))
  (declaration
    (type_qualifier)
    (primitive_type)
    (init_declarator
      (identifier)
      (number_literal)))
  (declaration
    (storage_class_specifier)
    (primitive_type)
    (init_declarator
      (identifier)
      (number_literal)))
  (function_definition
    (type_qualifier)
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement))
  (declaration
    (type_qualifier)
    (storage_class_specifier)
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list
        (parameter_declaration
          (sized_type_specifier
            (primitive_type))
          (identifier)))
      (attribute_specifier
        (argument_list
          (identifier)))
      (attribute_specifier
        (argument_list
          (identifier))))))

================================================================================
Local array declarations
================================================================================

int main() {
  char the_buffer[the_size];
  char the_other_buffer[*];
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (declaration
        (primitive_type)
        (array_declarator
          (identifier)
          (identifier)))
      (declaration
        (primitive_type)
        (array_declarator
          (identifier))))))

================================================================================
Attributes
================================================================================

extern __attribute__((visibility("hidden"))) int foo();
extern int bar() __attribute__((const));
void die(const char *format, ...) __attribute__((noreturn))
                                  __attribute__((format(printf,1,2)));
extern __attribute__((visibility("default"), weak)) int print_status();

extern int strerror_r(int __errnum, char *__buf,
                      int __buflen) __asm__(""
                                            "__xpg_strerror_r")
    __attribute__((__nothrow__)) __attribute__((__nonnull__(2)));

int f([[a::b(c), d]] int x) {}

[[gnu::always_inline]] [[gnu::hot]] [[gnu::const]] [[nodiscard]]
int g(void);

[[gnu::always_inline, gnu::hot, gnu::const, nodiscard]]
int g(void);

int i [[maybe_unused]];
void f[[gnu::always_inline]]();

[[nodiscard("reason")]] int foo;

[[fallthrough]];

struct S {
  int a [[deprecated]];
};

typedef int MyInt [[deprecated]];

struct X {
    int a __attribute__((aligned(4)));
} __attribute__((aligned(16)));

union Y {
    int a __attribute__((aligned(4)));
} __attribute__((aligned(16)));

enum Z {
    A
} __attribute__((aligned(16)));

struct __attribute__((__packed__)) foo_t {
  int x;
};

--------------------------------------------------------------------------------

(translation_unit
  (declaration
    (storage_class_specifier)
    (attribute_specifier
      (argument_list
        (call_expression
          (identifier)
          (argument_list
            (string_literal
              (string_content))))))
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list)))
  (declaration
    (storage_class_specifier)
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list)
      (attribute_specifier
        (argument_list
          (identifier)))))
  (declaration
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list
        (parameter_declaration
          (type_qualifier)
          (primitive_type)
          (pointer_declarator
            (identifier))))
      (attribute_specifier
        (argument_list
          (identifier)))
      (attribute_specifier
        (argument_list
          (call_expression
            (identifier)
            (argument_list
              (identifier)
              (number_literal)
              (number_literal)))))))
  (declaration
    (storage_class_specifier)
    (attribute_specifier
      (argument_list
        (call_expression
          (identifier)
          (argument_list
            (string_literal
              (string_content))))
        (identifier)))
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list)))
  (declaration
    (storage_class_specifier)
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list
        (parameter_declaration
          (primitive_type)
          (identifier))
        (parameter_declaration
          (primitive_type)
          (pointer_declarator
            (identifier)))
        (parameter_declaration
          (primitive_type)
          (identifier)))
      (gnu_asm_expression
        (concatenated_string
          (string_literal)
          (string_literal
            (string_content))))
      (attribute_specifier
        (argument_list
          (identifier)))
      (attribute_specifier
        (argument_list
          (call_expression
            (identifier)
            (argument_list
              (number_literal)))))))
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list
        (parameter_declaration
          (attribute_declaration
            (attribute
              (identifier)
              (identifier)
              (argument_list
                (identifier)))
            (attribute
              (identifier)))
          (primitive_type)
          (identifier))))
    (compound_statement))
  (declaration
    (attribute_declaration
      (attribute
        (identifier)
        (identifier)))
    (attribute_declaration
      (attribute
        (identifier)
        (identifier)))
    (attribute_declaration
      (attribute
        (identifier)
        (identifier)))
    (attribute_declaration
      (attribute
        (identifier)))
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list
        (parameter_declaration
          (primitive_type)))))
  (declaration
    (attribute_declaration
      (attribute
        (identifier)
        (identifier))
      (attribute
        (identifier)
        (identifier))
      (attribute
        (identifier)
        (identifier))
      (attribute
        (identifier)))
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list
        (parameter_declaration
          (primitive_type)))))
  (declaration
    (primitive_type)
    (attributed_declarator
      (identifier)
      (attribute_declaration
        (attribute
          (identifier)))))
  (declaration
    (primitive_type)
    (function_declarator
      (attributed_declarator
        (identifier)
        (attribute_declaration
          (attribute
            (identifier)
            (identifier))))
      (parameter_list)))
  (declaration
    (attribute_declaration
      (attribute
        (identifier)
        (argument_list
          (string_literal
            (string_content)))))
    (primitive_type)
    (identifier))
  (attributed_statement
    (attribute_declaration
      (attribute
        (identifier)))
    (expression_statement))
  (struct_specifier
    (type_identifier)
    (field_declaration_list
      (field_declaration
        (primitive_type)
        (attributed_declarator
          (field_identifier)
          (attribute_declaration
            (attribute
              (identifier)))))))
  (type_definition
    (primitive_type)
    (attributed_declarator
      (type_identifier)
      (attribute_declaration
        (attribute
          (identifier)))))
  (struct_specifier
    (type_identifier)
    (field_declaration_list
      (field_declaration
        (primitive_type)
        (field_identifier)
        (attribute_specifier
          (argument_list
            (call_expression
              (identifier)
              (argument_list
                (number_literal)))))))
    (attribute_specifier
      (argument_list
        (call_expression
          (identifier)
          (argument_list
            (number_literal))))))
  (union_specifier
    (type_identifier)
    (field_declaration_list
      (field_declaration
        (primitive_type)
        (field_identifier)
        (attribute_specifier
          (argument_list
            (call_expression
              (identifier)
              (argument_list
                (number_literal)))))))
    (attribute_specifier
      (argument_list
        (call_expression
          (identifier)
          (argument_list
            (number_literal))))))
  (enum_specifier
    (type_identifier)
    (enumerator_list
      (enumerator
        (identifier)))
    (attribute_specifier
      (argument_list
        (call_expression
          (identifier)
          (argument_list
            (number_literal))))))
  (struct_specifier
    (attribute_specifier
      (argument_list
        (identifier)))
    (type_identifier)
    (field_declaration_list
      (field_declaration
        (primitive_type)
        (field_identifier)))))



================================================
FILE: test/corpus/c/expressions.txt
================================================
================================================================================
Number literals
================================================================================

double a = {
  0xAC00,
  0.123,
  0b1010001,
  0xabc00ull,
  -0.1f,
  1'000'000.000'001,
  24e-5,
  0.1E1,
  58.,
  4e2,
  123.456e-67,
  .1E4f,
  0x10.1p0,
};

--------------------------------------------------------------------------------

(translation_unit
  (declaration
    (primitive_type)
    (init_declarator
      (identifier)
      (initializer_list
        (number_literal)
        (number_literal)
        (number_literal)
        (number_literal)
        (number_literal)
        (number_literal)
        (number_literal)
        (number_literal)
        (number_literal)
        (number_literal)
        (number_literal)
        (number_literal)
        (number_literal)))))

================================================================================
Identifiers
================================================================================

int main() {
  _abc;
  d_EG123;
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (expression_statement
        (identifier))
      (expression_statement
        (identifier)))))

================================================================================
Unicode Identifiers
================================================================================

int main() {
  µs;
  blah_accenté;
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (expression_statement
        (identifier))
      (expression_statement
        (identifier)))))

================================================================================
Common constants
================================================================================

int main() {
  true;
  false;
  NULL;

  // regression test - identifiers starting w/ these strings should tokenize correctly.
  true_value;
  false_value;
  NULL_value;
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (expression_statement
        (true))
      (expression_statement
        (false))
      (expression_statement
        (null))
      (comment)
      (expression_statement
        (identifier))
      (expression_statement
        (identifier))
      (expression_statement
        (identifier)))))

================================================================================
Function calls
================================================================================

int main() {
  printf("hi! %d\n", x);
  __assert_fail("some_error_message", 115, __extension__ __func__);
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (expression_statement
        (call_expression
          (identifier)
          (argument_list
            (string_literal
              (string_content)
              (escape_sequence))
            (identifier))))
      (expression_statement
        (call_expression
          (identifier)
          (argument_list
            (string_literal
              (string_content))
            (number_literal)
            (extension_expression
              (identifier))))))))

================================================================================
GNU inline assembly
================================================================================

asm volatile (
    "mov r0, %0\n"
    "mov r1, %[y]\n"
    "add r2, r0, r1\n"
    "mov %1, r2\n"
    :     "r"  (z)
    :     "=r" (x),
      [y] "=r" ((uintptr_t) y)
    : "r2");

--------------------------------------------------------------------------------

(translation_unit
  (expression_statement
    (gnu_asm_expression
      (gnu_asm_qualifier)
      (concatenated_string
        (string_literal
          (string_content)
          (escape_sequence))
        (string_literal
          (string_content)
          (escape_sequence))
        (string_literal
          (string_content)
          (escape_sequence))
        (string_literal
          (string_content)
          (escape_sequence)))
      (gnu_asm_output_operand_list
        (gnu_asm_output_operand
          (string_literal
            (string_content))
          (identifier)))
      (gnu_asm_input_operand_list
        (gnu_asm_input_operand
          (string_literal
            (string_content))
          (identifier))
        (gnu_asm_input_operand
          (identifier)
          (string_literal
            (string_content))
          (cast_expression
            (type_descriptor
              (primitive_type))
            (identifier))))
      (gnu_asm_clobber_list
        (string_literal
          (string_content))))))

================================================================================
Function call with compound statement
================================================================================

#define TAKES_BLOCK(x, block) for (i = 0; i < x; i++) block

int main(void) {
  {
    int x = 0;
  }
  TAKES_BLOCK(10, {
    // Doesn't matter what I put in here
  });
}

--------------------------------------------------------------------------------

(translation_unit
  (preproc_function_def
    (identifier)
    (preproc_params
      (identifier)
      (identifier))
    (preproc_arg))
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list
        (parameter_declaration
          (primitive_type))))
    (compound_statement
      (compound_statement
        (declaration
          (primitive_type)
          (init_declarator
            (identifier)
            (number_literal))))
      (expression_statement
        (call_expression
          (identifier)
          (argument_list
            (number_literal)
            (initializer_list
              (comment))))))))

================================================================================
String literals
================================================================================

int main() {
  "a";
  "b" "c" "d";
  e "f" g;
  "\"hi\"";
  L"bonjour";
  u"guten morgen";
  U"buenos dias";
  u8"buongiorno";
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (expression_statement
        (string_literal
          (string_content)))
      (expression_statement
        (concatenated_string
          (string_literal
            (string_content))
          (string_literal
            (string_content))
          (string_literal
            (string_content))))
      (expression_statement
        (concatenated_string
          (identifier)
          (string_literal
            (string_content))
          (identifier)))
      (expression_statement
        (string_literal
          (escape_sequence)
          (string_content)
          (escape_sequence)))
      (expression_statement
        (string_literal
          (string_content)))
      (expression_statement
        (string_literal
          (string_content)))
      (expression_statement
        (string_literal
          (string_content)))
      (expression_statement
        (string_literal
          (string_content))))))

================================================================================
Character literals
================================================================================

int main() {
  'a';
  '\0';
  '\t';
  '\'';
  L'b';
  u'c';
  U'\xa1';
  u8'\x1A';
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (expression_statement
        (char_literal
          (character)))
      (expression_statement
        (char_literal
          (escape_sequence)))
      (expression_statement
        (char_literal
          (escape_sequence)))
      (expression_statement
        (char_literal
          (escape_sequence)))
      (expression_statement
        (char_literal
          (character)))
      (expression_statement
        (char_literal
          (character)))
      (expression_statement
        (char_literal
          (escape_sequence)))
      (expression_statement
        (char_literal
          (escape_sequence))))))

================================================================================
Field access
================================================================================

int main() {
  s.data1;
  p->data2;
  q[data3];
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (expression_statement
        (field_expression
          (identifier)
          (field_identifier)))
      (expression_statement
        (field_expression
          (identifier)
          (field_identifier)))
      (expression_statement
        (subscript_expression
          (identifier)
          (subscript_argument_list
            (identifier)))))))

================================================================================
Boolean operators
================================================================================

int main() {
  !x || !y && !z;
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (expression_statement
        (binary_expression
          (unary_expression
            (identifier))
          (binary_expression
            (unary_expression
              (identifier))
            (unary_expression
              (identifier))))))))

================================================================================
Math operators
================================================================================

int main() {
  -a / b + c * -d;
  a++ - ++b + c-- + --d;
  ++L;
  }

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (expression_statement
        (binary_expression
          (binary_expression
            (unary_expression
              (identifier))
            (identifier))
          (binary_expression
            (identifier)
            (unary_expression
              (identifier)))))
      (expression_statement
        (binary_expression
          (binary_expression
            (binary_expression
              (update_expression
                (identifier))
              (update_expression
                (identifier)))
            (update_expression
              (identifier)))
          (update_expression
            (identifier))))
      (expression_statement
        (update_expression
          (identifier))))))

================================================================================
The comma operator
================================================================================

int main() {
  i--, j--;
  (i--, j--);
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (expression_statement
        (comma_expression
          (update_expression
            (identifier))
          (update_expression
            (identifier))))
      (expression_statement
        (parenthesized_expression
          (comma_expression
            (update_expression
              (identifier))
            (update_expression
              (identifier))))))))

================================================================================
Assignments
================================================================================

int main() {
  static int a = 1;
  b = *c = 2;
  d.e = 3;
  f->g = 4;
  h[i] = j;
  k += l;
  m -= o;
  n *= p;
  q /= r;
  *s++ = 1;
  (*t) = 1;
  a *= ((b!=c) ? d : e);
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    type: (primitive_type)
    declarator: (function_declarator
      declarator: (identifier)
      parameters: (parameter_list))
    body: (compound_statement
      (declaration
        (storage_class_specifier)
        type: (primitive_type)
        declarator: (init_declarator
          declarator: (identifier)
          value: (number_literal)))
      (expression_statement
        (assignment_expression
          left: (identifier)
          right: (assignment_expression
            left: (pointer_expression
              argument: (identifier))
            right: (number_literal))))
      (expression_statement
        (assignment_expression
          left: (field_expression
            argument: (identifier)
            field: (field_identifier))
          right: (number_literal)))
      (expression_statement
        (assignment_expression
          left: (field_expression
            argument: (identifier)
            field: (field_identifier))
          right: (number_literal)))
      (expression_statement
        (assignment_expression
          left: (subscript_expression
            argument: (identifier)
            indices: (subscript_argument_list
              (identifier)))
          right: (identifier)))
      (expression_statement
        (assignment_expression
          left: (identifier)
          right: (identifier)))
      (expression_statement
        (assignment_expression
          left: (identifier)
          right: (identifier)))
      (expression_statement
        (assignment_expression
          left: (identifier)
          right: (identifier)))
      (expression_statement
        (assignment_expression
          left: (identifier)
          right: (identifier)))
      (expression_statement
        (assignment_expression
          left: (pointer_expression
            argument: (update_expression
              argument: (identifier)))
          right: (number_literal)))
      (expression_statement
        (assignment_expression
          left: (parenthesized_expression
            (pointer_expression
              argument: (identifier)))
          right: (number_literal)))
      (expression_statement
        (assignment_expression
          left: (identifier)
          right: (parenthesized_expression
            (conditional_expression
              condition: (parenthesized_expression
                (binary_expression
                  left: (identifier)
                  right: (identifier)))
              consequence: (identifier)
              alternative: (identifier))))))))

================================================================================
Pointer operations
================================================================================

int main() {
  doSomething(&x, *x);
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (expression_statement
        (call_expression
          (identifier)
          (argument_list
            (pointer_expression
              (identifier))
            (pointer_expression
              (identifier))))))))

================================================================================
Type-casts
================================================================================

int main() {
  x = (const SomeType *)thing;
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    type: (primitive_type)
    declarator: (function_declarator
      declarator: (identifier)
      parameters: (parameter_list))
    body: (compound_statement
      (expression_statement
        (assignment_expression
          left: (identifier)
          right: (cast_expression
            type: (type_descriptor
              (type_qualifier)
              type: (type_identifier)
              declarator: (abstract_pointer_declarator))
            value: (identifier)))))))

================================================================================
Sizeof expressions
================================================================================

int main() {
  sizeof x.a;
  sizeof(x.a);
  sizeof(const char **);
  sizeof(char * ());
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (expression_statement
        (sizeof_expression
          (field_expression
            (identifier)
            (field_identifier))))
      (expression_statement
        (sizeof_expression
          (parenthesized_expression
            (field_expression
              (identifier)
              (field_identifier)))))
      (expression_statement
        (sizeof_expression
          (type_descriptor
            (type_qualifier)
            (primitive_type)
            (abstract_pointer_declarator
              (abstract_pointer_declarator)))))
      (expression_statement
        (sizeof_expression
          (type_descriptor
            (primitive_type)
            (abstract_pointer_declarator
              (abstract_function_declarator
                (parameter_list)))))))))

================================================================================
Alignof expressions
================================================================================

typedef struct {
    long long __clang_max_align_nonce1
        __attribute__((__aligned__(__alignof__(long long))));
    long double __clang_max_align_nonce2
        __attribute__((__aligned__(__alignof__(long double))));
} max_align_t;

--------------------------------------------------------------------------------

(translation_unit
  (type_definition
    (struct_specifier
      (field_declaration_list
        (field_declaration
          (sized_type_specifier)
          (field_identifier)
          (attribute_specifier
            (argument_list
              (call_expression
                (identifier)
                (argument_list
                  (alignof_expression
                    (type_descriptor
                      (sized_type_specifier))))))))
        (field_declaration
          (sized_type_specifier
            (primitive_type))
          (field_identifier)
          (attribute_specifier
            (argument_list
              (call_expression
                (identifier)
                (argument_list
                  (alignof_expression
                    (type_descriptor
                      (sized_type_specifier
                        (primitive_type)))))))))))
    (primitive_type)))

================================================================================
Offsetof expressions
================================================================================

int main() {
  offsetof( struct x, a );
  offsetof( x, a );
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (expression_statement
        (offsetof_expression
          (type_descriptor
            (struct_specifier
              (type_identifier)))
          (field_identifier)))
      (expression_statement
        (offsetof_expression
          (type_descriptor
            (type_identifier))
          (field_identifier))))))

================================================================================
Compound literals
================================================================================

int main() {
  x = (SomeType) {
    .f1.f2[f3] = 5,
    .f4 = {}
  };
  y = (struct SomeStruct) {
    7,
    8
  };
  z = (char const []) {'a', 'b'};
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (expression_statement
        (assignment_expression
          (identifier)
          (compound_literal_expression
            (type_descriptor
              (type_identifier))
            (initializer_list
              (initializer_pair
                (field_designator
                  (field_identifier))
                (field_designator
                  (field_identifier))
                (subscript_designator
                  (identifier))
                (number_literal))
              (initializer_pair
                (field_designator
                  (field_identifier))
                (initializer_list))))))
      (expression_statement
        (assignment_expression
          (identifier)
          (compound_literal_expression
            (type_descriptor
              (struct_specifier
                (type_identifier)))
            (initializer_list
              (number_literal)
              (number_literal)))))
      (expression_statement
        (assignment_expression
          (identifier)
          (compound_literal_expression
            (type_descriptor
              (primitive_type)
              (type_qualifier)
              (abstract_array_declarator))
            (initializer_list
              (char_literal
                (character))
              (char_literal
                (character)))))))))

================================================================================
Compound literals with trailing commas
================================================================================

int main() {
  y = (struct SomeStruct) { 7, 8, };
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (expression_statement
        (assignment_expression
          (identifier)
          (compound_literal_expression
            (type_descriptor
              (struct_specifier
                (type_identifier)))
            (initializer_list
              (number_literal)
              (number_literal))))))))

================================================================================
Comments with escaped newlines
================================================================================

// one \
   two

--------------------------------------------------------------------------------

(translation_unit
  (comment))

================================================================================
Comments with escaped chars and newlines
================================================================================

// one \a \b \
   two
// one \c \d
--------------------------------------------------------------------------------

(translation_unit
  (comment)
  (comment))

================================================================================
Generic Expressions
================================================================================

int main(int argc, char **argv) {
  int    a = 10;
  float  b = 3.14;
  double c = 2.71828;
  char   d = 'A';

  a = _Generic(d, int: 5, float: 0, char: 100);
  b = _Generic(a, void *: 0, int: 4.0, float: 3.14, double: 2.71828, char: 1.0);
	c = _Generic(b, void *: 0, int: 4.0, float: 3.14, double: 2.71828, char: 1.0);
	d = _Generic(c, void *: '\0', int: '0', float: '3', double: '2', char: '1');

  _Generic(a, int: printf("a is an int\n"), float: printf("a is a float\n"), double: printf("a is a double\n"), char: printf("a is a char\n"));
  _Generic(b, int: printf("b is an int\n"), float: printf("b is a float\n"), double: printf("b is a double\n"), char: printf("b is a char\n"));
  _Generic(c, int: printf("c is an int\n"), float: printf("c is a float\n"), double: printf("c is a double\n"), char: printf("c is a char\n"));
  _Generic(d, int: printf("d is an int\n"), float: printf("d is a float\n"), double: printf("d is a double\n"), char: printf("d is a char\n"));

  return 0;
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list
        (parameter_declaration
          (primitive_type)
          (identifier))
        (parameter_declaration
          (primitive_type)
          (pointer_declarator
            (pointer_declarator
              (identifier))))))
    (compound_statement
      (declaration
        (primitive_type)
        (init_declarator
          (identifier)
          (number_literal)))
      (declaration
        (primitive_type)
        (init_declarator
          (identifier)
          (number_literal)))
      (declaration
        (primitive_type)
        (init_declarator
          (identifier)
          (number_literal)))
      (declaration
        (primitive_type)
        (init_declarator
          (identifier)
          (char_literal
            (character))))
      (expression_statement
        (assignment_expression
          (identifier)
          (generic_expression
            (identifier)
            (type_descriptor
              (primitive_type))
            (number_literal)
            (type_descriptor
              (primitive_type))
            (number_literal)
            (type_descriptor
              (primitive_type))
            (number_literal))))
      (expression_statement
        (assignment_expression
          (identifier)
          (generic_expression
            (identifier)
            (type_descriptor
              (primitive_type)
              (abstract_pointer_declarator))
            (number_literal)
            (type_descriptor
              (primitive_type))
            (number_literal)
            (type_descriptor
              (primitive_type))
            (number_literal)
            (type_descriptor
              (primitive_type))
            (number_literal)
            (type_descriptor
              (primitive_type))
            (number_literal))))
      (expression_statement
        (assignment_expression
          (identifier)
          (generic_expression
            (identifier)
            (type_descriptor
              (primitive_type)
              (abstract_pointer_declarator))
            (number_literal)
            (type_descriptor
              (primitive_type))
            (number_literal)
            (type_descriptor
              (primitive_type))
            (number_literal)
            (type_descriptor
              (primitive_type))
            (number_literal)
            (type_descriptor
              (primitive_type))
            (number_literal))))
      (expression_statement
        (assignment_expression
          (identifier)
          (generic_expression
            (identifier)
            (type_descriptor
              (primitive_type)
              (abstract_pointer_declarator))
            (char_literal
              (escape_sequence))
            (type_descriptor
              (primitive_type))
            (char_literal
              (character))
            (type_descriptor
              (primitive_type))
            (char_literal
              (character))
            (type_descriptor
              (primitive_type))
            (char_literal
              (character))
            (type_descriptor
              (primitive_type))
            (char_literal
              (character)))))
      (expression_statement
        (generic_expression
          (identifier)
          (type_descriptor
            (primitive_type))
          (call_expression
            (identifier)
            (argument_list
              (string_literal
                (string_content)
                (escape_sequence))))
          (type_descriptor
            (primitive_type))
          (call_expression
            (identifier)
            (argument_list
              (string_literal
                (string_content)
                (escape_sequence))))
          (type_descriptor
            (primitive_type))
          (call_expression
            (identifier)
            (argument_list
              (string_literal
                (string_content)
                (escape_sequence))))
          (type_descriptor
            (primitive_type))
          (call_expression
            (identifier)
            (argument_list
              (string_literal
                (string_content)
                (escape_sequence))))))
      (expression_statement
        (generic_expression
          (identifier)
          (type_descriptor
            (primitive_type))
          (call_expression
            (identifier)
            (argument_list
              (string_literal
                (string_content)
                (escape_sequence))))
          (type_descriptor
            (primitive_type))
          (call_expression
            (identifier)
            (argument_list
              (string_literal
                (string_content)
                (escape_sequence))))
          (type_descriptor
            (primitive_type))
          (call_expression
            (identifier)
            (argument_list
              (string_literal
                (string_content)
                (escape_sequence))))
          (type_descriptor
            (primitive_type))
          (call_expression
            (identifier)
            (argument_list
              (string_literal
                (string_content)
                (escape_sequence))))))
      (expression_statement
        (generic_expression
          (identifier)
          (type_descriptor
            (primitive_type))
          (call_expression
            (identifier)
            (argument_list
              (string_literal
                (string_content)
                (escape_sequence))))
          (type_descriptor
            (primitive_type))
          (call_expression
            (identifier)
            (argument_list
              (string_literal
                (string_content)
                (escape_sequence))))
          (type_descriptor
            (primitive_type))
          (call_expression
            (identifier)
            (argument_list
              (string_literal
                (string_content)
                (escape_sequence))))
          (type_descriptor
            (primitive_type))
          (call_expression
            (identifier)
            (argument_list
              (string_literal
                (string_content)
                (escape_sequence))))))
      (expression_statement
        (generic_expression
          (identifier)
          (type_descriptor
            (primitive_type))
          (call_expression
            (identifier)
            (argument_list
              (string_literal
                (string_content)
                (escape_sequence))))
          (type_descriptor
            (primitive_type))
          (call_expression
            (identifier)
            (argument_list
              (string_literal
                (string_content)
                (escape_sequence))))
          (type_descriptor
            (primitive_type))
          (call_expression
            (identifier)
            (argument_list
              (string_literal
                (string_content)
                (escape_sequence))))
          (type_descriptor
            (primitive_type))
          (call_expression
            (identifier)
            (argument_list
              (string_literal
                (string_content)
                (escape_sequence))))))
      (return_statement
        (number_literal)))))

================================================================================
Noreturn Type Qualifier
================================================================================

_Noreturn void kill(void) {
  printf("Killing the program\n");
  exit(0);
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (type_qualifier)
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list
        (parameter_declaration
          (primitive_type))))
    (compound_statement
      (expression_statement
        (call_expression
          (identifier)
          (argument_list
            (string_literal
              (string_content)
              (escape_sequence)))))
      (expression_statement
        (call_expression
          (identifier)
          (argument_list
            (number_literal)))))))

================================================================================
Restrict Type Qualifier
================================================================================

void fn (int *__restrict__ rptr) {
  int *ptr = rptr;
  *ptr = 0;
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list
        (parameter_declaration
          (primitive_type)
          (pointer_declarator
            (type_qualifier)
            (identifier)))))
    (compound_statement
      (declaration
        (primitive_type)
        (init_declarator
          (pointer_declarator
            (identifier))
          (identifier)))
      (expression_statement
        (assignment_expression
          (pointer_expression
            (identifier))
          (number_literal))))))



================================================
FILE: test/corpus/c/microsoft.txt
================================================
================================
declaration specs
================================

struct __declspec(dllexport) s2
{
};

union __declspec(noinline) u2 {
};

---

(translation_unit
  (struct_specifier
    (ms_declspec_modifier
      (identifier))
    name: (type_identifier)
    body: (field_declaration_list))
  (union_specifier
    (ms_declspec_modifier
      (identifier))
    name: (type_identifier)
    body: (field_declaration_list)))

================================
pointers
================================

struct s2
{
    int * __restrict x;
    int * __sptr psp;
    int * __uptr pup;
    int * __unaligned pup;
};

void sum2(int n, int * __restrict a, int * __restrict b,
          int * c, int * d) {
   int i;
   for (i = 0; i < n; i++) {
      a[i] = b[i] + c[i];
      c[i] = b[i] + d[i];
    }
}

void MyFunction(char * __uptr myValue);

---

(translation_unit
  (struct_specifier
    name: (type_identifier)
    body: (field_declaration_list
      (field_declaration
        type: (primitive_type)
        declarator: (pointer_declarator
          (ms_pointer_modifier
            (ms_restrict_modifier))
          declarator: (field_identifier)))
      (field_declaration
        type: (primitive_type)
        declarator: (pointer_declarator
          (ms_pointer_modifier
            (ms_signed_ptr_modifier))
          declarator: (field_identifier)))
      (field_declaration
        type: (primitive_type)
        declarator: (pointer_declarator
          (ms_pointer_modifier
            (ms_unsigned_ptr_modifier))
          declarator: (field_identifier)))
      (field_declaration
        type: (primitive_type)
        declarator: (pointer_declarator
          (ms_pointer_modifier
            (ms_unaligned_ptr_modifier))
          declarator: (field_identifier)))))
  (function_definition
    type: (primitive_type)
    declarator: (function_declarator
      declarator: (identifier)
      parameters: (parameter_list
        (parameter_declaration
          type: (primitive_type)
          declarator: (identifier))
        (parameter_declaration
          type: (primitive_type)
          declarator: (pointer_declarator
            (ms_pointer_modifier
              (ms_restrict_modifier))
            declarator: (identifier)))
        (parameter_declaration
          type: (primitive_type)
          declarator: (pointer_declarator
            (ms_pointer_modifier
              (ms_restrict_modifier))
            declarator: (identifier)))
        (parameter_declaration
          type: (primitive_type)
          declarator: (pointer_declarator
            declarator: (identifier)))
        (parameter_declaration
          type: (primitive_type)
          declarator: (pointer_declarator
            declarator: (identifier)))))
    body: (compound_statement
      (declaration
        type: (primitive_type)
        declarator: (identifier))
      (for_statement
        initializer: (assignment_expression
          left: (identifier)
          right: (number_literal))
        condition: (binary_expression
          left: (identifier)
          right: (identifier))
        update: (update_expression
          argument: (identifier))
        body: (compound_statement
          (expression_statement
            (assignment_expression
              left: (subscript_expression
                argument: (identifier)
                indices: (subscript_argument_list
                  (identifier)))
              right: (binary_expression
                left: (subscript_expression
                  argument: (identifier)
                  indices: (subscript_argument_list
                    (identifier)))
                right: (subscript_expression
                  argument: (identifier)
                  indices: (subscript_argument_list
                    (identifier))))))
          (expression_statement
            (assignment_expression
              left: (subscript_expression
                argument: (identifier)
                indices: (subscript_argument_list
                  (identifier)))
              right: (binary_expression
                left: (subscript_expression
                  argument: (identifier)
                  indices: (subscript_argument_list
                    (identifier)))
                right: (subscript_expression
                  argument: (identifier)
                  indices: (subscript_argument_list
                    (identifier))))))))))
  (declaration
    type: (primitive_type)
    declarator: (function_declarator
      declarator: (identifier)
      parameters: (parameter_list
        (parameter_declaration
          type: (primitive_type)
          declarator: (pointer_declarator
            (ms_pointer_modifier
              (ms_unsigned_ptr_modifier))
            declarator: (identifier)))))))

================================
call modifiers
================================

__cdecl void mymethod(){
    return;
}

__fastcall void mymethod(){
    return;
}

---

(translation_unit
  (function_definition
    (ms_call_modifier)
    type: (primitive_type)
    declarator: (function_declarator
      declarator: (identifier)
      parameters: (parameter_list))
    body: (compound_statement
      (return_statement)))
  (function_definition
    (ms_call_modifier)
    type: (primitive_type)
    declarator: (function_declarator
      declarator: (identifier)
      parameters: (parameter_list))
    body: (compound_statement
      (return_statement))))



================================================
FILE: test/corpus/c/preprocessor.txt
================================================
================================================================================
Include directives
================================================================================

#include "some/path.h"
#include <stdint.h>
#include MACRO
#include MACRO(arg1, arg2)

--------------------------------------------------------------------------------

(translation_unit
  (preproc_include
    path: (string_literal
      (string_content)))
  (preproc_include
    path: (system_lib_string))
  (preproc_include
    path: (identifier))
  (preproc_include
    path: (call_expression
      function: (identifier)
      arguments: (argument_list
        (identifier)
        (identifier)))))

================================================================================
Object-like macro definitions
================================================================================

#define ONE
    #define TWO int a = b;
#define THREE \
  c == d ? \
  e : \
  f
#define FOUR (mno * pq)
#define FIVE(a,b) x \
                  + y
#define SIX(a,   \
            b) x \
               + y
#define SEVEN 7/* seven has an
                * annoying comment */
#define EIGHT(x) do { \
        x = x + 1;  \
        x = x / 2;  \
    } while (x > 0);

--------------------------------------------------------------------------------

(translation_unit
  (preproc_def
    name: (identifier))
  (preproc_def
    name: (identifier)
    value: (preproc_arg))
  (preproc_def
    name: (identifier)
    value: (preproc_arg))
  (preproc_def
    name: (identifier)
    value: (preproc_arg))
  (preproc_function_def
    name: (identifier)
    parameters: (preproc_params
      (identifier)
      (identifier))
    value: (preproc_arg))
  (preproc_function_def
    name: (identifier)
    parameters: (preproc_params
      (identifier)
      (identifier))
    value: (preproc_arg))
  (preproc_def
    name: (identifier)
    value: (preproc_arg)
    (comment))
  (preproc_function_def
    name: (identifier)
    parameters: (preproc_params
      (identifier))
    value: (preproc_arg)))

================================================================================
Function-like macro definitions
================================================================================

#define ONE() a
#define TWO(b) c
#define THREE(d, e) f
#define FOUR(...) g
#define FIVE(h, i, ...) j

--------------------------------------------------------------------------------

(translation_unit
  (preproc_function_def
    name: (identifier)
    parameters: (preproc_params)
    value: (preproc_arg))
  (preproc_function_def
    name: (identifier)
    parameters: (preproc_params
      (identifier))
    value: (preproc_arg))
  (preproc_function_def
    name: (identifier)
    parameters: (preproc_params
      (identifier)
      (identifier))
    value: (preproc_arg))
  (preproc_function_def
    name: (identifier)
    parameters: (preproc_params)
    value: (preproc_arg))
  (preproc_function_def
    name: (identifier)
    parameters: (preproc_params
      (identifier)
      (identifier))
    value: (preproc_arg)))

================================================================================
Ifdefs
================================================================================

#ifndef DEFINE1
int j;
#endif

#ifdef DEFINE2
ssize_t b;
#define c 32
#elif defined DEFINE3
#else
int b;
#define c 16
#endif

#ifdef DEFINE2
#else
#  ifdef DEFINE3
#  else
#  endif
#endif

--------------------------------------------------------------------------------

(translation_unit
  (preproc_ifdef
    name: (identifier)
    (declaration
      type: (primitive_type)
      declarator: (identifier)))
  (preproc_ifdef
    name: (identifier)
    (declaration
      type: (primitive_type)
      declarator: (identifier))
    (preproc_def
      name: (identifier)
      value: (preproc_arg))
    alternative: (preproc_elif
      condition: (preproc_defined
        (identifier))
      alternative: (preproc_else
        (declaration
          type: (primitive_type)
          declarator: (identifier))
        (preproc_def
          name: (identifier)
          value: (preproc_arg)))))
  (preproc_ifdef
    name: (identifier)
    alternative: (preproc_else
      (preproc_ifdef
        name: (identifier)
        alternative: (preproc_else)))))

================================================================================
Elifdefs
================================================================================

#ifndef DEFINE1
int j;
#elifndef DEFINE2
int k;
#endif

#ifdef DEFINE2
ssize_t b;
#elifdef DEFINE3
ssize_t c;
#else
int b;
#endif

--------------------------------------------------------------------------------

(translation_unit
  (preproc_ifdef
    (identifier)
    (declaration
      (primitive_type)
      (identifier))
    (preproc_elifdef
      (identifier)
      (declaration
        (primitive_type)
        (identifier))))
  (preproc_ifdef
    (identifier)
    (declaration
      (primitive_type)
      (identifier))
    (preproc_elifdef
      (identifier)
      (declaration
        (primitive_type)
        (identifier))
      (preproc_else
        (declaration
          (primitive_type)
          (identifier))))))

================================================================================
General if blocks
================================================================================

#if defined(__GNUC__) && defined(__PIC__)
#define inline inline __attribute__((always_inline))
#elif defined(_WIN32)
#define something
#elif !defined(SOMETHING_ELSE)
#define SOMETHING_ELSE
#else
#include <something>
#endif

--------------------------------------------------------------------------------

(translation_unit
  (preproc_if
    condition: (binary_expression
      left: (preproc_defined
        (identifier))
      right: (preproc_defined
        (identifier)))
    (preproc_def
      name: (identifier)
      value: (preproc_arg))
    alternative: (preproc_elif
      condition: (preproc_defined
        (identifier))
      (preproc_def
        name: (identifier))
      alternative: (preproc_elif
        condition: (unary_expression
          argument: (preproc_defined
            (identifier)))
        (preproc_def
          name: (identifier))
        alternative: (preproc_else
          (preproc_include
            path: (system_lib_string)))))))

================================================================================
Preprocessor conditionals in functions
================================================================================

int main() {
  #if d
    puts("1");
  #else
    puts("2");
  #endif

  #if a
    return 0;
  #elif b
    return 1;
  #elif c
    return 2;
  #else
    return 3;
  #endif
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (preproc_if
        (identifier)
        (expression_statement
          (call_expression
            (identifier)
            (argument_list
              (string_literal
                (string_content)))))
        (preproc_else
          (expression_statement
            (call_expression
              (identifier)
              (argument_list
                (string_literal
                  (string_content)))))))
      (preproc_if
        (identifier)
        (return_statement
          (number_literal))
        (preproc_elif
          (identifier)
          (return_statement
            (number_literal))
          (preproc_elif
            (identifier)
            (return_statement
              (number_literal))
            (preproc_else
              (return_statement
                (number_literal)))))))))

================================================================================
Preprocessor conditionals in struct/union bodies
================================================================================

struct S {
#ifdef _WIN32
  LONG f2;
#else
  uint32_t f2;
#endif
};

--------------------------------------------------------------------------------

(translation_unit
  (struct_specifier
    (type_identifier)
    (field_declaration_list
      (preproc_ifdef
        (identifier)
        (field_declaration
          (type_identifier)
          (field_identifier))
        (preproc_else
          (field_declaration
            (primitive_type)
            (field_identifier)))))))

================================================================================
Unknown preprocessor directives
================================================================================

#pragma mark - UIViewController

--------------------------------------------------------------------------------

(translation_unit
  (preproc_call
    directive: (preproc_directive)
    argument: (preproc_arg)))

================================================================================
Preprocessor expressions
================================================================================

#if A(B || C) && \
    !D(F)

uint32_t a;

#endif

--------------------------------------------------------------------------------

(translation_unit
  (preproc_if
    (binary_expression
      (call_expression
        (identifier)
        (argument_list
          (binary_expression
            (identifier)
            (identifier))))
      (unary_expression
        (call_expression
          (identifier)
          (argument_list
            (identifier)))))
    (declaration
      (primitive_type)
      (identifier))))



================================================
FILE: test/corpus/c/statements.txt
================================================
================================================================================
If statements
================================================================================

int main() {
  if (a)
    1;

  if (!a) {
    2;
  } else {
    3;
  }
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (if_statement
        (condition_clause
          (identifier))
        (expression_statement
          (number_literal)))
      (if_statement
        (condition_clause
          (unary_expression
            (identifier)))
        (compound_statement
          (expression_statement
            (number_literal)))
        (else_clause
          (compound_statement
            (expression_statement
              (number_literal))))))))

================================================================================
For loops
================================================================================

int main() {
  for (;;)
    1;

  for (int i = 0; i < 5; next(), i++) {
    2;
  }

  for (start(); check(); step())
    3;

  for (i = 0, j = 0, k = 0, l = 0; i < 1, j < 1; i++, j++, k++, l++)
    1;
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (for_statement
        (expression_statement
          (number_literal)))
      (for_statement
        (declaration
          (primitive_type)
          (init_declarator
            (identifier)
            (number_literal)))
        (binary_expression
          (identifier)
          (number_literal))
        (comma_expression
          (call_expression
            (identifier)
            (argument_list))
          (update_expression
            (identifier)))
        (compound_statement
          (expression_statement
            (number_literal))))
      (for_statement
        (call_expression
          (identifier)
          (argument_list))
        (call_expression
          (identifier)
          (argument_list))
        (call_expression
          (identifier)
          (argument_list))
        (expression_statement
          (number_literal)))
      (for_statement
        (comma_expression
          (assignment_expression
            (identifier)
            (number_literal))
          (comma_expression
            (assignment_expression
              (identifier)
              (number_literal))
            (comma_expression
              (assignment_expression
                (identifier)
                (number_literal))
              (assignment_expression
                (identifier)
                (number_literal)))))
        (comma_expression
          (binary_expression
            (identifier)
            (number_literal))
          (binary_expression
            (identifier)
            (number_literal)))
        (comma_expression
          (update_expression
            (identifier))
          (comma_expression
            (update_expression
              (identifier))
            (comma_expression
              (update_expression
                (identifier))
              (update_expression
                (identifier)))))
        (expression_statement
          (number_literal))))))

================================================================================
While loops
================================================================================

int main() {
  while (x)
    printf("hi");
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (while_statement
        (condition_clause
          (identifier))
        (expression_statement
          (call_expression
            (identifier)
            (argument_list
              (string_literal
                (string_content)))))))))

================================================================================
Labeled statements
================================================================================

void foo(T *t) {
recur:
  t = t->next();
  if (t) goto recur;
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list
        (parameter_declaration
          (type_identifier)
          (pointer_declarator
            (identifier)))))
    (compound_statement
      (labeled_statement
        (statement_identifier)
        (expression_statement
          (assignment_expression
            (identifier)
            (call_expression
              (field_expression
                (identifier)
                (field_identifier))
              (argument_list)))))
      (if_statement
        (condition_clause
          (identifier))
        (goto_statement
          (statement_identifier))))))

================================================================================
Switch statements
================================================================================

void foo(int a) {
  switch (a) {
    puts("entered switch!");

    case 3:
    case 5:
      if (b) {
        c();
      }
      break;

    default:
      c();
      break;
  }
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list
        (parameter_declaration
          (primitive_type)
          (identifier))))
    (compound_statement
      (switch_statement
        (condition_clause
          (identifier))
        (compound_statement
          (expression_statement
            (call_expression
              (identifier)
              (argument_list
                (string_literal
                  (string_content)))))
          (case_statement
            (number_literal))
          (case_statement
            (number_literal)
            (if_statement
              (condition_clause
                (identifier))
              (compound_statement
                (expression_statement
                  (call_expression
                    (identifier)
                    (argument_list)))))
            (break_statement))
          (case_statement
            (expression_statement
              (call_expression
                (identifier)
                (argument_list)))
            (break_statement)))))))

================================================================================
Case statements separate from switch statements
================================================================================

int main() {
  switch (count % 8) {
  case 0:
    do {
      *to = *from++;
      case 2: *to = *from++;
      case 1: *to = *from++;
    } while (--n > 0);
  }
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (switch_statement
        (condition_clause
          (binary_expression
            (identifier)
            (number_literal)))
        (compound_statement
          (case_statement
            (number_literal)
            (do_statement
              (compound_statement
                (expression_statement
                  (assignment_expression
                    (pointer_expression
                      (identifier))
                    (pointer_expression
                      (update_expression
                        (identifier)))))
                (case_statement
                  (number_literal)
                  (expression_statement
                    (assignment_expression
                      (pointer_expression
                        (identifier))
                      (pointer_expression
                        (update_expression
                          (identifier))))))
                (case_statement
                  (number_literal)
                  (expression_statement
                    (assignment_expression
                      (pointer_expression
                        (identifier))
                      (pointer_expression
                        (update_expression
                          (identifier)))))))
              (parenthesized_expression
                (binary_expression
                  (update_expression
                    (identifier))
                  (number_literal))))))))))

================================================================================
Return statements
================================================================================

void foo() {
  return;
  return a;
  return a, b;
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (return_statement)
      (return_statement
        (identifier))
      (return_statement
        (comma_expression
          (identifier)
          (identifier))))))

================================================================================
Comments with asterisks
================================================================================

/*************************
 * odd number of asterisks
 *************************/
int a;

/**************************
 * even number of asterisks
 **************************/
int b;

--------------------------------------------------------------------------------

(translation_unit
  (comment)
  (declaration
    (primitive_type)
    (identifier))
  (comment)
  (declaration
    (primitive_type)
    (identifier)))

================================================================================
Comment with multiple backslashes
================================================================================

int a = 3; // Hello \\
World

--------------------------------------------------------------------------------

(translation_unit
  (declaration
    (primitive_type)
    (init_declarator
      (identifier)
      (number_literal)))
  (comment))

================================================================================
Attributes
================================================================================

void f() {
  [[a]] switch (b) {
   [[c]] case 1: {}
   case 2:
     [[fallthrough]];
   default:
  }
  [[a]] while (true) {}
  [[a]] if (true) {}
  [[a]] for (;;) {}
  [[a]] return;
  [[a]] a;
  [[a]];
  [[a]] label: {}
  [[a]] goto label;

  // these are c++ specific, but their bind locations should be c-compatible
  if (true) [[likely]] {} else [[unlikely]] {}
  do [[likely]] {} while (true);
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (attributed_statement
        (attribute_declaration
          (attribute
            (identifier)))
        (switch_statement
          (condition_clause
            (identifier))
          (compound_statement
            (attributed_statement
              (attribute_declaration
                (attribute
                  (identifier)))
              (case_statement
                (number_literal)
                (compound_statement)))
            (case_statement
              (number_literal)
              (attributed_statement
                (attribute_declaration
                  (attribute
                    (identifier)))
                (expression_statement)))
            (case_statement))))
      (attributed_statement
        (attribute_declaration
          (attribute
            (identifier)))
        (while_statement
          (condition_clause
            (true))
          (compound_statement)))
      (attributed_statement
        (attribute_declaration
          (attribute
            (identifier)))
        (if_statement
          (condition_clause
            (true))
          (compound_statement)))
      (attributed_statement
        (attribute_declaration
          (attribute
            (identifier)))
        (for_statement
          (compound_statement)))
      (attributed_statement
        (attribute_declaration
          (attribute
            (identifier)))
        (return_statement))
      (attributed_statement
        (attribute_declaration
          (attribute
            (identifier)))
        (expression_statement
          (identifier)))
      (attributed_statement
        (attribute_declaration
          (attribute
            (identifier)))
        (expression_statement))
      (attributed_statement
        (attribute_declaration
          (attribute
            (identifier)))
        (labeled_statement
          (statement_identifier)
          (compound_statement)))
      (attributed_statement
        (attribute_declaration
          (attribute
            (identifier)))
        (goto_statement
          (statement_identifier)))
      (comment)
      (if_statement
        (condition_clause
          (true))
        (attributed_statement
          (attribute_declaration
            (attribute
              (identifier)))
          (compound_statement))
        (else_clause
          (attributed_statement
            (attribute_declaration
              (attribute
                (identifier)))
            (compound_statement))))
      (do_statement
        (attributed_statement
          (attribute_declaration
            (attribute
              (identifier)))
          (compound_statement))
        (parenthesized_expression
          (true))))))



================================================
FILE: test/corpus/c/types.txt
================================================
========================================
Primitive types
========================================

int a;
uint8_t a;
uint16_t a;
uint32_t a;
uint64_t a;
uintptr_t a;

int8_t a;
int16_t a;
int32_t a;
int64_t a;
intptr_t a;

char16_t a;
char32_t a;

size_t a;
ssize_t a;

---

(translation_unit
  (declaration (primitive_type) (identifier))
  (declaration (primitive_type) (identifier))
  (declaration (primitive_type) (identifier))
  (declaration (primitive_type) (identifier))
  (declaration (primitive_type) (identifier))
  (declaration (primitive_type) (identifier))
  (declaration (primitive_type) (identifier))
  (declaration (primitive_type) (identifier))
  (declaration (primitive_type) (identifier))
  (declaration (primitive_type) (identifier))
  (declaration (primitive_type) (identifier))
  (declaration (primitive_type) (identifier))
  (declaration (primitive_type) (identifier))
  (declaration (primitive_type) (identifier))
  (declaration (primitive_type) (identifier)))

========================================
Type modifiers
========================================

void f(unsigned);
void f(unsigned int);
void f(signed long int);
void f(unsigned v1);
void f(unsigned long v2);

---

(translation_unit
  (declaration
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list (parameter_declaration (sized_type_specifier)))))
  (declaration
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list (parameter_declaration (sized_type_specifier (primitive_type))))))
  (declaration
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list (parameter_declaration (sized_type_specifier (primitive_type))))))
  (declaration
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list (parameter_declaration (sized_type_specifier) (identifier)))))
  (declaration
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list (parameter_declaration (sized_type_specifier) (identifier))))))



================================================
FILE: test/highlight/keywords.cpp
================================================
export module keywords;
// <- keyword
//   ^ keyword

import std;
// ^ keyword

using namespace std;
// ^ keyword

namespace foo {}
// ^ keyword

template <typename T>
// ^ keyword
//         ^ keyword

class A {
  // <- keyword

public:
  // <- keyword
private:
  // <- keyword
protected:
  // <- keyword
  virtual ~A() = 0;
  // <- keyword
};

int main() {
  throw new Error();
  // ^ keyword
  //     ^ keyword

  try {
    // <- keyword
  } catch (e) {
    // <- keyword
  }
}



================================================
FILE: test/highlight/names.cpp
================================================
int main() {
  a<T>();
  // <- function

  a::b();
  // ^ function

  a::b<C, D>();
  // ^ function

  this->b<C, D>();
  //    ^ function

  auto x = y;
  // <- type

  vector<T> a;
  // <- type

  std::vector<T> a;
  //   ^ type
}

class C : D{
  A();
  // <- function

  void efg() {
    // ^ function
  }
}

void A::b() {
  //    ^ function
}



================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"
    commit-message:
      prefix: "ci"



================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms

github: tree-sitter
patreon: # Replace with a single Patreon username
open_collective: tree-sitter # Replace with a single Open Collective username
ko_fi: amaanq
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
polar: # Replace with a single Polar username
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
thanks_dev: # Replace with a single thanks.dev username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']



================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.yml
================================================
name: Bug Report
description: File a bug or issue
title: "bug: "
labels: [bug]
body:
  - type: markdown
    attributes:
      value: |
        **Before** reporting an issue, make sure to search [existing issues](https://github.com/tree-sitter/tree-sitter-cpp/issues). Usage questions such as ***"How do I...?"*** either belong in [Discussions](https://github.com/tree-sitter/tree-sitter/discussions) upstream or in our [Discord server](https://discord.gg/w7nTvsVJhm) and will be closed.
        If your issue is related to a bug in your editor-experience because your editor *leverages* tree-sitter and this parser, then it is likely your issue does *NOT* belong here and belongs in the relevant editor's repository.
  - type: checkboxes
    attributes:
      label: Did you check existing issues?
      description: Make sure you've checked all of the below before submitting an issue
      options:
        - label: I have read all the [tree-sitter docs](https://tree-sitter.github.io/tree-sitter/using-parsers) if it relates to using the parser
          required: false
        - label: I have searched the existing issues of tree-sitter-cpp
          required: true
  - type: input
    attributes:
      label: "Tree-Sitter CLI Version, if relevant (output of `tree-sitter --version`)"
      placeholder: "tree-sitter 0.20.8 (6bbb50bef8249e6460e7d69e42cc8146622fa4fd)"
    validations:
      required: false
  - type: textarea
    attributes:
      label: Describe the bug
      description: A clear and concise description of what the bug is. Please include any related errors you see such as parsing errors or tree-sitter cli errors.
    validations:
      required: true
  - type: textarea
    attributes:
      label: Steps To Reproduce/Bad Parse Tree
      description: Steps to reproduce the behavior. If you have a bad parse tree, please include it here. You can get this by running `tree-sitter parse <path-to-file>` and copying the output.
      placeholder: |
        1.
        2.
        3.
    validations:
      required: true
  - type: textarea
    attributes:
      label: Expected Behavior/Parse Tree
      description: A concise description of what you expected to happen, or in the case of a bad parse tree, the expected parse tree.
    validations:
      required: true
  - type: textarea
    attributes:
      label: Repro
      description: Minimal code to reproduce this issue. Ideally this should be reproducible with the C library or the tree-sitter cli, do not suggest an editor or external tool.
      value: |
        // Example code that causes the issue
        void foo() {
          // Code that fails to parse, or causes an error
        }
      render: cpp
    validations:
      required: false



================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false



================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.yml
================================================
name: Feature Request
description: Suggest a new feature
title: "feature: "
labels: [enhancement]
body:
  - type: checkboxes
    attributes:
      label: Did you check the tree-sitter docs?
      description: Make sure you read all the docs before submitting a feature request
      options:
        - label: I have read all the [tree-sitter docs](https://tree-sitter.github.io/tree-sitter/using-parsers) if it relates to using the parser
          required: false
  - type: textarea
    validations:
      required: true
    attributes:
      label: Is your feature request related to a problem? Please describe.
      description: A clear and concise description of what the problem is. Ex. I think the grammar models this rule incorrectly and can be improved, or the scanner can be improved by doing [...], or C++ has officially added a new feature that should be added to the grammar.
  - type: textarea
    validations:
      required: true
    attributes:
      label: Describe the solution you'd like
      description: A clear and concise description of what you want to happen.
  - type: textarea
    validations:
      required: true
    attributes:
      label: Describe alternatives you've considered
      description: A clear and concise description of any alternative solutions or features you've considered.
  - type: textarea
    validations:
      required: false
    attributes:
      label: Additional context
      description: Add any other context or screenshots about the feature request here. If your feature request is related to a new C++ feature, please include a link to the relevant **official** C++ documentation.



================================================
FILE: .github/workflows/ci.yml
================================================
name: CI

on:
  push:
    branches: [master]
    paths:
      - grammar.js
      - src/**
      - test/**
      - bindings/**
      - binding.gyp
  pull_request:
    paths:
      - grammar.js
      - src/**
      - test/**
      - bindings/**
      - binding.gyp

concurrency:
  group: ${{github.workflow}}-${{github.ref}}
  cancel-in-progress: true

jobs:
  test:
    name: Test parser
    runs-on: ${{matrix.os}}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, windows-latest, macos-15]
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
      - name: Checkout tree-sitter-c
        uses: actions/checkout@v4
        with:
          repository: tree-sitter/tree-sitter-c
          path: node_modules/tree-sitter-c
          sparse-checkout: queries/
          ref: v0.23.6
      - name: Set up tree-sitter
        uses: tree-sitter/setup-action/cli@v2
      - name: Run tests
        uses: tree-sitter/parser-test-action@v2
        with:
          test-rust: true
          test-node: true
          test-python: true
          test-go: true
          test-swift: true
          abi-version: 14
      - name: Parse examples
        uses: tree-sitter/parse-action@v4
        with:
          files: examples/*



================================================
FILE: .github/workflows/fuzz.yml
================================================
name: Fuzz Parser

on:
  push:
    branches: [master]
    paths:
      - src/scanner.c
  pull_request:
    paths:
      - src/scanner.c

jobs:
  fuzz:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
      - name: Run fuzzer
        uses: tree-sitter/fuzz-action@v4



================================================
FILE: .github/workflows/lint.yml
================================================
name: Lint

on:
  push:
    branches: [master]
    paths:
      - grammar.js
  pull_request:
    paths:
      - grammar.js

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          cache: npm
          node-version: ${{vars.NODE_VERSION}}
      - name: Install modules
        run: npm ci --legacy-peer-deps
      - name: Run ESLint
        run: npm run lint



================================================
FILE: .github/workflows/publish.yml
================================================
name: Publish packages

on:
  push:
    tags: ["*"]

permissions:
  contents: write
  id-token: write
  attestations: write

jobs:
  github:
    uses: tree-sitter/workflows/.github/workflows/release.yml@main
    with:
      generate: true
      attestations: true
  npm:
    uses: tree-sitter/workflows/.github/workflows/package-npm.yml@main
    secrets:
      NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
    with:
      generate: true
  crates:
    uses: tree-sitter/workflows/.github/workflows/package-crates.yml@main
    secrets:
      CARGO_REGISTRY_TOKEN: ${{secrets.CARGO_REGISTRY_TOKEN}}
    with:
      generate: true
  pypi:
    uses: tree-sitter/workflows/.github/workflows/package-pypi.yml@main
    secrets:
      PYPI_API_TOKEN: ${{secrets.PYPI_API_TOKEN}}
    with:
      generate: true
