lectures.alex.balgavy.eu

Lecture notes from university.
git clone git://git.alex.balgavy.eu/lectures.alex.balgavy.eu.git
Log | Files | Refs | Submodules

C++.sublime-syntax (76083B)


      1 %YAML 1.2
      2 ---
      3 # http://www.sublimetext.com/docs/3/syntax.html
      4 name: C++
      5 comment: I don't think anyone uses .hp. .cp tends to be paired with .h. (I could be wrong. :) -- chris
      6 file_extensions:
      7   - cpp
      8   - cc
      9   - cp
     10   - cxx
     11   - c++
     12   - C
     13   - h
     14   - hh
     15   - hpp
     16   - hxx
     17   - h++
     18   - inl
     19   - ipp
     20 first_line_match: '-\*- C\+\+ -\*-'
     21 scope: source.c++
     22 variables:
     23   # number digits
     24   dec_digits: '(?:\d(?:[\d'']*\d)?)'
     25 
     26   # number exponents
     27   dec_exponent: '(?:[eE][-+]??{{dec_digits}})'
     28   hex_exponent: '(?:[pP][-+]??{{dec_digits}})'
     29 
     30   # number suffixes
     31   # note: nearly everything can be defined as suffix via `operator` keyword
     32   #  see: https://en.cppreference.com/w/cpp/numeric/complex/operator%22%22i
     33   dec_suffix: '(?:[a-zA-Z_][[:alnum:]_]*|(?=[^[:alnum:]_'']))'
     34   hex_suffix: '(?:[g-zG-Z_][[:alnum:]_]*|(?=[^[:alnum:]_'']))'
     35   float_suffix: '[fF]'
     36   integer_suffix: '[lL]{1,2}[uU]?|[uU][lL]{0,2}'
     37 
     38   identifier: \b[[:alpha:]_][[:alnum:]_]*\b # upper and lowercase
     39   macro_identifier: \b[[:upper:]_][[:upper:][:digit:]_]{2,}\b # only uppercase, at least 3 chars
     40   path_lookahead: '(?:::\s*)?(?:{{identifier}}\s*::\s*)*(?:template\s+)?{{identifier}}'
     41   operator_method_name: '\boperator\s*(?:[-+*/%^&|~!=<>]|[-+*/%^&|=!<>]=|<<=?|>>=?|&&|\|\||\+\+|--|,|->\*?|\(\)|\[\]|""\s*{{identifier}})'
     42   casts: 'const_cast|dynamic_cast|reinterpret_cast|static_cast'
     43   operator_keywords: 'and|and_eq|bitand|bitor|compl|not|not_eq|or|or_eq|xor|xor_eq|noexcept'
     44   control_keywords: 'break|case|catch|continue|default|do|else|for|goto|if|_Pragma|return|switch|throw|try|while'
     45   memory_operators: 'new|delete'
     46   basic_types: 'asm|__asm__|auto|bool|_Bool|char|_Complex|double|float|_Imaginary|int|long|short|signed|unsigned|void'
     47   before_tag: 'struct|union|enum\s+class|enum\s+struct|enum|class'
     48   declspec: '__declspec\(\s*\w+(?:\([^)]+\))?\s*\)'
     49   storage_classes: 'static|export|extern|friend|explicit|virtual|register|thread_local'
     50   type_qualifier: 'const|constexpr|mutable|typename|volatile'
     51   compiler_directive: 'inline|restrict|__restrict__|__restrict'
     52   visibility_modifiers: 'private|protected|public'
     53   other_keywords: 'typedef|nullptr|{{visibility_modifiers}}|static_assert|sizeof|using|typeid|alignof|alignas|namespace|template'
     54   modifiers: '{{storage_classes}}|{{type_qualifier}}|{{compiler_directive}}'
     55   non_angle_brackets: '(?=<<|<=)'
     56 
     57   regular: '[^(){}&;*^%=<>-]*'
     58   regular_plus: '[^(){}&;*^%=<>-]+'
     59   paren_open: (?:\(
     60   paren_close: '\))?'
     61   generic_open: (?:{{regular_plus}}(?:<
     62   generic_close: '>)?)?'
     63   balance_parentheses: '{{regular}}{{paren_open}}{{regular}}{{paren_close}}{{regular}}'
     64   generic_lookahead: <{{generic_open}}{{generic_open}}{{regular}}{{generic_close}}\s*{{generic_close}}{{balance_parentheses}}>
     65 
     66   data_structures_forward_decl_lookahead: '(\s+{{macro_identifier}})*\s*(:\s*({{path_lookahead}}|{{visibility_modifiers}}|,|\s|<[^;]*>)+)?;'
     67   non_func_keywords: 'if|for|switch|while|decltype|sizeof|__declspec|__attribute__|typeid|alignof|alignas|static_assert'
     68 
     69 contexts:
     70   main:
     71     - include: preprocessor-global
     72     - include: global
     73 
     74   #############################################################################
     75   # Reusable contexts
     76   #
     77   # The follow contexts are currently constructed to be reused in the
     78   # Objetive-C++ syntax. They are specifically constructed to not push into
     79   # sub-contexts, which ensures that Objective-C++ code isn't accidentally
     80   # lexed as plain C++.
     81   #
     82   # The "unique-*" contexts are additions that C++ makes over C, and thus can
     83   # be directly reused in Objective-C++ along with contexts from Objective-C
     84   # and C.
     85   #############################################################################
     86 
     87   unique-late-expressions:
     88     # This is highlighted after all of the other control keywords
     89     # to allow operator overloading to be lexed properly
     90     - match: \boperator\b
     91       scope: keyword.control.c++
     92 
     93   unique-modifiers:
     94     - match: \b({{modifiers}})\b
     95       scope: storage.modifier.c++
     96 
     97   unique-variables:
     98     - match: \bthis\b
     99       scope: variable.language.c++
    100     # common C++ instance var naming idiom -- fMemberName
    101     - match: '\b(f|m)[[:upper:]]\w*\b'
    102       scope: variable.other.readwrite.member.c++
    103     # common C++ instance var naming idiom -- m_member_name
    104     - match: '\bm_[[:alnum:]_]+\b'
    105       scope: variable.other.readwrite.member.c++
    106 
    107   unique-constants:
    108     - match: \bnullptr\b
    109       scope: constant.language.c++
    110 
    111   unique-keywords:
    112     - match: \busing\b
    113       scope: keyword.control.c++
    114     - match: \bbreak\b
    115       scope: keyword.control.flow.break.c++
    116     - match: \bcontinue\b
    117       scope: keyword.control.flow.continue.c++
    118     - match: \bgoto\b
    119       scope: keyword.control.flow.goto.c++
    120     - match: \breturn\b
    121       scope: keyword.control.flow.return.c++
    122     - match: \bthrow\b
    123       scope: keyword.control.flow.throw.c++
    124     - match: \b({{control_keywords}})\b
    125       scope: keyword.control.c++
    126     - match: '\bdelete\b(\s*\[\])?|\bnew\b(?!])'
    127       scope: keyword.control.c++
    128     - match: \b({{operator_keywords}})\b
    129       scope: keyword.operator.word.c++
    130 
    131   unique-types:
    132     - match: \b(char16_t|char32_t|wchar_t|nullptr_t)\b
    133       scope: storage.type.c++
    134     - match: \bclass\b
    135       scope: storage.type.c++
    136 
    137   unique-strings:
    138     - match: '((?:L|u8|u|U)?R)("([^\(\)\\ ]{0,16})\()'
    139       captures:
    140         1: storage.type.string.c++
    141         2: punctuation.definition.string.begin.c++
    142       push:
    143         - meta_scope: string.quoted.double.c++
    144         - match: '\)\3"'
    145           scope: punctuation.definition.string.end.c++
    146           pop: true
    147 
    148   numbers:
    149     # https://en.cppreference.com/w/cpp/language/floating_literal
    150 
    151     # decimal floats
    152     - match: |-
    153         (?x:
    154           \b{{dec_digits}}
    155           (?:
    156             (?:
    157               (\.)
    158               (?:
    159                 # 1.1, 1.1e1, 1.1e-1, 1.1f, 1.1e1f, 1.1e-1f, 1.1L, 1.1e1L, 1.1e-1L
    160                 {{dec_digits}} {{dec_exponent}}?
    161                 # 1.e1, 1.e-1, 1.e1f, 1.e-1f, 1.e1L, 1.e-1L
    162                 | {{dec_exponent}}
    163                 # 1., 1.f, 1.L # but not `..`
    164                 | (?!\.)
    165               )
    166               # 1e1 1e1f 1e1L
    167               | {{dec_exponent}}
    168             ) ({{dec_suffix}})?
    169             # 1f
    170             | ({{float_suffix}})
    171           )
    172           # .1, .1e1, .1e-1, .1f, .1e1f, .1e-1f, .1L, .1e1L, .1e-1L
    173           | (\.) {{dec_digits}} {{dec_exponent}}? ({{dec_suffix}})?
    174         )
    175       scope: constant.numeric.float.decimal.c++
    176       captures:
    177         1: punctuation.separator.decimal.c++
    178         2: storage.type.numeric.c++
    179         3: storage.type.numeric.c++
    180         4: punctuation.separator.decimal.c++
    181         5: storage.type.numeric.c++
    182 
    183     # hexadecimal float (C99)
    184     - match: \b0[xX](?=[[:alnum:]_''.]+?[pP])
    185       scope: punctuation.definition.numeric.base.c++
    186       push:
    187         - meta_include_prototype: false
    188         - meta_scope: constant.numeric.float.hexadecimal.c++
    189         - match: '{{hex_exponent}}'
    190           pop: true
    191         - match: \.
    192           scope: punctuation.separator.decimal.c++
    193         - match: \H
    194           scope: invalid.illegal.numeric.digit.c++
    195 
    196     # https://en.cppreference.com/w/c/language/integer_constant
    197 
    198     # binary integer
    199     - match: \b0[bB]
    200       scope: punctuation.definition.numeric.base.c++
    201       push:
    202         - meta_include_prototype: false
    203         - meta_scope: constant.numeric.integer.binary.c++
    204         - include: decimal-suffix
    205         - match: '[2-9]'
    206           scope: invalid.illegal.numeric.digit.c++
    207     # hexadecimal integer
    208     - match: \b0[xX]
    209       scope: punctuation.definition.numeric.base.c++
    210       push:
    211         - meta_include_prototype: false
    212         - meta_scope: constant.numeric.integer.hexadecimal.c++
    213         - include: hexadecimal-suffix
    214     # octal integer
    215     - match: \b0(?=[\d''])
    216       scope: punctuation.definition.numeric.base.c++
    217       push:
    218         - meta_include_prototype: false
    219         - meta_scope: constant.numeric.integer.octal.c++
    220         - include: decimal-suffix
    221         - match: '[89]'
    222           scope: invalid.illegal.numeric.digit.c++
    223     # decimal integer
    224     - match: \b\d+
    225       push:
    226         - meta_include_prototype: false
    227         - meta_scope: constant.numeric.integer.decimal.c++
    228         - include: decimal-suffix
    229 
    230   decimal-suffix:
    231     - match: '{{dec_suffix}}'
    232       scope: storage.type.numeric.c++
    233       pop: true
    234 
    235   hexadecimal-suffix:
    236     - match: '{{hex_suffix}}'
    237       scope: storage.type.numeric.c++
    238       pop: true
    239 
    240   identifiers:
    241     - match: '(?:(::)\s*)?{{identifier}}\s*(::)\s*'
    242       captures:
    243         1: punctuation.accessor.double-colon.c++
    244         2: punctuation.accessor.double-colon.c++
    245     - match: '(?:(::)\s*)?{{identifier}}'
    246       captures:
    247         1: punctuation.accessor.double-colon.c++
    248 
    249   identifier-path-generic:
    250     - include: angle-brackets
    251     - match: '(?:(::)\s*)?{{identifier}}\s*(?=(<.*>)?\s*(::))\s*'
    252       captures:
    253         1: punctuation.accessor.double-colon.c++
    254         2: punctuation.accessor.double-colon.c++
    255 
    256   function-specifiers:
    257     - match: \b(const|final|noexcept|override)\b
    258       scope: storage.modifier.c++
    259 
    260   #############################################################################
    261   # The following are C++-specific contexts that should not be reused. This is
    262   # because they push into subcontexts and use variables that are C++-specific.
    263   #############################################################################
    264 
    265   ## Common context layout
    266 
    267   global:
    268     - match: '(?=\btemplate\b)'
    269       push:
    270         - include: template
    271         - match: (?=\S)
    272           set: global-modifier
    273     - include: using-namespace
    274     - include: namespace
    275     - include: keywords-angle-brackets
    276     - match: '(?={{path_lookahead}}\s*<)'
    277       push: global-modifier
    278     # Take care of comments just before a function definition.
    279     - match: /\*
    280       scope: punctuation.definition.comment.c
    281       push:
    282         - - match: \s*(?=\w)
    283             set: global-modifier
    284           - match: ""
    285             pop: true
    286         - - meta_scope: comment.block.c
    287           - match: \*/
    288             scope: punctuation.definition.comment.c
    289             pop: true
    290           - match: ^\s*(\*)(?!/)
    291             captures:
    292               1: punctuation.definition.comment.c
    293     - include: early-expressions
    294     - match: ^\s*\b(extern)(?=\s+"C(\+\+)?")
    295       scope: storage.modifier.c++
    296       push:
    297         - include: comments
    298         - include: strings
    299         - match: '\{'
    300           scope: punctuation.section.block.begin.c++
    301           set:
    302             - meta_scope: meta.extern-c.c++
    303             - match: '^\s*(#\s*ifdef)\s*__cplusplus\s*'
    304               scope: meta.preprocessor.c++
    305               captures:
    306                 1: keyword.control.import.c++
    307               set:
    308                 - match: '\}'
    309                   scope: punctuation.section.block.end.c++
    310                   pop: true
    311                 - include: preprocessor-global
    312                 - include: global
    313             - match: '\}'
    314               scope: punctuation.section.block.end.c++
    315               pop: true
    316             - include: preprocessor-global
    317             - include: global
    318         - match: (?=\S)
    319           set: global-modifier
    320     - match: ^\s*(?=\w)
    321       push: global-modifier
    322     - include: late-expressions
    323 
    324   statements:
    325     - include: preprocessor-statements
    326     - include: scope:source.c#label
    327     - include: expressions
    328 
    329   expressions:
    330     - include: early-expressions
    331     - include: late-expressions
    332 
    333   early-expressions:
    334     - include: early-expressions-before-generic-type
    335     - include: generic-type
    336     - include: early-expressions-after-generic-type
    337 
    338   early-expressions-before-generic-type:
    339     - include: preprocessor-expressions
    340     - include: comments
    341     - include: case-default
    342     - include: using-namespace
    343     - include: typedef
    344     - include: using-alias
    345     - include: keywords-angle-brackets
    346     - include: keywords-parens
    347     - include: keywords
    348     - include: numbers
    349     # Prevent a '<' from getting scoped as the start of another template
    350     # parameter list, if in reality a less-than-or-equals sign is meant.
    351     - match: <=
    352       scope: keyword.operator.comparison.c
    353 
    354   early-expressions-after-generic-type:
    355     - include: members-arrow
    356     - include: operators
    357     - include: members-dot
    358     - include: strings
    359     - include: parens
    360     - include: brackets
    361     - include: block
    362     - include: variables
    363     - include: constants
    364     - match: ','
    365       scope: punctuation.separator.c++
    366     - match: '\)|\}'
    367       scope: invalid.illegal.stray-bracket-end.c++
    368 
    369   expressions-minus-generic-type:
    370     - include: early-expressions-before-generic-type
    371     - include: angle-brackets
    372     - include: early-expressions-after-generic-type
    373     - include: late-expressions
    374 
    375   expressions-minus-generic-type-function-call:
    376     - include: early-expressions-before-generic-type
    377     - include: angle-brackets
    378     - include: early-expressions-after-generic-type
    379     - include: late-expressions-before-function-call
    380     - include: identifiers
    381     - match: ';'
    382       scope: punctuation.terminator.c++
    383 
    384   late-expressions:
    385     - include: late-expressions-before-function-call
    386     - include: function-call
    387     - include: identifiers
    388     - match: ';'
    389       scope: punctuation.terminator.c++
    390 
    391   late-expressions-before-function-call:
    392     - include: unique-late-expressions
    393     - include: modifiers-parens
    394     - include: modifiers
    395     - include: types
    396 
    397   expressions-minus-function-call:
    398     - include: early-expressions
    399     - include: late-expressions-before-function-call
    400     - include: identifiers
    401     - match: ';'
    402       scope: punctuation.terminator.c++
    403 
    404   comments:
    405     - include: scope:source.c#comments
    406 
    407   operators:
    408     - include: scope:source.c#operators
    409 
    410   modifiers:
    411     - include: unique-modifiers
    412     - include: scope:source.c#modifiers
    413 
    414   variables:
    415     - include: unique-variables
    416     - include: scope:source.c#variables
    417 
    418   constants:
    419     - include: unique-constants
    420     - include: scope:source.c#constants
    421 
    422   keywords:
    423     - include: unique-keywords
    424     - include: scope:source.c#keywords
    425 
    426   types:
    427     - include: unique-types
    428     - include: types-parens
    429     - include: scope:source.c#types
    430 
    431   strings:
    432     - include: unique-strings
    433     - include: scope:source.c#strings
    434 
    435   ## C++-specific contexts
    436 
    437   case-default:
    438     - match: '\b(default|case)\b'
    439       scope: keyword.control.c++
    440       push:
    441         - match: (?=[);,])
    442           pop: true
    443         - match: ':'
    444           scope: punctuation.separator.c++
    445           pop: true
    446         - include: expressions
    447 
    448   modifiers-parens:
    449     - match: '\b(alignas)\b\s*(\()'
    450       captures:
    451         1: storage.modifier.c++
    452         2: meta.group.c++ punctuation.section.group.begin.c++
    453       push:
    454         - meta_content_scope: meta.group.c++
    455         - match: '\)'
    456           scope: meta.group.c++ punctuation.section.group.end.c++
    457           pop: true
    458         - include: expressions
    459     - match: \b(__attribute__)\s*(\(\()
    460       captures:
    461         1: storage.modifier.c++
    462         2: meta.group.c++ punctuation.section.group.begin.c++
    463       push :
    464         - meta_scope: meta.attribute.c++
    465         - meta_content_scope: meta.group.c++
    466         - include: parens
    467         - include: strings
    468         - match: \)\)
    469           scope: meta.group.c++ punctuation.section.group.end.c++
    470           pop: true
    471     - match: \b(__declspec)(\()
    472       captures:
    473         1: storage.modifier.c++
    474         2: meta.group.c++ punctuation.section.group.begin.c++
    475       push:
    476         - meta_content_scope: meta.group.c++
    477         - match: '\)'
    478           scope: meta.group.c++ punctuation.section.group.end.c++
    479           pop: true
    480         - match: '\b(align|allocate|code_seg|deprecated|property|uuid)\b\s*(\()'
    481           captures:
    482             1: storage.modifier.c++
    483             2: meta.group.c++ punctuation.section.group.begin.c++
    484           push:
    485             - meta_content_scope: meta.group.c++
    486             - match: '\)'
    487               scope: meta.group.c++ punctuation.section.group.end.c++
    488               pop: true
    489             - include: numbers
    490             - include: strings
    491             - match: \b(get|put)\b
    492               scope: variable.parameter.c++
    493             - match: ','
    494               scope: punctuation.separator.c++
    495             - match: '='
    496               scope: keyword.operator.assignment.c++
    497         - match: '\b(appdomain|deprecated|dllimport|dllexport|jintrinsic|naked|noalias|noinline|noreturn|nothrow|novtable|process|restrict|safebuffers|selectany|thread)\b'
    498           scope: constant.other.c++
    499 
    500   types-parens:
    501     - match: '\b(decltype)\b\s*(\()'
    502       captures:
    503         1: storage.type.c++
    504         2: meta.group.c++ punctuation.section.group.begin.c++
    505       push:
    506         - meta_content_scope: meta.group.c++
    507         - match: '\)'
    508           scope: meta.group.c++ punctuation.section.group.end.c++
    509           pop: true
    510         - include: expressions
    511 
    512   keywords-angle-brackets:
    513     - match: \b({{casts}})\b\s*
    514       scope: keyword.operator.word.cast.c++
    515       push:
    516         - match: '>'
    517           scope: punctuation.section.generic.end.c++
    518           pop: true
    519         - match: '<'
    520           scope: punctuation.section.generic.begin.c++
    521           push:
    522             - match: '(?=>)'
    523               pop: true
    524             - include: expressions-minus-generic-type-function-call
    525 
    526   keywords-parens:
    527     - match: '\b(alignof|typeid|static_assert|sizeof)\b\s*(\()'
    528       captures:
    529         1: keyword.operator.word.c++
    530         2: meta.group.c++ punctuation.section.group.begin.c++
    531       push:
    532         - meta_content_scope: meta.group.c++
    533         - match: '\)'
    534           scope: meta.group.c++ punctuation.section.group.end.c++
    535           pop: true
    536         - include: expressions
    537 
    538   using-namespace:
    539     - match: '\b(using)\s+(namespace)\b'
    540       captures:
    541         1: keyword.control.c++
    542         2: keyword.control.c++
    543       push:
    544         - include: identifiers
    545         - match: ''
    546           pop: true
    547 
    548   namespace:
    549     - match: '\b(namespace)\s+(?=({{path_lookahead}})?(?!\s*[;,]))'
    550       scope: meta.namespace.c++
    551       captures:
    552         1: keyword.control.c++
    553       push:
    554         - meta_content_scope: meta.namespace.c++ entity.name.namespace.c++
    555         - include: identifiers
    556         - match: ''
    557           set:
    558             - meta_scope: meta.namespace.c++
    559             - include: comments
    560             - match: '='
    561               scope: keyword.operator.alias.c++
    562             - match: '(?=;)'
    563               pop: true
    564             - match: '\}'
    565               scope: meta.block.c++ punctuation.section.block.end.c++
    566               pop: true
    567             - match: '\{'
    568               scope: punctuation.section.block.begin.c++
    569               push:
    570                 - meta_scope: meta.block.c++
    571                 - match: '(?=\})'
    572                   pop: true
    573                 - include: preprocessor-global
    574                 - include: global
    575             - include: expressions
    576 
    577   template-common:
    578     # Exit the template scope if we hit some basic invalid characters. This
    579     # helps when a user is in the middle of typing their template types and
    580     # prevents re-highlighting the whole file until the next > is found.
    581     - match: (?=[{};])
    582       pop: true
    583     - include: expressions
    584 
    585   template:
    586     - match: \btemplate\b
    587       scope: storage.type.template.c++
    588       push:
    589         - meta_scope: meta.template.c++
    590         # Explicitly include comments here at the top, in order to NOT match the
    591         # \S lookahead in the case of comments.
    592         - include: comments
    593         - match: <
    594           scope: punctuation.section.generic.begin.c++
    595           set:
    596             - meta_content_scope: meta.template.c++
    597             - match: '>'
    598               scope: meta.template.c++ punctuation.section.generic.end.c++
    599               pop: true
    600             - match: \.{3}
    601               scope: keyword.operator.variadic.c++
    602             - match: \b(typename|{{before_tag}})\b
    603               scope: storage.type.c++
    604             - include: template # include template here for nested templates
    605             - include: template-common
    606         - match: (?=\S)
    607           set:
    608             - meta_content_scope: meta.template.c++
    609             - match: \b({{before_tag}})\b
    610               scope: storage.type.c++
    611             - include: template-common
    612 
    613   generic-type:
    614     - match: '(?=(?!template){{path_lookahead}}\s*{{generic_lookahead}}\s*(\(|\{))'
    615       push:
    616         - meta_scope: meta.function-call.c++
    617         - match: \btemplate\b
    618           scope: storage.type.template.c++
    619         - match: (?:(::)\s*)?({{identifier}})\s*(<)
    620           captures:
    621             1: punctuation.accessor.double-colon.c++
    622             2: variable.function.c++
    623             3: punctuation.section.generic.begin.c++
    624           push:
    625             - match: '>'
    626               scope: punctuation.section.generic.end.c++
    627               pop: true
    628             - include: expressions-minus-generic-type-function-call
    629         - match: (?:(::)\s*)?({{identifier}})\s*(\()
    630           captures:
    631             1: punctuation.accessor.double-colon.c++
    632             2: variable.function.c++
    633             3: punctuation.section.group.begin.c++
    634           set:
    635             - meta_scope: meta.function-call.c++
    636             - meta_content_scope: meta.group.c++
    637             - match: '\)'
    638               scope: meta.group.c++ punctuation.section.group.end.c++
    639               pop: true
    640             - include: expressions
    641         - match: (?:(::)\s*)?({{identifier}})\s*(\{)
    642           captures:
    643             1: punctuation.accessor.double-colon.c++
    644             2: variable.function.c++
    645             3: punctuation.section.group.begin.c++
    646           set:
    647             - meta_scope: meta.function-call.c++
    648             - meta_content_scope: meta.group.c++
    649             - match: '\}'
    650               scope: meta.group.c++ punctuation.section.group.end.c++
    651               pop: true
    652             - include: expressions
    653         - include: identifiers
    654         - include: angle-brackets
    655         - match: '\('
    656           scope: meta.group.c++ punctuation.section.group.begin.c++
    657           set:
    658             - meta_scope: meta.function-call.c++
    659             - meta_content_scope: meta.group.c++
    660             - match: '\)'
    661               scope: meta.group.c++ punctuation.section.group.end.c++
    662               pop: true
    663             - include: expressions
    664         - match: '\{'
    665           scope: meta.group.c++ punctuation.section.group.begin.c++
    666           set:
    667             - meta_scope: meta.function-call.c++
    668             - meta_content_scope: meta.group.c++
    669             - match: '\}'
    670               scope: meta.group.c++ punctuation.section.group.end.c++
    671               pop: true
    672             - include: expressions
    673     - match: '(?=(?!template){{path_lookahead}}\s*{{generic_lookahead}})'
    674       push:
    675         - include: identifiers
    676         - match: '<'
    677           scope: punctuation.section.generic.begin.c++
    678           set:
    679             - match: '>'
    680               scope: punctuation.section.generic.end.c++
    681               pop: true
    682             - include: expressions-minus-generic-type-function-call
    683 
    684   angle-brackets:
    685     - match: '<(?!<)'
    686       scope: punctuation.section.generic.begin.c++
    687       push:
    688         - match: '>'
    689           scope: punctuation.section.generic.end.c++
    690           pop: true
    691         - include: expressions-minus-generic-type-function-call
    692 
    693   block:
    694     - match: '\{'
    695       scope: punctuation.section.block.begin.c++
    696       push:
    697         - meta_scope: meta.block.c++
    698         - match: (?=^\s*#\s*(elif|else|endif)\b)
    699           pop: true
    700         - match: '\}'
    701           scope: punctuation.section.block.end.c++
    702           pop: true
    703         - include: statements
    704 
    705   function-call:
    706     - match: (?={{path_lookahead}}\s*(\(|\{))
    707       push:
    708         - meta_scope: meta.function-call.c++
    709         - include: scope:source.c#c99
    710         - match: '(?:(::)\s*)?{{identifier}}\s*(::)\s*'
    711           captures:
    712             1: punctuation.accessor.double-colon.c++
    713             2: punctuation.accessor.double-colon.c++
    714         - match: '(?:(::)\s*)?({{identifier}})'
    715           captures:
    716             1: punctuation.accessor.c++
    717             2: variable.function.c++
    718         - match: '\('
    719           scope: meta.group.c++ punctuation.section.group.begin.c++
    720           set:
    721             - meta_content_scope: meta.function-call.c++ meta.group.c++
    722             - match: '\)'
    723               scope: meta.function-call.c++ meta.group.c++ punctuation.section.group.end.c++
    724               pop: true
    725             - include: expressions
    726         - match: '\{'
    727           scope: meta.group.c++ punctuation.section.group.begin.c++
    728           set:
    729             - meta_content_scope: meta.function-call.c++ meta.group.c++
    730             - match: '\}'
    731               scope: meta.function-call.c++ meta.group.c++ punctuation.section.group.end.c++
    732               pop: true
    733             - include: expressions
    734 
    735   members-inside-function-call:
    736     - meta_content_scope: meta.method-call.c++ meta.group.c++
    737     - match: \)
    738       scope: meta.method-call.c++ meta.group.c++ punctuation.section.group.end.c++
    739       pop: true
    740     - include: expressions
    741 
    742   members-after-accessor-junction:
    743     # After we've seen an accessor (dot or arrow), this context decides what
    744     # kind of entity we're accessing.
    745     - include: comments
    746     - match: \btemplate\b
    747       scope: meta.method-call.c++ storage.type.template.c++
    748       # Guaranteed to be a template member function call after we match this
    749       set:
    750         - meta_content_scope: meta.method-call.c++
    751         - include: comments
    752         - match: '{{identifier}}'
    753           scope: variable.function.member.c++
    754           set:
    755             - meta_content_scope: meta.method-call.c++
    756             - match: \(
    757               scope: meta.group.c++ punctuation.section.group.begin.c++
    758               set: members-inside-function-call
    759             - include: comments
    760             - include: angle-brackets
    761             - match: (?=\S) # safety pop
    762               pop: true
    763         - match: (?=\S) # safety pop
    764           pop: true
    765     # Operator overloading
    766     - match: '({{operator_method_name}})\s*(\()'
    767       captures:
    768         0: meta.method-call.c++
    769         1: variable.function.member.c++
    770         2: meta.group.c++ punctuation.section.group.begin.c++
    771       set: members-inside-function-call
    772     # Non-templated member function call
    773     - match: (~?{{identifier}})\s*(\()
    774       captures:
    775         0: meta.method-call.c++
    776         1: variable.function.member.c++
    777         2: meta.group.c++ punctuation.section.group.begin.c++
    778       set: members-inside-function-call
    779     # Templated member function call
    780     - match: (~?{{identifier}})\s*(?={{generic_lookahead}})
    781       captures:
    782         1: variable.function.member.c++
    783       set:
    784         - meta_scope: meta.method-call.c++
    785         - match: <
    786           scope: punctuation.section.generic.begin.c++
    787           set:
    788             - meta_content_scope: meta.method-call.c++
    789             - match: '>'
    790               scope: punctuation.section.generic.end.c++
    791               set:
    792                 - meta_content_scope: meta.method-call.c++
    793                 - include: comments
    794                 - match: \(
    795                   scope: punctuation.section.group.begin.c++
    796                   set: members-inside-function-call
    797                 - match: (?=\S) # safety pop
    798                   pop: true
    799             - include: expressions
    800     # Explicit base-class access
    801     - match: ({{identifier}})\s*(::)
    802       captures:
    803         1: variable.other.base-class.c++
    804         2: punctuation.accessor.double-colon.c++
    805       set: members-after-accessor-junction # reset
    806     # Just a regular member variable
    807     - match: '{{identifier}}'
    808       scope: variable.other.readwrite.member.c++
    809       pop: true
    810 
    811   members-dot:
    812     - include: scope:source.c#access-illegal
    813     # No lookahead required because members-dot goes after operators in the
    814     # early-expressions-after-generic-type context. This means triple dots
    815     # (i.e. "..." or "variadic") is attempted first.
    816     - match: \.
    817       scope: punctuation.accessor.dot.c++
    818       push: members-after-accessor-junction
    819 
    820   members-arrow:
    821     # This needs to be before operators in the
    822     # early-expressions-after-generic-type context because otherwise the "->"
    823     # from the C language will match.
    824     - match: ->
    825       scope: punctuation.accessor.arrow.c++
    826       push: members-after-accessor-junction
    827 
    828   using-alias:
    829     # consume keyword if followed by typename
    830     - match: '\b(using)\b(?=\s+typename\b)'
    831       captures:
    832         1: keyword.control.c++
    833     - match: '\b(using)\b\s+({{identifier}})(?!\s*(<|::))'
    834       captures:
    835         1: keyword.control.c++
    836         2: entity.name.type.using.c++
    837 
    838   typedef:
    839     - match: \btypedef\b
    840       scope: storage.type.c++
    841       push:
    842         - match: ({{identifier}})?\s*(?=;)
    843           captures:
    844             1: entity.name.type.typedef.c++
    845           pop: true
    846         - match: \b(struct)\s+({{identifier}})\b
    847           captures:
    848             1: storage.type.c++
    849         - include: expressions-minus-generic-type
    850 
    851   parens:
    852     - match: \(
    853       scope: punctuation.section.group.begin.c++
    854       push:
    855         - meta_scope: meta.group.c++
    856         - match: \)
    857           scope: punctuation.section.group.end.c++
    858           pop: true
    859         - include: expressions
    860 
    861   brackets:
    862     - match: \[
    863       scope: punctuation.section.brackets.begin.c++
    864       push:
    865         - meta_scope: meta.brackets.c++
    866         - match: \]
    867           scope: punctuation.section.brackets.end.c++
    868           pop: true
    869         - include: expressions
    870 
    871   function-trailing-return-type:
    872     - match: '{{non_angle_brackets}}'
    873       pop: true
    874     - include: angle-brackets
    875     - include: types
    876     - include: modifiers-parens
    877     - include: modifiers
    878     - include: identifiers
    879     - match: \*|&
    880       scope: keyword.operator.c++
    881     - include: function-trailing-return-type-parens
    882     - match: '(?=\S)'
    883       pop: true
    884 
    885   function-trailing-return-type-parens:
    886     - match: \(
    887       scope: punctuation.section.group.begin.c++
    888       push:
    889         - meta_scope: meta.group.c++
    890         - match: \)
    891           scope: punctuation.section.group.end.c++
    892           pop: true
    893         - include: function-trailing-return-type
    894 
    895   ## Detection of function and data structure definitions at the global level
    896 
    897   global-modifier:
    898     - include: comments
    899     - include: modifiers-parens
    900     - include: modifiers
    901     # Constructors and destructors don't have a type
    902     - match: '(?={{path_lookahead}}\s*(?:{{generic_lookahead}})?\s*::\s*{{identifier}}\s*\()'
    903       set:
    904         - meta_content_scope: meta.function.c++ meta.toc-list.full-identifier.c++
    905         - include: identifier-path-generic
    906         - match: '(?:(::)\s*)?({{identifier}})'
    907           captures:
    908             1: punctuation.accessor.double-colon.c++
    909             2: entity.name.function.constructor.c++
    910         - match: '(?=[^\w\s])'
    911           set: function-definition-params
    912     - match: '(?={{path_lookahead}}\s*(?:{{generic_lookahead}})?\s*::\s*~{{identifier}}\s*(\(|$))'
    913       set:
    914         - meta_content_scope: meta.function.c++ meta.toc-list.full-identifier.c++
    915         - include: identifier-path-generic
    916         - match: '(?:(::)\s*)?(~{{identifier}})'
    917           captures:
    918             1: punctuation.accessor.double-colon.c++
    919             2: entity.name.function.destructor.c++
    920         - match: '(?=[^\w\s])'
    921           set: function-definition-params
    922     # If we see a path ending in :: before a newline, we don't know if it is
    923     # a constructor or destructor, or a long return type, so we are just going
    924     # to treat it like a regular function. Most likely it is a constructor,
    925     # since it doesn't seem most developers would create such a long typename.
    926     - match: '(?={{path_lookahead}}\s*(?:{{generic_lookahead}})?::\s*$)'
    927       set:
    928         - meta_content_scope: meta.function.c++ meta.toc-list.full-identifier.c++
    929         - include: identifier-path-generic
    930         - match: '(::)\s*$'
    931           captures:
    932             1: punctuation.accessor.double-colon.c++
    933         - match: '(?:(::)\s*)?(~?{{identifier}})(?=\s*\()'
    934           captures:
    935             1: punctuation.accessor.double-colon.c++
    936             2: entity.name.function.c++
    937         - match: '(?=[^\w\s])'
    938           set: function-definition-params
    939     - include: unique-strings
    940     - match: '(?=\S)'
    941       set: global-type
    942 
    943   global-type:
    944     - include: comments
    945     - match: \*|&
    946       scope: keyword.operator.c++
    947     - match: '(?=\b({{control_keywords}}|{{operator_keywords}}|{{casts}}|{{memory_operators}}|{{other_keywords}}|operator)\b)'
    948       pop: true
    949     - match: '(?=\s)'
    950       set: global-maybe-function
    951     # If a class/struct/enum followed by a name that is not a macro or declspec
    952     # then this is likely a return type of a function. This is uncommon.
    953     - match: |-
    954         (?x:
    955           ({{before_tag}})
    956           \s+
    957           (?=
    958             (?![[:upper:][:digit:]_]+\b|__declspec|{{before_tag}})
    959             {{path_lookahead}}
    960             (\s+{{identifier}}\s*\(|\s*[*&])
    961           )
    962         )
    963       captures:
    964         1: storage.type.c++
    965       set:
    966         - include: identifiers
    967         - match: ''
    968           set: global-maybe-function
    969     # The previous match handles return types of struct/enum/etc from a func,
    970     # there this one exits the context to allow matching an actual struct/class
    971     - match: '(?=\b({{before_tag}})\b)'
    972       set: data-structures
    973     - match: '(?=\b({{casts}})\b\s*<)'
    974       pop: true
    975     - match: '{{non_angle_brackets}}'
    976       pop: true
    977     - include: angle-brackets
    978     - include: types
    979     # Allow a macro call
    980     - match: '({{identifier}})\s*(\()(?=[^\)]+\))'
    981       captures:
    982         1: variable.function.c++
    983         2: meta.group.c++ punctuation.section.group.begin.c++
    984       push:
    985         - meta_scope: meta.function-call.c++
    986         - meta_content_scope: meta.group.c++
    987         - match: '\)'
    988           scope: meta.group.c++ punctuation.section.group.end.c++
    989           pop: true
    990         - include: expressions
    991     - match: '(?={{path_lookahead}}\s*\()'
    992       set:
    993         - include: function-call
    994         - match: ''
    995           pop: true
    996     - include: variables
    997     - include: constants
    998     - include: identifiers
    999     - match: (?=\W)
   1000       pop: true
   1001 
   1002   global-maybe-function:
   1003     - include: comments
   1004     # Consume pointer info, macros and any type info that was offset by macros
   1005     - match: \*|&
   1006       scope: keyword.operator.c++
   1007     - match: '(?=\b({{control_keywords}}|{{operator_keywords}}|{{casts}}|{{memory_operators}}|{{other_keywords}})\b)'
   1008       pop: true
   1009     - match: '\b({{type_qualifier}})\b'
   1010       scope: storage.modifier.c++
   1011     - match: '{{non_angle_brackets}}'
   1012       pop: true
   1013     - include: angle-brackets
   1014     - include: types
   1015     - include: modifiers-parens
   1016     - include: modifiers
   1017     # All uppercase identifier just before a newline is most likely a macro
   1018     - match: '[[:upper:][:digit:]_]+\s*$'
   1019     # Operator overloading
   1020     - match: '(?=({{path_lookahead}}\s*(?:{{generic_lookahead}})?::\s*)?{{operator_method_name}}\s*(\(|$))'
   1021       set:
   1022         - meta_content_scope: meta.function.c++ meta.toc-list.full-identifier.c++
   1023         - include: identifier-path-generic
   1024         - match: '(?:(::)\s*)?({{operator_method_name}})(?=\s*\()'
   1025           captures:
   1026             1: punctuation.accessor.double-colon.c++
   1027             2: entity.name.function.c++
   1028         - match: '(?=\s*(\(|$))'
   1029           set: function-definition-params
   1030     # Identifier that is not the function name - likely a macro or type
   1031     - match: '(?={{path_lookahead}}([ \t]+|[*&])(?!\s*(<|::|\(|$)))'
   1032       push:
   1033         - include: identifiers
   1034         - match: ''
   1035           pop: true
   1036     # Real function definition
   1037     - match: '(?={{path_lookahead}}({{generic_lookahead}}({{path_lookahead}})?)\s*(\(|$))'
   1038       set: [function-definition-params, global-function-identifier-generic]
   1039     - match: '(?={{path_lookahead}}\s*(\(|$))'
   1040       set: [function-definition-params, global-function-identifier]
   1041     - match: '(?={{path_lookahead}}\s*::\s*$)'
   1042       set: [function-definition-params, global-function-identifier]
   1043     - match: '(?=\S)'
   1044       pop: true
   1045 
   1046   global-function-identifier-generic:
   1047     - meta_content_scope: meta.toc-list.full-identifier.c++
   1048     - include: identifier-path-generic
   1049     - match: '(?:(::)\s*)?({{identifier}})(?=\s*(<.*>)?\s*\()'
   1050       captures:
   1051         1: punctuation.accessor.double-colon.c++
   1052         2: entity.name.function.c++
   1053     - match: '(?=\()'
   1054       pop: true
   1055 
   1056   global-function-identifier:
   1057     - meta_content_scope: meta.toc-list.full-identifier.c++
   1058     - match: '(?:(::)\s*)?({{identifier}})(?!\s*(::))'
   1059       captures:
   1060         1: punctuation.accessor.double-colon.c++
   1061         2: entity.name.function.c++
   1062     - include: identifiers
   1063     - match: '(?=\S)'
   1064       pop: true
   1065 
   1066   function-definition-params:
   1067     - meta_content_scope: meta.function.c++
   1068     - include: comments
   1069     - match: '(?=\()'
   1070       set:
   1071         - match: \(
   1072           scope: meta.function.parameters.c++ meta.group.c++ punctuation.section.group.begin.c++
   1073           set:
   1074             - meta_content_scope: meta.function.parameters.c++ meta.group.c++
   1075             - match : \)
   1076               scope: punctuation.section.group.end.c++
   1077               set: function-definition-continue
   1078             - match: '\bvoid\b'
   1079               scope: storage.type.c++
   1080             - match: '{{identifier}}(?=\s*(\[|,|\)|=))'
   1081               scope: variable.parameter.c++
   1082             - match: '='
   1083               scope: keyword.operator.assignment.c++
   1084               push:
   1085                 - match: '(?=,|\))'
   1086                   pop: true
   1087                 - include: expressions-minus-generic-type
   1088                 - include: scope:source.c#preprocessor-line-continuation
   1089             - include: expressions-minus-generic-type
   1090             - include: scope:source.c#preprocessor-line-continuation
   1091     - match: (?=\S)
   1092       pop: true
   1093 
   1094   function-definition-continue:
   1095     - meta_content_scope: meta.function.c++
   1096     - include: comments
   1097     - match: '(?=;)'
   1098       pop: true
   1099     - match: '->'
   1100       scope: punctuation.separator.c++
   1101       set: function-definition-trailing-return
   1102     - include: function-specifiers
   1103     - match: '='
   1104       scope: keyword.operator.assignment.c++
   1105     - match: '&'
   1106       scope: keyword.operator.c++
   1107     - match: \b0\b
   1108       scope: constant.numeric.integer.decimal.c++
   1109     - match: \b(default|delete)\b
   1110       scope: storage.modifier.c++
   1111     - match: '(?=\{)'
   1112       set: function-definition-body
   1113     - match: '(?=\S)'
   1114       pop: true
   1115 
   1116   function-definition-trailing-return:
   1117     - include: comments
   1118     - match: '(?=;)'
   1119       pop: true
   1120     - match: '(?=\{)'
   1121       set: function-definition-body
   1122     - include: function-specifiers
   1123     - include: function-trailing-return-type
   1124 
   1125   function-definition-body:
   1126     - meta_content_scope: meta.function.c++ meta.block.c++
   1127     - match: '\{'
   1128       scope: punctuation.section.block.begin.c++
   1129       set:
   1130         - meta_content_scope: meta.function.c++ meta.block.c++
   1131         - match: '\}'
   1132           scope: meta.function.c++ meta.block.c++ punctuation.section.block.end.c++
   1133           pop: true
   1134         - match: (?=^\s*#\s*(elif|else|endif)\b)
   1135           pop: true
   1136         - match: '(?=({{before_tag}})([^(;]+$|.*\{))'
   1137           push: data-structures
   1138         - include: statements
   1139 
   1140   ## Data structures including classes, structs, unions and enums
   1141 
   1142   data-structures:
   1143     - match: '\bclass\b'
   1144       scope: storage.type.c++
   1145       set: data-structures-class-definition
   1146     # Detect variable type definitions using struct/enum/union followed by a tag
   1147     - match: '\b({{before_tag}})(?=\s+{{path_lookahead}}\s+{{path_lookahead}}\s*[=;\[])'
   1148       scope: storage.type.c++
   1149     - match: '\bstruct\b'
   1150       scope: storage.type.c++
   1151       set: data-structures-struct-definition
   1152     - match: '\benum(\s+(class|struct))?\b'
   1153       scope: storage.type.c++
   1154       set: data-structures-enum-definition
   1155     - match: '\bunion\b'
   1156       scope: storage.type.c++
   1157       set: data-structures-union-definition
   1158     - match: '(?=\S)'
   1159       pop: true
   1160 
   1161   preprocessor-workaround-eat-macro-before-identifier:
   1162     # Handle macros so they aren't matched as the class name
   1163     - match: ({{macro_identifier}})(?=\s+~?{{identifier}})
   1164       captures:
   1165         1: meta.assumed-macro.c
   1166 
   1167   data-structures-class-definition:
   1168     - meta_scope: meta.class.c++
   1169     - include: data-structures-definition-common-begin
   1170     - match: '{{identifier}}(?={{data_structures_forward_decl_lookahead}})'
   1171       scope: entity.name.class.forward-decl.c++
   1172       set: data-structures-class-definition-after-identifier
   1173     - match: '(?={{path_lookahead}})'
   1174       set:
   1175         - meta_scope: meta.class.c++
   1176         - match: '{{identifier}}(?!\s*::)'
   1177           scope: entity.name.class.c++
   1178           set: data-structures-class-definition-after-identifier
   1179         - include: identifiers
   1180         - match: '(?=[^\w\s])'
   1181           set: data-structures-class-definition-after-identifier
   1182     - match: '(?=[:{])'
   1183       set: data-structures-class-definition-after-identifier
   1184     - match: '(?=;)'
   1185       pop: true
   1186 
   1187   data-structures-class-definition-after-identifier:
   1188     - meta_content_scope: meta.class.c++
   1189     - include: data-structures-definition-common-begin
   1190     # No matching of identifiers since they should all be macros at this point
   1191     - include: data-structures-definition-common-end
   1192     - match: '\{'
   1193       scope: meta.block.c++ punctuation.section.block.begin.c++
   1194       set:
   1195         - meta_content_scope: meta.class.c++ meta.block.c++
   1196         - match: '\}'
   1197           scope: meta.class.c++ meta.block.c++ punctuation.section.block.end.c++
   1198           pop: true
   1199         - include: data-structures-body
   1200 
   1201   data-structures-struct-definition:
   1202     - meta_scope: meta.struct.c++
   1203     - include: data-structures-definition-common-begin
   1204     - match: '{{identifier}}(?={{data_structures_forward_decl_lookahead}})'
   1205       scope: entity.name.struct.forward-decl.c++
   1206       set: data-structures-struct-definition-after-identifier
   1207     - match: '(?={{path_lookahead}})'
   1208       set:
   1209         - meta_scope: meta.struct.c++
   1210         - match: '{{identifier}}(?!\s*::)'
   1211           scope: entity.name.struct.c++
   1212           set: data-structures-struct-definition-after-identifier
   1213         - include: identifiers
   1214         - match: '(?=[^\w\s])'
   1215           set: data-structures-struct-definition-after-identifier
   1216     - match: '(?=[:{])'
   1217       set: data-structures-struct-definition-after-identifier
   1218     - match: '(?=;)'
   1219       pop: true
   1220 
   1221   data-structures-struct-definition-after-identifier:
   1222     - meta_content_scope: meta.struct.c++
   1223     - include: data-structures-definition-common-begin
   1224     # No matching of identifiers since they should all be macros at this point
   1225     - include: data-structures-definition-common-end
   1226     - match: '\{'
   1227       scope: meta.block.c++ punctuation.section.block.begin.c++
   1228       set:
   1229         - meta_content_scope: meta.struct.c++ meta.block.c++
   1230         - match: '\}'
   1231           scope: meta.struct.c++ meta.block.c++ punctuation.section.block.end.c++
   1232           pop: true
   1233         - include: data-structures-body
   1234 
   1235   data-structures-enum-definition:
   1236     - meta_scope: meta.enum.c++
   1237     - include: data-structures-definition-common-begin
   1238     - match: '{{identifier}}(?={{data_structures_forward_decl_lookahead}})'
   1239       scope: entity.name.enum.forward-decl.c++
   1240       set: data-structures-enum-definition-after-identifier
   1241     - match: '(?={{path_lookahead}})'
   1242       set:
   1243         - meta_scope: meta.enum.c++
   1244         - match: '{{identifier}}(?!\s*::)'
   1245           scope: entity.name.enum.c++
   1246           set: data-structures-enum-definition-after-identifier
   1247         - include: identifiers
   1248         - match: '(?=[^\w\s])'
   1249           set: data-structures-enum-definition-after-identifier
   1250     - match: '(?=[:{])'
   1251       set: data-structures-enum-definition-after-identifier
   1252     - match: '(?=;)'
   1253       pop: true
   1254 
   1255   data-structures-enum-definition-after-identifier:
   1256     - meta_content_scope: meta.enum.c++
   1257     - include: data-structures-definition-common-begin
   1258     # No matching of identifiers since they should all be macros at this point
   1259     - include: data-structures-definition-common-end
   1260     - match: '\{'
   1261       scope: meta.block.c++ punctuation.section.block.begin.c++
   1262       set:
   1263         - meta_content_scope: meta.enum.c++ meta.block.c++
   1264         # Enums don't support methods so we have a simplified body
   1265         - match: '\}'
   1266           scope: meta.enum.c++ meta.block.c++ punctuation.section.block.end.c++
   1267           pop: true
   1268         - include: statements
   1269 
   1270   data-structures-union-definition:
   1271     - meta_scope: meta.union.c++
   1272     - include: data-structures-definition-common-begin
   1273     - match: '{{identifier}}(?={{data_structures_forward_decl_lookahead}})'
   1274       scope: entity.name.union.forward-decl.c++
   1275       set: data-structures-union-definition-after-identifier
   1276     - match: '(?={{path_lookahead}})'
   1277       set:
   1278         - meta_scope: meta.union.c++
   1279         - match: '{{identifier}}(?!\s*::)'
   1280           scope: entity.name.union.c++
   1281           set: data-structures-union-definition-after-identifier
   1282         - include: identifiers
   1283         - match: '(?=[^\w\s])'
   1284           set: data-structures-union-definition-after-identifier
   1285     - match: '(?=[{])'
   1286       set: data-structures-union-definition-after-identifier
   1287     - match: '(?=;)'
   1288       pop: true
   1289 
   1290   data-structures-union-definition-after-identifier:
   1291     - meta_content_scope: meta.union.c++
   1292     - include: data-structures-definition-common-begin
   1293     # No matching of identifiers since they should all be macros at this point
   1294     # Unions don't support base classes
   1295     - include: angle-brackets
   1296     - match: '\{'
   1297       scope: meta.block.c++ punctuation.section.block.begin.c++
   1298       set:
   1299         - meta_content_scope: meta.union.c++ meta.block.c++
   1300         - match: '\}'
   1301           scope: meta.union.c++ meta.block.c++ punctuation.section.block.end.c++
   1302           pop: true
   1303         - include: data-structures-body
   1304     - match: '(?=;)'
   1305       pop: true
   1306 
   1307   data-structures-definition-common-begin:
   1308     - include: comments
   1309     - match: '(?=\b(?:{{before_tag}}|{{control_keywords}})\b)'
   1310       pop: true
   1311     - include: preprocessor-other
   1312     - include: modifiers-parens
   1313     - include: modifiers
   1314     - include: preprocessor-workaround-eat-macro-before-identifier
   1315 
   1316   data-structures-definition-common-end:
   1317     - include: angle-brackets
   1318     - match: \bfinal\b
   1319       scope: storage.modifier.c++
   1320     - match: ':'
   1321       scope: punctuation.separator.c++
   1322       push:
   1323         - include: comments
   1324         - include: preprocessor-other
   1325         - include: modifiers-parens
   1326         - include: modifiers
   1327         - match: '\b(virtual|{{visibility_modifiers}})\b'
   1328           scope: storage.modifier.c++
   1329         - match: (?={{path_lookahead}})
   1330           push:
   1331             - meta_scope: entity.other.inherited-class.c++
   1332             - include: identifiers
   1333             - match: ''
   1334               pop: true
   1335         - include: angle-brackets
   1336         - match: ','
   1337           scope: punctuation.separator.c++
   1338         - match: (?=\{|;)
   1339           pop: true
   1340     - match: '(?=;)'
   1341       pop: true
   1342 
   1343   data-structures-body:
   1344     - include: preprocessor-data-structures
   1345     - match: '(?=\btemplate\b)'
   1346       push:
   1347         - include: template
   1348         - match: (?=\S)
   1349           set: data-structures-modifier
   1350     - include: using-namespace
   1351     - include: typedef
   1352     - include: using-alias
   1353     - match: \b({{visibility_modifiers}})\s*(:)(?!:)
   1354       captures:
   1355         1: storage.modifier.c++
   1356         2: punctuation.section.class.c++
   1357     - match: '^\s*(?=(?:~?\w+|::))'
   1358       push: data-structures-modifier
   1359     - include: expressions-minus-generic-type
   1360 
   1361   data-structures-modifier-friend:
   1362     - match: (?=;)
   1363       pop: true
   1364     - match: '\{'
   1365       scope: punctuation.section.block.begin.c++
   1366       set:
   1367         - meta_scope: meta.block.c++
   1368         - match: '\}'
   1369           scope: punctuation.section.block.end.c++
   1370           pop: true
   1371         - include: statements
   1372     - include: expressions-minus-function-call
   1373 
   1374   data-structures-modifier:
   1375     - match: '\bfriend\b'
   1376       scope: storage.modifier.c++
   1377       push:
   1378         - include: comments
   1379         - match: '\b({{before_tag}})\b'
   1380           scope: storage.type.c++
   1381           set: data-structures-modifier-friend
   1382         - match: '(?=\S)(?=[^;]+;)'
   1383           set: data-structures-modifier-friend
   1384         - match: '(?=\S)'
   1385           pop: true
   1386     - include: comments
   1387     - include: modifiers-parens
   1388     - include: modifiers
   1389     - match: '\bstatic_assert(?=\s*\()'
   1390       scope: meta.static-assert.c++ keyword.operator.word.c++
   1391       push:
   1392         - match: '\('
   1393           scope: meta.group.c++ punctuation.section.group.begin.c++
   1394           set:
   1395             - meta_content_scope: meta.function-call.c++ meta.group.c++
   1396             - match: '\)'
   1397               scope: meta.function-call.c++ meta.group.c++ punctuation.section.group.end.c++
   1398               pop: true
   1399             - include: expressions
   1400     # Destructor
   1401     - match: '(?:{{identifier}}\s*(::)\s*)?~{{identifier}}(?=\s*(\(|$))'
   1402       scope: meta.method.destructor.c++ entity.name.function.destructor.c++
   1403       captures:
   1404         1: punctuation.accessor.c++
   1405       set: method-definition-params
   1406     # It's a macro, not a constructor if there is no type in the first param
   1407     - match: '({{identifier}})\s*(\()(?=\s*(?!void){{identifier}}\s*[),])'
   1408       captures:
   1409         1: variable.function.c++
   1410         2: meta.group.c++ punctuation.section.group.begin.c++
   1411       push:
   1412         - meta_scope: meta.function-call.c++
   1413         - meta_content_scope: meta.group.c++
   1414         - match: '\)'
   1415           scope: meta.group.c++ punctuation.section.group.end.c++
   1416           pop: true
   1417         - include: expressions
   1418     # Constructor
   1419     - include: preprocessor-workaround-eat-macro-before-identifier
   1420     - match: '((?!{{before_tag}}|template){{identifier}})(?=\s*\()'
   1421       scope: meta.method.constructor.c++ entity.name.function.constructor.c++
   1422       set: method-definition-params
   1423     # Long form constructor
   1424     - match: '({{identifier}}\s*(::)\s*{{identifier}})(?=\s*\()'
   1425       captures:
   1426         1: meta.method.constructor.c++ entity.name.function.constructor.c++
   1427         2: punctuation.accessor.c++
   1428       push: method-definition-params
   1429     - match: '(?=\S)'
   1430       set: data-structures-type
   1431 
   1432   data-structures-type:
   1433     - include: comments
   1434     - match: \*|&
   1435       scope: keyword.operator.c++
   1436       # Cast methods
   1437     - match: '(operator)\s+({{identifier}})(?=\s*(\(|$))'
   1438       captures:
   1439         1: keyword.control.c++
   1440         2: meta.method.c++ entity.name.function.c++
   1441       set: method-definition-params
   1442     - match: '(?=\b({{control_keywords}}|{{operator_keywords}}|{{casts}}|{{memory_operators}}|{{other_keywords}}|operator)\b)'
   1443       pop: true
   1444     - match: '(?=\s)'
   1445       set: data-structures-maybe-method
   1446     # If a class/struct/enum followed by a name that is not a macro or declspec
   1447     # then this is likely a return type of a function. This is uncommon.
   1448     - match: |-
   1449         (?x:
   1450           ({{before_tag}})
   1451           \s+
   1452           (?=
   1453             (?![[:upper:][:digit:]_]+\b|__declspec|{{before_tag}})
   1454             {{path_lookahead}}
   1455             (\s+{{identifier}}\s*\(|\s*[*&])
   1456           )
   1457         )
   1458       captures:
   1459         1: storage.type.c++
   1460       set:
   1461         - include: identifiers
   1462         - match: ''
   1463           set: data-structures-maybe-method
   1464     # The previous match handles return types of struct/enum/etc from a func,
   1465     # there this one exits the context to allow matching an actual struct/class
   1466     - match: '(?=\b({{before_tag}})\b)'
   1467       set: data-structures
   1468     - match: '(?=\b({{casts}})\b\s*<)'
   1469       pop: true
   1470     - match: '{{non_angle_brackets}}'
   1471       pop: true
   1472     - include: angle-brackets
   1473     - include: types
   1474     - include: variables
   1475     - include: constants
   1476     - include: identifiers
   1477     - match: (?=[&*])
   1478       set: data-structures-maybe-method
   1479     - match: (?=\W)
   1480       pop: true
   1481 
   1482   data-structures-maybe-method:
   1483     - include: comments
   1484     # Consume pointer info, macros and any type info that was offset by macros
   1485     - match: \*|&
   1486       scope: keyword.operator.c++
   1487     - match: '(?=\b({{control_keywords}}|{{operator_keywords}}|{{casts}}|{{memory_operators}}|{{other_keywords}})\b)'
   1488       pop: true
   1489     - match: '\b({{type_qualifier}})\b'
   1490       scope: storage.modifier.c++
   1491     - match: '{{non_angle_brackets}}'
   1492       pop: true
   1493     - include: angle-brackets
   1494     - include: types
   1495     - include: modifiers-parens
   1496     - include: modifiers
   1497     # Operator overloading
   1498     - match: '{{operator_method_name}}(?=\s*(\(|$))'
   1499       scope: meta.method.c++ entity.name.function.c++
   1500       set: method-definition-params
   1501     # Identifier that is not the function name - likely a macro or type
   1502     - match: '(?={{path_lookahead}}([ \t]+|[*&])(?!\s*(<|::|\()))'
   1503       push:
   1504         - include: identifiers
   1505         - match: ''
   1506           pop: true
   1507     # Real function definition
   1508     - match: '(?={{path_lookahead}}({{generic_lookahead}})\s*(\())'
   1509       set: [method-definition-params, data-structures-function-identifier-generic]
   1510     - match: '(?={{path_lookahead}}\s*(\())'
   1511       set: [method-definition-params, data-structures-function-identifier]
   1512     - match: '(?={{path_lookahead}}\s*::\s*$)'
   1513       set: [method-definition-params, data-structures-function-identifier]
   1514     - match: '(?=\S)'
   1515       pop: true
   1516 
   1517   data-structures-function-identifier-generic:
   1518     - include: angle-brackets
   1519     - match: '(?={{identifier}})'
   1520       push:
   1521         - meta_content_scope: entity.name.function.c++
   1522         - include: identifiers
   1523         - match: '(?=<)'
   1524           pop: true
   1525     - match: '(?=\()'
   1526       pop: true
   1527 
   1528   data-structures-function-identifier:
   1529     - meta_content_scope: entity.name.function.c++
   1530     - include: identifiers
   1531     - match: '(?=\S)'
   1532       pop: true
   1533 
   1534   method-definition-params:
   1535     - meta_content_scope: meta.method.c++
   1536     - include: comments
   1537     - match: '(?=\()'
   1538       set:
   1539         - match: \(
   1540           scope: meta.method.parameters.c++ meta.group.c++ punctuation.section.group.begin.c++
   1541           set:
   1542             - meta_content_scope: meta.method.parameters.c++ meta.group.c++
   1543             - match : \)
   1544               scope: punctuation.section.group.end.c++
   1545               set: method-definition-continue
   1546             - match: '\bvoid\b'
   1547               scope: storage.type.c++
   1548             - match: '{{identifier}}(?=\s*(\[|,|\)|=))'
   1549               scope: variable.parameter.c++
   1550             - match: '='
   1551               scope: keyword.operator.assignment.c++
   1552               push:
   1553                 - match: '(?=,|\))'
   1554                   pop: true
   1555                 - include: expressions-minus-generic-type
   1556             - include: expressions-minus-generic-type
   1557     - match: '(?=\S)'
   1558       pop: true
   1559 
   1560   method-definition-continue:
   1561     - meta_content_scope: meta.method.c++
   1562     - include: comments
   1563     - match: '(?=;)'
   1564       pop: true
   1565     - match: '->'
   1566       scope: punctuation.separator.c++
   1567       set: method-definition-trailing-return
   1568     - include: function-specifiers
   1569     - match: '='
   1570       scope: keyword.operator.assignment.c++
   1571     - match: '&'
   1572       scope: keyword.operator.c++
   1573     - match: \b0\b
   1574       scope: constant.numeric.integer.decimal.c++
   1575     - match: \b(default|delete)\b
   1576       scope: storage.modifier.c++
   1577     - match: '(?=:)'
   1578       set:
   1579         - match: ':'
   1580           scope: punctuation.separator.initializer-list.c++
   1581           set:
   1582             - meta_scope: meta.method.constructor.initializer-list.c++
   1583             - match: '{{identifier}}'
   1584               scope: variable.other.readwrite.member.c++
   1585               push:
   1586                 - match: \(
   1587                   scope: meta.group.c++ punctuation.section.group.begin.c++
   1588                   set:
   1589                     - meta_content_scope: meta.group.c++
   1590                     - match: \)
   1591                       scope: meta.group.c++ punctuation.section.group.end.c++
   1592                       pop: true
   1593                     - include: expressions
   1594                 - match: \{
   1595                   scope: meta.group.c++ punctuation.section.group.begin.c++
   1596                   set:
   1597                     - meta_content_scope: meta.group.c++
   1598                     - match: \}
   1599                       scope: meta.group.c++ punctuation.section.group.end.c++
   1600                       pop: true
   1601                     - include: expressions
   1602                 - include: comments
   1603             - match: (?=\{|;)
   1604               set: method-definition-continue
   1605             - include: expressions
   1606     - match: '(?=\{)'
   1607       set: method-definition-body
   1608     - match: '(?=\S)'
   1609       pop: true
   1610 
   1611   method-definition-trailing-return:
   1612     - include: comments
   1613     - match: '(?=;)'
   1614       pop: true
   1615     - match: '(?=\{)'
   1616       set: method-definition-body
   1617     - include: function-specifiers
   1618     - include: function-trailing-return-type
   1619 
   1620   method-definition-body:
   1621     - meta_content_scope: meta.method.c++ meta.block.c++
   1622     - match: '\{'
   1623       scope: punctuation.section.block.begin.c++
   1624       set:
   1625         - meta_content_scope: meta.method.c++ meta.block.c++
   1626         - match: '\}'
   1627           scope: meta.method.c++ meta.block.c++ punctuation.section.block.end.c++
   1628           pop: true
   1629         - match: (?=^\s*#\s*(elif|else|endif)\b)
   1630           pop: true
   1631         - match: '(?=({{before_tag}})([^(;]+$|.*\{))'
   1632           push: data-structures
   1633         - include: statements
   1634 
   1635   ## Preprocessor for data-structures
   1636 
   1637   preprocessor-data-structures:
   1638     - include: preprocessor-rule-enabled-data-structures
   1639     - include: preprocessor-rule-disabled-data-structures
   1640     - include: preprocessor-practical-workarounds
   1641 
   1642   preprocessor-rule-disabled-data-structures:
   1643     - match: ^\s*((#if)\s+(0))\b
   1644       captures:
   1645         1: meta.preprocessor.c++
   1646         2: keyword.control.import.c++
   1647         3: constant.numeric.integer.decimal.c++
   1648       push:
   1649         - match: ^\s*(#\s*endif)\b
   1650           captures:
   1651             1: meta.preprocessor.c++ keyword.control.import.c++
   1652           pop: true
   1653         - match: ^\s*(#\s*else)\b
   1654           captures:
   1655             1: meta.preprocessor.c++ keyword.control.import.else.c++
   1656           push:
   1657             - match: (?=^\s*#\s*endif\b)
   1658               pop: true
   1659             - include: negated-block
   1660             - include: data-structures-body
   1661         - match: ""
   1662           push:
   1663             - meta_scope: comment.block.preprocessor.if-branch.c++
   1664             - match: (?=^\s*#\s*(else|endif)\b)
   1665               pop: true
   1666             - include: scope:source.c#preprocessor-disabled
   1667 
   1668   preprocessor-rule-enabled-data-structures:
   1669     - match: ^\s*((#if)\s+(0*1))\b
   1670       captures:
   1671         1: meta.preprocessor.c++
   1672         2: keyword.control.import.c++
   1673         3: constant.numeric.integer.decimal.c++
   1674       push:
   1675         - match: ^\s*(#\s*endif)\b
   1676           captures:
   1677             1: meta.preprocessor.c++ keyword.control.import.c++
   1678           pop: true
   1679         - match: ^\s*(#\s*else)\b
   1680           captures:
   1681             1: meta.preprocessor.c++ keyword.control.import.else.c++
   1682           push:
   1683             - meta_content_scope: comment.block.preprocessor.else-branch.c++
   1684             - match: (?=^\s*#\s*endif\b)
   1685               pop: true
   1686             - include: scope:source.c#preprocessor-disabled
   1687         - match: ""
   1688           push:
   1689             - match: (?=^\s*#\s*(else|endif)\b)
   1690               pop: true
   1691             - include: negated-block
   1692             - include: data-structures-body
   1693 
   1694   ## Preprocessor for global
   1695 
   1696   preprocessor-global:
   1697     - include: preprocessor-rule-enabled-global
   1698     - include: preprocessor-rule-disabled-global
   1699     - include: preprocessor-rule-other-global
   1700 
   1701   preprocessor-statements:
   1702     - include: preprocessor-rule-enabled-statements
   1703     - include: preprocessor-rule-disabled-statements
   1704     - include: preprocessor-rule-other-statements
   1705 
   1706   preprocessor-expressions:
   1707     - include: scope:source.c#incomplete-inc
   1708     - include: preprocessor-macro-define
   1709     - include: scope:source.c#pragma-mark
   1710     - include: preprocessor-other
   1711 
   1712   preprocessor-rule-disabled-global:
   1713     - match: ^\s*((#if)\s+(0))\b
   1714       captures:
   1715         1: meta.preprocessor.c++
   1716         2: keyword.control.import.c++
   1717         3: constant.numeric.integer.decimal.c++
   1718       push:
   1719         - match: ^\s*(#\s*endif)\b
   1720           captures:
   1721             1: meta.preprocessor.c++ keyword.control.import.c++
   1722           pop: true
   1723         - match: ^\s*(#\s*else)\b
   1724           captures:
   1725             1: meta.preprocessor.c++ keyword.control.import.else.c++
   1726           push:
   1727             - match: (?=^\s*#\s*endif\b)
   1728               pop: true
   1729             - include: preprocessor-global
   1730             - include: negated-block
   1731             - include: global
   1732         - match: ""
   1733           push:
   1734             - meta_scope: comment.block.preprocessor.if-branch.c++
   1735             - match: (?=^\s*#\s*(else|endif)\b)
   1736               pop: true
   1737             - include: scope:source.c#preprocessor-disabled
   1738 
   1739   preprocessor-rule-enabled-global:
   1740     - match: ^\s*((#if)\s+(0*1))\b
   1741       captures:
   1742         1: meta.preprocessor.c++
   1743         2: keyword.control.import.c++
   1744         3: constant.numeric.integer.decimal.c++
   1745       push:
   1746         - match: ^\s*(#\s*endif)\b
   1747           captures:
   1748             1: meta.preprocessor.c++ keyword.control.import.c++
   1749           pop: true
   1750         - match: ^\s*(#\s*else)\b
   1751           captures:
   1752             1: meta.preprocessor.c++ keyword.control.import.else.c++
   1753           push:
   1754             - meta_content_scope: comment.block.preprocessor.else-branch.c++
   1755             - match: (?=^\s*#\s*endif\b)
   1756               pop: true
   1757             - include: scope:source.c#preprocessor-disabled
   1758         - match: ""
   1759           push:
   1760             - match: (?=^\s*#\s*(else|endif)\b)
   1761               pop: true
   1762             - include: preprocessor-global
   1763             - include: negated-block
   1764             - include: global
   1765 
   1766   preprocessor-rule-other-global:
   1767     - match: ^\s*(#\s*(?:if|ifdef|ifndef))\b
   1768       captures:
   1769         1: keyword.control.import.c++
   1770       push:
   1771         - meta_scope: meta.preprocessor.c++
   1772         - include: scope:source.c#preprocessor-line-continuation
   1773         - include: scope:source.c#preprocessor-comments
   1774         - match: \bdefined\b
   1775           scope: keyword.control.c++
   1776         # Enter a new scope where all elif/else branches have their
   1777         # contexts popped by a subsequent elif/else/endif. This ensures that
   1778         # preprocessor branches don't push multiple meta.block scopes on
   1779         # the stack, thus messing up the "global" context's detection of
   1780         # functions.
   1781         - match: $\n
   1782           set: preprocessor-if-branch-global
   1783 
   1784   # These gymnastics here ensure that we are properly handling scope even
   1785   # when the preprocessor is used to create different scope beginnings, such
   1786   # as a different if/while condition
   1787   preprocessor-if-branch-global:
   1788     - match: ^\s*(#\s*endif)\b
   1789       captures:
   1790         1: meta.preprocessor.c++ keyword.control.import.c++
   1791       pop: true
   1792     - match: (?=^\s*#\s*(elif|else)\b)
   1793       push: preprocessor-elif-else-branch-global
   1794     - match: \{
   1795       scope: punctuation.section.block.begin.c++
   1796       set: preprocessor-block-if-branch-global
   1797     - include: preprocessor-global
   1798     - include: negated-block
   1799     - include: global
   1800 
   1801   preprocessor-block-if-branch-global:
   1802     - meta_scope: meta.block.c++
   1803     - match: ^\s*(#\s*endif)\b
   1804       captures:
   1805         1: meta.preprocessor.c++ keyword.control.import.c++
   1806       set: preprocessor-block-finish-global
   1807     - match: (?=^\s*#\s*(elif|else)\b)
   1808       push: preprocessor-elif-else-branch-global
   1809     - match: \}
   1810       scope: punctuation.section.block.end.c++
   1811       set: preprocessor-if-branch-global
   1812     - include: statements
   1813 
   1814   preprocessor-block-finish-global:
   1815     - meta_scope: meta.block.c++
   1816     - match: ^\s*(#\s*(?:if|ifdef|ifndef))\b
   1817       captures:
   1818         1: meta.preprocessor.c++ keyword.control.import.c++
   1819       set: preprocessor-block-finish-if-branch-global
   1820     - match: \}
   1821       scope: punctuation.section.block.end.c++
   1822       pop: true
   1823     - include: statements
   1824 
   1825   preprocessor-block-finish-if-branch-global:
   1826     - match: ^\s*(#\s*endif)\b
   1827       captures:
   1828         1: keyword.control.import.c++
   1829       pop: true
   1830     - match: \}
   1831       scope: punctuation.section.block.end.c++
   1832       set: preprocessor-if-branch-global
   1833     - include: statements
   1834 
   1835   preprocessor-elif-else-branch-global:
   1836     - match: (?=^\s*#\s*(endif)\b)
   1837       pop: true
   1838     - include: preprocessor-global
   1839     - include: negated-block
   1840     - include: global
   1841 
   1842   ## Preprocessor for statements
   1843 
   1844   preprocessor-rule-disabled-statements:
   1845     - match: ^\s*((#if)\s+(0))\b
   1846       captures:
   1847         1: meta.preprocessor.c++
   1848         2: keyword.control.import.c++
   1849         3: constant.numeric.integer.decimal.c++
   1850       push:
   1851         - match: ^\s*(#\s*endif)\b
   1852           captures:
   1853             1: meta.preprocessor.c++ keyword.control.import.c++
   1854           pop: true
   1855         - match: ^\s*(#\s*else)\b
   1856           captures:
   1857             1: meta.preprocessor.c++ keyword.control.import.else.c++
   1858           push:
   1859             - match: (?=^\s*#\s*endif\b)
   1860               pop: true
   1861             - include: negated-block
   1862             - include: statements
   1863         - match: ""
   1864           push:
   1865             - meta_scope: comment.block.preprocessor.if-branch.c++
   1866             - match: (?=^\s*#\s*(else|endif)\b)
   1867               pop: true
   1868             - include: scope:source.c#preprocessor-disabled
   1869 
   1870   preprocessor-rule-enabled-statements:
   1871     - match: ^\s*((#if)\s+(0*1))\b
   1872       captures:
   1873         1: meta.preprocessor.c++
   1874         2: keyword.control.import.c++
   1875         3: constant.numeric.integer.decimal.c++
   1876       push:
   1877         - match: ^\s*(#\s*endif)\b
   1878           captures:
   1879             1: meta.preprocessor.c++ keyword.control.import.c++
   1880           pop: true
   1881         - match: ^\s*(#\s*else)\b
   1882           captures:
   1883             1: meta.preprocessor.c++ keyword.control.import.else.c++
   1884           push:
   1885             - meta_content_scope: comment.block.preprocessor.else-branch.c++
   1886             - match: (?=^\s*#\s*endif\b)
   1887               pop: true
   1888             - include: scope:source.c#preprocessor-disabled
   1889         - match: ""
   1890           push:
   1891             - match: (?=^\s*#\s*(else|endif)\b)
   1892               pop: true
   1893             - include: negated-block
   1894             - include: statements
   1895 
   1896   preprocessor-rule-other-statements:
   1897     - match: ^\s*(#\s*(?:if|ifdef|ifndef))\b
   1898       captures:
   1899         1: keyword.control.import.c++
   1900       push:
   1901         - meta_scope: meta.preprocessor.c++
   1902         - include: scope:source.c#preprocessor-line-continuation
   1903         - include: scope:source.c#preprocessor-comments
   1904         - match: \bdefined\b
   1905           scope: keyword.control.c++
   1906         # Enter a new scope where all elif/else branches have their
   1907         # contexts popped by a subsequent elif/else/endif. This ensures that
   1908         # preprocessor branches don't push multiple meta.block scopes on
   1909         # the stack, thus messing up the "global" context's detection of
   1910         # functions.
   1911         - match: $\n
   1912           set: preprocessor-if-branch-statements
   1913 
   1914   # These gymnastics here ensure that we are properly handling scope even
   1915   # when the preprocessor is used to create different scope beginnings, such
   1916   # as a different if/while condition
   1917   preprocessor-if-branch-statements:
   1918     - match: ^\s*(#\s*endif)\b
   1919       captures:
   1920         1: meta.preprocessor.c++ keyword.control.import.c++
   1921       pop: true
   1922     - match: (?=^\s*#\s*(elif|else)\b)
   1923       push: preprocessor-elif-else-branch-statements
   1924     - match: \{
   1925       scope: punctuation.section.block.begin.c++
   1926       set: preprocessor-block-if-branch-statements
   1927     - match: (?=(?!{{non_func_keywords}}){{path_lookahead}}\s*\()
   1928       set: preprocessor-if-branch-function-call
   1929     - include: negated-block
   1930     - include: statements
   1931 
   1932   preprocessor-if-branch-function-call:
   1933     - meta_content_scope: meta.function-call.c++
   1934     - include: scope:source.c#c99
   1935     - match: '(?:(::)\s*)?{{identifier}}\s*(::)\s*'
   1936       scope: variable.function.c++
   1937       captures:
   1938         1: punctuation.accessor.c++
   1939         2: punctuation.accessor.c++
   1940     - match: '(?:(::)\s*)?{{identifier}}'
   1941       scope: variable.function.c++
   1942       captures:
   1943         1: punctuation.accessor.c++
   1944     - match: '\('
   1945       scope: meta.group.c++ punctuation.section.group.begin.c++
   1946       set: preprocessor-if-branch-function-call-arguments
   1947 
   1948   preprocessor-if-branch-function-call-arguments:
   1949     - meta_content_scope: meta.function-call.c++ meta.group.c++
   1950     - match : \)
   1951       scope: meta.function-call.c++ meta.group.c++ punctuation.section.group.end.c++
   1952       set: preprocessor-if-branch-statements
   1953     - match: ^\s*(#\s*(?:elif|else))\b
   1954       captures:
   1955         1: meta.preprocessor.c++ keyword.control.import.c++
   1956       set: preprocessor-if-branch-statements
   1957     - match: ^\s*(#\s*endif)\b
   1958       captures:
   1959         1: meta.preprocessor.c++ keyword.control.import.c++
   1960       set: preprocessor-if-branch-function-call-arguments-finish
   1961     - include: expressions
   1962 
   1963   preprocessor-if-branch-function-call-arguments-finish:
   1964     - meta_content_scope: meta.function-call.c++ meta.group.c++
   1965     - match: \)
   1966       scope: meta.function-call.c++ meta.group.c++ punctuation.section.group.end.c++
   1967       pop: true
   1968     - include: expressions
   1969 
   1970   preprocessor-block-if-branch-statements:
   1971     - meta_scope: meta.block.c++
   1972     - match: ^\s*(#\s*endif)\b
   1973       captures:
   1974         1: meta.preprocessor.c++ keyword.control.import.c++
   1975       set: preprocessor-block-finish-statements
   1976     - match: (?=^\s*#\s*(elif|else)\b)
   1977       push: preprocessor-elif-else-branch-statements
   1978     - match: \}
   1979       scope: punctuation.section.block.end.c++
   1980       set: preprocessor-if-branch-statements
   1981     - include: statements
   1982 
   1983   preprocessor-block-finish-statements:
   1984     - meta_scope: meta.block.c++
   1985     - match: ^\s*(#\s*(?:if|ifdef|ifndef))\b
   1986       captures:
   1987         1: meta.preprocessor.c++ keyword.control.import.c++
   1988       set: preprocessor-block-finish-if-branch-statements
   1989     - match: \}
   1990       scope: punctuation.section.block.end.c++
   1991       pop: true
   1992     - include: statements
   1993 
   1994   preprocessor-block-finish-if-branch-statements:
   1995     - match: ^\s*(#\s*endif)\b
   1996       captures:
   1997         1: keyword.control.import.c++
   1998       pop: true
   1999     - match: \}
   2000       scope: meta.block.c++ punctuation.section.block.end.c++
   2001       set: preprocessor-if-branch-statements
   2002     - include: statements
   2003 
   2004   preprocessor-elif-else-branch-statements:
   2005     - match: (?=^\s*#\s*endif\b)
   2006       pop: true
   2007     - include: negated-block
   2008     - include: statements
   2009 
   2010   ## Preprocessor other
   2011 
   2012   negated-block:
   2013     - match: '\}'
   2014       scope: punctuation.section.block.end.c++
   2015       push:
   2016         - match: '\{'
   2017           scope: punctuation.section.block.begin.c++
   2018           pop: true
   2019         - match: (?=^\s*#\s*(elif|else|endif)\b)
   2020           pop: true
   2021         - include: statements
   2022 
   2023   preprocessor-macro-define:
   2024     - match: ^\s*(\#\s*define)\b
   2025       captures:
   2026         1: meta.preprocessor.macro.c++ keyword.control.import.define.c++
   2027       push:
   2028         - meta_content_scope: meta.preprocessor.macro.c++
   2029         - include: scope:source.c#preprocessor-line-continuation
   2030         - include: scope:source.c#preprocessor-line-ending
   2031         - include: scope:source.c#preprocessor-comments
   2032         - match: '({{identifier}})(?=\()'
   2033           scope: entity.name.function.preprocessor.c++
   2034           set:
   2035             - match: '\('
   2036               scope: punctuation.section.group.begin.c++
   2037               set: preprocessor-macro-params
   2038         - match: '{{identifier}}'
   2039           scope: entity.name.constant.preprocessor.c++
   2040           set: preprocessor-macro-definition
   2041 
   2042   preprocessor-macro-params:
   2043     - meta_scope: meta.preprocessor.macro.parameters.c++ meta.group.c++
   2044     - match: '{{identifier}}'
   2045       scope: variable.parameter.c++
   2046     - match: \)
   2047       scope: punctuation.section.group.end.c++
   2048       set: preprocessor-macro-definition
   2049     - match: ','
   2050       scope: punctuation.separator.c++
   2051       push:
   2052         - match: '{{identifier}}'
   2053           scope: variable.parameter.c++
   2054           pop: true
   2055         - include: scope:source.c#preprocessor-line-continuation
   2056         - include: scope:source.c#preprocessor-comments
   2057         - match: '\.\.\.'
   2058           scope: keyword.operator.variadic.c++
   2059         - match: '(?=\))'
   2060           pop: true
   2061         - match: (/\*).*(\*/)
   2062           scope: comment.block.c++
   2063           captures:
   2064             1: punctuation.definition.comment.c++
   2065             2: punctuation.definition.comment.c++
   2066         - match: '\S+'
   2067           scope: invalid.illegal.unexpected-character.c++
   2068     - include: scope:source.c#preprocessor-line-continuation
   2069     - include: scope:source.c#preprocessor-comments
   2070     - match: '\.\.\.'
   2071       scope: keyword.operator.variadic.c++
   2072     - match: (/\*).*(\*/)
   2073       scope: comment.block.c++
   2074       captures:
   2075         1: punctuation.definition.comment.c++
   2076         2: punctuation.definition.comment.c++
   2077     - match: $\n
   2078       scope: invalid.illegal.unexpected-end-of-line.c++
   2079 
   2080   preprocessor-macro-definition:
   2081     - meta_content_scope: meta.preprocessor.macro.c++
   2082     - include: scope:source.c#preprocessor-line-continuation
   2083     - include: scope:source.c#preprocessor-line-ending
   2084     - include: scope:source.c#preprocessor-comments
   2085     # Don't define blocks in define statements
   2086     - match: '\{'
   2087       scope: punctuation.section.block.begin.c++
   2088     - match: '\}'
   2089       scope: punctuation.section.block.end.c++
   2090     # Captures the namespace macro idiom
   2091     - match: '\b(namespace)\s+(?={{path_lookahead}}\s*\{)'
   2092       scope: meta.namespace.c++
   2093       captures:
   2094         1: keyword.control.c++
   2095       push:
   2096         - meta_content_scope: meta.namespace.c++ entity.name.namespace.c++
   2097         - include: identifiers
   2098         - match: '(?=\S)'
   2099           pop: true
   2100     - include: expressions
   2101 
   2102   preprocessor-practical-workarounds:
   2103     - include: preprocessor-convention-ignore-uppercase-ident-lines
   2104     - include: scope:source.c#preprocessor-convention-ignore-uppercase-calls-without-semicolon
   2105 
   2106   preprocessor-convention-ignore-uppercase-ident-lines:
   2107     - match: ^(\s*{{macro_identifier}})+\s*$
   2108       scope: meta.assumed-macro.c++
   2109       push:
   2110         # It's possible that we are dealing with a function return type on its own line, and the
   2111         # name of the function is on the subsequent line.
   2112         - match: '(?={{path_lookahead}}({{generic_lookahead}}({{path_lookahead}})?)\s*\()'
   2113           set: [function-definition-params, global-function-identifier-generic]
   2114         - match: '(?={{path_lookahead}}\s*\()'
   2115           set: [function-definition-params, global-function-identifier]
   2116         - match: ^
   2117           pop: true
   2118 
   2119   preprocessor-other:
   2120     - match: ^\s*(#\s*(?:if|ifdef|ifndef|elif|else|line|pragma|undef))\b
   2121       captures:
   2122         1: keyword.control.import.c++
   2123       push:
   2124         - meta_scope: meta.preprocessor.c++
   2125         - include: scope:source.c#preprocessor-line-continuation
   2126         - include: scope:source.c#preprocessor-line-ending
   2127         - include: scope:source.c#preprocessor-comments
   2128         - match: \bdefined\b
   2129           scope: keyword.control.c++
   2130     - match: ^\s*(#\s*endif)\b
   2131       captures:
   2132         1: meta.preprocessor.c++ keyword.control.import.c++
   2133     - match: ^\s*(#\s*(?:error|warning))\b
   2134       captures:
   2135         1: keyword.control.import.error.c++
   2136       push:
   2137         - meta_scope: meta.preprocessor.diagnostic.c++
   2138         - include: scope:source.c#preprocessor-line-continuation
   2139         - include: scope:source.c#preprocessor-line-ending
   2140         - include: scope:source.c#preprocessor-comments
   2141         - include: strings
   2142         - match: '\S+'
   2143           scope: string.unquoted.c++
   2144     - match: ^\s*(#\s*(?:include|include_next|import))\b
   2145       captures:
   2146         1: keyword.control.import.include.c++
   2147       push:
   2148         - meta_scope: meta.preprocessor.include.c++
   2149         - include: scope:source.c#preprocessor-line-continuation
   2150         - include: scope:source.c#preprocessor-line-ending
   2151         - include: scope:source.c#preprocessor-comments
   2152         - match: '"'
   2153           scope: punctuation.definition.string.begin.c++
   2154           push:
   2155             - meta_scope: string.quoted.double.include.c++
   2156             - match: '"'
   2157               scope: punctuation.definition.string.end.c++
   2158               pop: true
   2159         - match: <
   2160           scope: punctuation.definition.string.begin.c++
   2161           push:
   2162             - meta_scope: string.quoted.other.lt-gt.include.c++
   2163             - match: '>'
   2164               scope: punctuation.definition.string.end.c++
   2165               pop: true
   2166     - include: preprocessor-practical-workarounds