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