Created
October 11, 2019 10:29
-
-
Save xenoken/df60d7b412005a8a831b7c6150ed24dd to your computer and use it in GitHub Desktop.
Revisions
-
xenoken created this gist
Oct 11, 2019 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,2005 @@ %YAML 1.2 --- # http://www.sublimetext.com/docs/3/syntax.html name: C++ comment: Adapted from C++.sublime-syntax file_extensions: - tps - ush first_line_match: '-\*- C\+\+ -\*-' scope: source.c++ variables: identifier: \b[[:alpha:]_][[:alnum:]_]*\b # upper and lowercase macro_identifier: \b[[:upper:]_][[:upper:][:digit:]_]{2,}\b # only uppercase, at least 3 chars path_lookahead: '(?:::\s*)?(?:{{identifier}}\s*::\s*)*(?:template\s+)?{{identifier}}' operator_method_name: '\boperator\s*(?:[-+*/%^&|~!=<>]|[-+*/%^&|=!<>]=|<<=?|>>=?|&&|\|\||\+\+|--|,|->\*?|\(\)|\[\]|""\s*{{identifier}})' casts: 'const_cast|dynamic_cast|reinterpret_cast|static_cast' operator_keywords: 'and|and_eq|bitand|bitor|compl|not|not_eq|or|or_eq|xor|xor_eq|noexcept' control_keywords: 'break|case|catch|continue|default|do|else|for|goto|if|_Pragma|return|switch|throw|try|while' memory_operators: 'new|delete' basic_types: 'asm|__asm__|auto|bool|_Bool|char|_Complex|double|float|_Imaginary|int|long|short|signed|unsigned|void' before_tag: 'struct|union|enum\s+class|enum\s+struct|enum|class' declspec: '__declspec\(\s*\w+(?:\([^)]+\))?\s*\)' storage_classes: 'static|export|extern|friend|explicit|virtual|register|thread_local' type_qualifier: 'const|constexpr|mutable|typename|volatile' compiler_directive: 'inline|restrict|__restrict__|__restrict' visibility_modifiers: 'private|protected|public' other_keywords: 'typedef|nullptr|{{visibility_modifiers}}|static_assert|sizeof|using|typeid|alignof|alignas|namespace|template' modifiers: '{{storage_classes}}|{{type_qualifier}}|{{compiler_directive}}' non_angle_brackets: '(?=<<|<=)' regular: '[^(){}&;*^%=<>-]*' paren_open: (?:\( paren_close: '\))?' generic_open: (?:< generic_close: '>)?' balance_parentheses: '{{regular}}{{paren_open}}{{regular}}{{paren_close}}{{regular}}' generic_lookahead: <{{regular}}{{generic_open}}{{regular}}{{generic_open}}{{regular}}{{generic_close}}\s*{{generic_close}}{{balance_parentheses}}> data_structures_forward_decl_lookahead: '(\s+{{macro_identifier}})*\s*(:\s*({{path_lookahead}}|{{visibility_modifiers}}|,|\s|<[^;]*>)+)?;' non_func_keywords: 'if|for|switch|while|decltype|sizeof|__declspec|__attribute__|typeid|alignof|alignas|static_assert' contexts: main: - include: preprocessor-global - include: global ############################################################################# # Reusable contexts # # The follow contexts are currently constructed to be reused in the # Objetive-C++ syntax. They are specifically constructed to not push into # sub-contexts, which ensures that Objective-C++ code isn't accidentally # lexed as plain C++. # # The "unique-*" contexts are additions that C++ makes over C, and thus can # be directly reused in Objective-C++ along with contexts from Objective-C # and C. ############################################################################# unique-late-expressions: # This is highlighted after all of the other control keywords # to allow operator overloading to be lexed properly - match: \boperator\b scope: keyword.control.c++ unique-modifiers: - match: \b({{modifiers}})\b scope: storage.modifier.c++ unique-variables: - match: \bthis\b scope: variable.language.c++ # common C++ instance var naming idiom -- fMemberName - match: '\b(f|m)[[:upper:]]\w*\b' scope: variable.other.readwrite.member.c++ # common C++ instance var naming idiom -- m_member_name - match: '\bm_[[:alnum:]_]+\b' scope: variable.other.readwrite.member.c++ unique-constants: - match: \bnullptr\b scope: constant.language.c++ unique-keywords: - match: \busing\b scope: keyword.control.c++ - match: \bbreak\b scope: keyword.control.flow.break.c++ - match: \bcontinue\b scope: keyword.control.flow.continue.c++ - match: \bgoto\b scope: keyword.control.flow.goto.c++ - match: \breturn\b scope: keyword.control.flow.return.c++ - match: \bthrow\b scope: keyword.control.flow.throw.c++ - match: \b({{control_keywords}})\b scope: keyword.control.c++ - match: '\bdelete\b(\s*\[\])?|\bnew\b(?!])' scope: keyword.control.c++ - match: \b({{operator_keywords}})\b scope: keyword.operator.word.c++ unique-types: - match: \b(char16_t|char32_t|wchar_t|nullptr_t)\b scope: storage.type.c++ - match: \bclass\b scope: storage.type.c++ unique-strings: - match: '((?:L|u8|u|U)?R)("([^\(\)\\ ]{0,16})\()' captures: 1: storage.type.string.c++ 2: punctuation.definition.string.begin.c++ push: - meta_scope: string.quoted.double.c++ - match: '\)\3"' scope: punctuation.definition.string.end.c++ pop: true unique-numbers: - match: |- (?x) (?: # floats (?: (?:\b\d(?:[\d']*\d)?\.\d(?:[\d']*\d)?|\B\.\d(?:[\d']*\d)?)(?:[Ee][+-]?\d(?:[\d']*\d)?)?(?:[fFlL]|(?:i[fl]?|h|min|[mun]?s|_\w*))?\b | (?:\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) | \b\d(?:[\d']*\d)?(?:[Ee][+-]?\d(?:[\d']*\d)?)(?:[fFlL]|(?:i[fl]?|h|min|[mun]?s|_\w*))?\b ) | # ints \b(?: (?: # dec [1-9](?:[\d']*\d)? | # oct 0(?:[0-7']*[0-7])? | # hex 0[Xx][\da-fA-F](?:[\da-fA-F']*[\da-fA-F])? | # bin 0[Bb][01](?:[01']*[01])? ) # int suffixes (?:(?:l{1,2}|L{1,2})[uU]?|[uU](?:l{0,2}|L{0,2})|(?:i[fl]?|h|min|[mun]?s|_\w*))?)\b ) (?!\.) # Number must not be followed by a decimal point scope: constant.numeric.c++ identifiers: - match: '{{identifier}}\s*(::)\s*' captures: 1: punctuation.accessor.c++ - match: '(?:(::)\s*)?{{identifier}}' captures: 1: punctuation.accessor.c++ function-specifiers: - match: \b(const|final|noexcept|override)\b scope: storage.modifier.c++ ############################################################################# # The following are C++-specific contexts that should not be reused. This is # because they push into subcontexts and use variables that are C++-specific. ############################################################################# ## Common context layout global: - match: '(?=\btemplate\b)' push: - include: template - match: (?=\S) set: global-modifier - include: namespace - include: keywords-angle-brackets - match: '(?={{path_lookahead}}\s*<)' push: global-modifier # Take care of comments just before a function definition. - match: /\* scope: punctuation.definition.comment.c push: - - match: \s*(?=\w) set: global-modifier - match: "" pop: true - - meta_scope: comment.block.c - match: \*/ scope: punctuation.definition.comment.c pop: true - match: ^\s*(\*)(?!/) captures: 1: punctuation.definition.comment.c - include: early-expressions - match: ^\s*\b(extern)(?=\s+"C(\+\+)?") scope: storage.modifier.c++ push: - include: comments - include: strings - match: '\{' scope: punctuation.section.block.begin.c++ set: - meta_scope: meta.extern-c.c++ - match: '^\s*(#\s*ifdef)\s*__cplusplus\s*' scope: meta.preprocessor.c++ captures: 1: keyword.control.import.c++ set: - match: '\}' scope: punctuation.section.block.end.c++ pop: true - include: preprocessor-global - include: global - match: '\}' scope: punctuation.section.block.end.c++ pop: true - include: preprocessor-global - include: global - match: (?=\S) set: global-modifier - match: ^\s*(?=\w) push: global-modifier - include: late-expressions statements: - include: preprocessor-statements - include: scope:source.c#label - include: expressions expressions: - include: early-expressions - include: late-expressions early-expressions: - include: early-expressions-before-generic-type - include: generic-type - include: early-expressions-after-generic-type early-expressions-before-generic-type: - include: preprocessor-expressions - include: comments - include: case-default - include: typedef - include: keywords-angle-brackets - include: keywords-parens - include: keywords - include: numbers # Prevent a '<' from getting scoped as the start of another template # parameter list, if in reality a less-than-or-equals sign is meant. - match: <= scope: keyword.operator.comparison.c early-expressions-after-generic-type: - include: members-arrow - include: operators - include: members-dot - include: strings - include: parens - include: brackets - include: block - include: variables - include: constants - match: ',' scope: punctuation.separator.c++ - match: '\)|\}' scope: invalid.illegal.stray-bracket-end.c++ expressions-minus-generic-type: - include: early-expressions-before-generic-type - include: angle-brackets - include: early-expressions-after-generic-type - include: late-expressions expressions-minus-generic-type-function-call: - include: early-expressions-before-generic-type - include: angle-brackets - include: early-expressions-after-generic-type - include: late-expressions-before-function-call - include: identifiers - match: ';' scope: punctuation.terminator.c++ late-expressions: - include: late-expressions-before-function-call - include: function-call - include: identifiers - match: ';' scope: punctuation.terminator.c++ late-expressions-before-function-call: - include: unique-late-expressions - include: modifiers-parens - include: modifiers - include: types expressions-minus-function-call: - include: early-expressions - include: late-expressions-before-function-call - include: identifiers - match: ';' scope: punctuation.terminator.c++ comments: - include: scope:source.c#comments operators: - include: scope:source.c#operators modifiers: - include: unique-modifiers - include: scope:source.c#modifiers variables: - include: unique-variables - include: scope:source.c#variables constants: - include: unique-constants - include: scope:source.c#constants keywords: - include: unique-keywords - include: scope:source.c#keywords types: - include: unique-types - include: types-parens - include: scope:source.c#types strings: - include: unique-strings - include: scope:source.c#strings numbers: - include: unique-numbers - include: scope:source.c#numbers ## C++-specific contexts case-default: - match: '\b(default|case)\b' scope: keyword.control.c++ push: - match: (?=[);,]) pop: true - match: ':' scope: punctuation.separator.c++ pop: true - include: expressions modifiers-parens: - match: '\b(alignas)\b\s*(\()' captures: 1: storage.modifier.c++ 2: meta.group.c++ punctuation.section.group.begin.c++ push: - meta_content_scope: meta.group.c++ - match: '\)' scope: meta.group.c++ punctuation.section.group.end.c++ pop: true - include: expressions - match: \b(__attribute__)\s*(\(\() captures: 1: storage.modifier.c++ 2: meta.group.c++ punctuation.section.group.begin.c++ push : - meta_scope: meta.attribute.c++ - meta_content_scope: meta.group.c++ - include: parens - include: strings - match: \)\) scope: meta.group.c++ punctuation.section.group.end.c++ pop: true - match: \b(__declspec)(\() captures: 1: storage.modifier.c++ 2: meta.group.c++ punctuation.section.group.begin.c++ push: - meta_content_scope: meta.group.c++ - match: '\)' scope: meta.group.c++ punctuation.section.group.end.c++ pop: true - match: '\b(align|allocate|code_seg|deprecated|property|uuid)\b\s*(\()' captures: 1: storage.modifier.c++ 2: meta.group.c++ punctuation.section.group.begin.c++ push: - meta_content_scope: meta.group.c++ - match: '\)' scope: meta.group.c++ punctuation.section.group.end.c++ pop: true - include: numbers - include: strings - match: \b(get|put)\b scope: variable.parameter.c++ - match: ',' scope: punctuation.separator.c++ - match: '=' scope: keyword.operator.assignment.c++ - match: '\b(appdomain|deprecated|dllimport|dllexport|jintrinsic|naked|noalias|noinline|noreturn|nothrow|novtable|process|restrict|safebuffers|selectany|thread)\b' scope: constant.other.c++ types-parens: - match: '\b(decltype)\b\s*(\()' captures: 1: storage.type.c++ 2: meta.group.c++ punctuation.section.group.begin.c++ push: - meta_content_scope: meta.group.c++ - match: '\)' scope: meta.group.c++ punctuation.section.group.end.c++ pop: true - include: expressions keywords-angle-brackets: - match: \b({{casts}})\b\s* scope: keyword.operator.word.cast.c++ push: - match: '>' scope: punctuation.section.generic.end.c++ pop: true - match: '<' scope: punctuation.section.generic.begin.c++ push: - match: '(?=>)' pop: true - include: expressions-minus-generic-type-function-call keywords-parens: - match: '\b(alignof|typeid|static_assert|sizeof)\b\s*(\()' captures: 1: keyword.operator.word.c++ 2: meta.group.c++ punctuation.section.group.begin.c++ push: - meta_content_scope: meta.group.c++ - match: '\)' scope: meta.group.c++ punctuation.section.group.end.c++ pop: true - include: expressions namespace: - match: '\b(using)\s+(namespace)\s+(?={{path_lookahead}})' captures: 1: keyword.control.c++ 2: keyword.control.c++ push: - include: identifiers - match: '' pop: true - match: '\b(namespace)\s+(?=({{path_lookahead}})?(?!\s*[;,]))' scope: meta.namespace.c++ captures: 1: keyword.control.c++ push: - meta_content_scope: meta.namespace.c++ entity.name.namespace.c++ - include: identifiers - match: '' set: - meta_scope: meta.namespace.c++ - include: comments - match: '=' scope: keyword.operator.alias.c++ - match: '(?=;)' pop: true - match: '\}' scope: meta.block.c++ punctuation.section.block.end.c++ pop: true - match: '\{' scope: punctuation.section.block.begin.c++ push: - meta_scope: meta.block.c++ - match: '(?=\})' pop: true - include: preprocessor-global - include: global - include: expressions template-common: # Exit the template scope if we hit some basic invalid characters. This # helps when a user is in the middle of typing their template types and # prevents re-highlighting the whole file until the next > is found. - match: (?=[{};]) pop: true - include: expressions template: - match: \btemplate\b scope: storage.type.template.c++ push: - meta_scope: meta.template.c++ # Explicitly include comments here at the top, in order to NOT match the # \S lookahead in the case of comments. - include: comments - match: < scope: punctuation.section.generic.begin.c++ set: - meta_content_scope: meta.template.c++ - match: '>' scope: meta.template.c++ punctuation.section.generic.end.c++ pop: true - match: \.{3} scope: keyword.operator.variadic.c++ - match: \b(typename|{{before_tag}})\b scope: storage.type.c++ - include: template # include template here for nested templates - include: template-common - match: (?=\S) set: - meta_content_scope: meta.template.c++ - match: \b({{before_tag}})\b scope: storage.type.c++ - include: template-common generic-type: - match: '(?=(?!template){{path_lookahead}}\s*{{generic_lookahead}}\s*\()' push: - meta_scope: meta.function-call.c++ - match: \btemplate\b scope: storage.type.template.c++ - match: '(?:(::)\s*)?{{identifier}}\s*(::)\s*' captures: 1: punctuation.accessor.double-colon.c++ 2: punctuation.accessor.double-colon.c++ - match: (?:(::)\s*)?({{identifier}})\s*(<) captures: 1: punctuation.accessor.double-colon.c++ 2: variable.function.c++ 3: punctuation.section.generic.begin.c++ push: - match: '>' scope: punctuation.section.generic.end.c++ pop: true - include: expressions-minus-generic-type-function-call - match: (?:(::)\s*)?({{identifier}})\s*(\() captures: 1: punctuation.accessor.double-colon.c++ 2: variable.function.c++ 3: punctuation.section.group.begin.c++ set: - meta_scope: meta.function-call.c++ - meta_content_scope: meta.group.c++ - match: '\)' scope: meta.group.c++ punctuation.section.group.end.c++ pop: true - include: expressions - include: angle-brackets - match: '\(' scope: meta.group.c++ punctuation.section.group.begin.c++ set: - meta_scope: meta.function-call.c++ - meta_content_scope: meta.group.c++ - match: '\)' scope: meta.group.c++ punctuation.section.group.end.c++ pop: true - include: expressions - match: '(?=(?!template){{path_lookahead}}\s*{{generic_lookahead}})' push: - include: identifiers - match: '<' scope: punctuation.section.generic.begin.c++ set: - match: '>' scope: punctuation.section.generic.end.c++ pop: true - include: expressions-minus-generic-type-function-call angle-brackets: - match: '<(?!<)' scope: punctuation.section.generic.begin.c++ push: - match: '>' scope: punctuation.section.generic.end.c++ pop: true - include: expressions-minus-generic-type-function-call block: - match: '\{' scope: punctuation.section.block.begin.c++ push: - meta_scope: meta.block.c++ - match: (?=^\s*#\s*(elif|else|endif)\b) pop: true - match: '\}' scope: punctuation.section.block.end.c++ pop: true - include: statements function-call: - match: (?={{path_lookahead}}\s*\() push: - meta_scope: meta.function-call.c++ - include: scope:source.c#c99 - match: '(?:(::)\s*)?{{identifier}}\s*(::)\s*' scope: variable.function.c++ captures: 1: punctuation.accessor.c++ 2: punctuation.accessor.c++ - match: '(?:(::)\s*)?{{identifier}}' scope: variable.function.c++ captures: 1: punctuation.accessor.c++ - match: '\(' scope: meta.group.c++ punctuation.section.group.begin.c++ set: - meta_content_scope: meta.function-call.c++ meta.group.c++ - match: '\)' scope: meta.function-call.c++ meta.group.c++ punctuation.section.group.end.c++ pop: true - include: expressions members-inside-function-call: - meta_content_scope: meta.method-call.c++ meta.group.c++ - match: \) scope: meta.method-call.c++ meta.group.c++ punctuation.section.group.end.c++ pop: true - include: expressions members-after-accessor-junction: # After we've seen an accessor (dot or arrow), this context decides what # kind of entity we're accessing. - include: comments - match: \btemplate\b scope: meta.method-call.c++ storage.type.template.c++ # Guaranteed to be a template member function call after we match this set: - meta_content_scope: meta.method-call.c++ - include: comments - match: '{{identifier}}' scope: variable.function.member.c++ set: - meta_content_scope: meta.method-call.c++ - match: \( scope: meta.group.c++ punctuation.section.group.begin.c++ set: members-inside-function-call - include: comments - include: angle-brackets - match: (?=\S) # safety pop pop: true - match: (?=\S) # safety pop pop: true # Operator overloading - match: '({{operator_method_name}})\s*(\()' captures: 0: meta.method-call.c++ 1: variable.function.member.c++ 2: meta.group.c++ punctuation.section.group.begin.c++ set: members-inside-function-call # Non-templated member function call - match: (~?{{identifier}})\s*(\() captures: 0: meta.method-call.c++ 1: variable.function.member.c++ 2: meta.group.c++ punctuation.section.group.begin.c++ set: members-inside-function-call # Templated member function call - match: (~?{{identifier}})\s*(?={{generic_lookahead}}) captures: 1: variable.function.member.c++ set: - meta_scope: meta.method-call.c++ - match: < scope: punctuation.section.generic.begin.c++ set: - meta_content_scope: meta.method-call.c++ - match: '>' scope: punctuation.section.generic.end.c++ set: - meta_content_scope: meta.method-call.c++ - include: comments - match: \( scope: punctuation.section.group.begin.c++ set: members-inside-function-call - match: (?=\S) # safety pop pop: true - include: expressions # Explicit base-class access - match: ({{identifier}})\s*(::) captures: 1: variable.other.base-class.c++ 2: punctuation.accessor.double-colon.c++ set: members-after-accessor-junction # reset # Just a regular member variable - match: '{{identifier}}' scope: variable.other.readwrite.member.c++ pop: true members-dot: - include: scope:source.c#access-illegal # No lookahead required because members-dot goes after operators in the # early-expressions-after-generic-type context. This means triple dots # (i.e. "..." or "variadic") is attempted first. - match: \. scope: punctuation.accessor.dot.c++ push: members-after-accessor-junction members-arrow: # This needs to be before operators in the # early-expressions-after-generic-type context because otherwise the "->" # from the C language will match. - match: -> scope: punctuation.accessor.arrow.c++ push: members-after-accessor-junction typedef: - match: \btypedef\b scope: storage.type.c++ push: - match: ({{identifier}})?\s*(?=;) captures: 1: entity.name.type.typedef.c++ pop: true - match: \b(struct)\s+({{identifier}})\b captures: 1: storage.type.c++ - include: expressions-minus-generic-type parens: - match: \( scope: punctuation.section.group.begin.c++ push: - meta_scope: meta.group.c++ - match: \) scope: punctuation.section.group.end.c++ pop: true - include: expressions brackets: - match: \[ scope: punctuation.section.brackets.begin.c++ push: - meta_scope: meta.brackets.c++ - match: \] scope: punctuation.section.brackets.end.c++ pop: true - include: expressions function-trailing-return-type: - match: '{{non_angle_brackets}}' pop: true - include: angle-brackets - include: types - include: modifiers-parens - include: modifiers - include: identifiers - match: \*|& scope: keyword.operator.c++ - include: function-trailing-return-type-parens - match: '(?=\S)' pop: true function-trailing-return-type-parens: - match: \( scope: punctuation.section.group.begin.c++ push: - meta_scope: meta.group.c++ - match: \) scope: punctuation.section.group.end.c++ pop: true - include: function-trailing-return-type ## Detection of function and data structure definitions at the global level global-modifier: - include: comments - include: modifiers-parens - include: modifiers # Constructors and destructors don't have a type - match: '(?={{path_lookahead}}\s*::\s*{{identifier}}\s*(\(|$))' set: - meta_content_scope: meta.function.c++ entity.name.function.constructor.c++ - include: identifiers - match: '(?=[^\w\s])' set: function-definition-params - match: '(?={{path_lookahead}}\s*::\s*~{{identifier}}\s*(\(|$))' set: - meta_content_scope: meta.function.c++ entity.name.function.destructor.c++ - include: identifiers - match: '~{{identifier}}' - match: '(?=[^\w\s])' set: function-definition-params # If we see a path ending in :: before a newline, we don't know if it is # a constructor or destructor, or a long return type, so we are just going # to treat it like a regular function. Most likely it is a constructor, # since it doesn't seem most developers would create such a long typename. - match: '(?={{path_lookahead}}\s*::\s*$)' set: - meta_content_scope: meta.function.c++ entity.name.function.c++ - include: identifiers - match: '~{{identifier}}' - match: '(?=[^\w\s])' set: function-definition-params - include: unique-strings - match: '(?=\S)' set: global-type global-type: - include: comments - match: \*|& scope: keyword.operator.c++ - match: '(?=\b({{control_keywords}}|{{operator_keywords}}|{{casts}}|{{memory_operators}}|{{other_keywords}}|operator)\b)' pop: true - match: '(?=\s)' set: global-maybe-function # If a class/struct/enum followed by a name that is not a macro or declspec # then this is likely a return type of a function. This is uncommon. - match: |- (?x: ({{before_tag}}) \s+ (?= (?![[:upper:][:digit:]_]+\b|__declspec|{{before_tag}}) {{path_lookahead}} (\s+{{identifier}}\s*\(|\s*[*&]) ) ) captures: 1: storage.type.c++ set: - include: identifiers - match: '' set: global-maybe-function # The previous match handles return types of struct/enum/etc from a func, # there this one exits the context to allow matching an actual struct/class - match: '(?=\b({{before_tag}})\b)' set: data-structures - match: '(?=\b({{casts}})\b\s*<)' pop: true - match: '{{non_angle_brackets}}' pop: true - include: angle-brackets - include: types # Allow a macro call - match: '({{identifier}})\s*(\()(?=[^\)]+\))' captures: 1: variable.function.c++ 2: meta.group.c++ punctuation.section.group.begin.c++ push: - meta_scope: meta.function-call.c++ - meta_content_scope: meta.group.c++ - match: '\)' scope: meta.group.c++ punctuation.section.group.end.c++ pop: true - include: expressions - match: '(?={{path_lookahead}}\s*\()' set: - include: function-call - match: '' pop: true - include: variables - include: constants - include: identifiers - match: (?=\W) pop: true global-maybe-function: - include: comments # Consume pointer info, macros and any type info that was offset by macros - match: \*|& scope: keyword.operator.c++ - match: '(?=\b({{control_keywords}}|{{operator_keywords}}|{{casts}}|{{memory_operators}}|{{other_keywords}})\b)' pop: true - match: '\b({{type_qualifier}})\b' scope: storage.modifier.c++ - match: '{{non_angle_brackets}}' pop: true - include: angle-brackets - include: types - include: modifiers-parens - include: modifiers # All uppercase identifier just before a newline is most likely a macro - match: '[[:upper:][:digit:]_]+\s*$' # Operator overloading - match: '(?=({{path_lookahead}}\s*(?:{{generic_lookahead}})?::\s*)?{{operator_method_name}}\s*(\(|$))' set: - meta_content_scope: meta.function.c++ entity.name.function.c++ - include: identifiers - match: '(?=\s*(\(|$))' set: function-definition-params # Identifier that is not the function name - likely a macro or type - match: '(?={{path_lookahead}}([ \t]+|[*&])(?!\s*(<|::|\(|$)))' push: - include: identifiers - match: '' pop: true # Real function definition - match: '(?={{path_lookahead}}({{generic_lookahead}}({{path_lookahead}})?)\s*(\(|$))' set: [function-definition-params, global-function-identifier-generic] - match: '(?={{path_lookahead}}\s*(\(|$))' set: [function-definition-params, global-function-identifier] - match: '(?={{path_lookahead}}\s*::\s*$)' set: [function-definition-params, global-function-identifier] - match: '(?=\S)' pop: true global-function-identifier-generic: - include: angle-brackets - match: '::' scope: punctuation.accessor.c++ - match: '(?={{identifier}}<.*>\s*\()' push: - meta_content_scope: entity.name.function.c++ - include: identifiers - match: '(?=<)' pop: true - match: '(?={{identifier}}\s*\()' push: - meta_content_scope: entity.name.function.c++ - include: identifiers - match: '' pop: true - match: '(?=\()' pop: true global-function-identifier: - meta_content_scope: entity.name.function.c++ - include: identifiers - match: '(?=\S)' pop: true function-definition-params: - meta_content_scope: meta.function.c++ - include: comments - match: '(?=\()' set: - match: \( scope: meta.function.parameters.c++ meta.group.c++ punctuation.section.group.begin.c++ set: - meta_content_scope: meta.function.parameters.c++ meta.group.c++ - match : \) scope: punctuation.section.group.end.c++ set: function-definition-continue - match: '\bvoid\b' scope: storage.type.c++ - match: '{{identifier}}(?=\s*(\[|,|\)|=))' scope: variable.parameter.c++ - match: '=' scope: keyword.operator.assignment.c++ push: - match: '(?=,|\))' pop: true - include: expressions-minus-generic-type - include: scope:source.c#preprocessor-line-continuation - include: expressions-minus-generic-type - include: scope:source.c#preprocessor-line-continuation - match: (?=\S) pop: true function-definition-continue: - meta_content_scope: meta.function.c++ - include: comments - match: '(?=;)' pop: true - match: '->' scope: punctuation.separator.c++ set: function-definition-trailing-return - include: function-specifiers - match: '=' scope: keyword.operator.assignment.c++ - match: '&' scope: keyword.operator.c++ - match: \b0\b scope: constant.numeric.c++ - match: \b(default|delete)\b scope: storage.modifier.c++ - match: '(?=\{)' set: function-definition-body - match: '(?=\S)' pop: true function-definition-trailing-return: - include: comments - match: '(?=;)' pop: true - match: '(?=\{)' set: function-definition-body - include: function-specifiers - include: function-trailing-return-type function-definition-body: - meta_content_scope: meta.function.c++ meta.block.c++ - match: '\{' scope: punctuation.section.block.begin.c++ set: - meta_content_scope: meta.function.c++ meta.block.c++ - match: '\}' scope: meta.function.c++ meta.block.c++ punctuation.section.block.end.c++ pop: true - match: (?=^\s*#\s*(elif|else|endif)\b) pop: true - match: '(?=({{before_tag}})([^(;]+$|.*\{))' push: data-structures - include: statements ## Data structures including classes, structs, unions and enums data-structures: - match: '\bclass\b' scope: storage.type.c++ set: data-structures-class-definition # Detect variable type definitions using struct/enum/union followed by a tag - match: '\b({{before_tag}})(?=\s+{{path_lookahead}}\s+{{path_lookahead}}\s*[=;\[])' scope: storage.type.c++ - match: '\bstruct\b' scope: storage.type.c++ set: data-structures-struct-definition - match: '\benum(\s+(class|struct))?\b' scope: storage.type.c++ set: data-structures-enum-definition - match: '\bunion\b' scope: storage.type.c++ set: data-structures-union-definition - match: '(?=\S)' pop: true preprocessor-workaround-eat-macro-before-identifier: # Handle macros so they aren't matched as the class name - match: ({{macro_identifier}})(?=\s+~?{{identifier}}) captures: 1: meta.assumed-macro.c data-structures-class-definition: - meta_scope: meta.class.c++ - include: data-structures-definition-common-begin - match: '{{identifier}}(?={{data_structures_forward_decl_lookahead}})' scope: entity.name.class.forward-decl.c++ set: data-structures-class-definition-after-identifier - match: '(?={{path_lookahead}})' set: - meta_scope: meta.class.c++ - match: '{{identifier}}(?!\s*::)' scope: entity.name.class.c++ set: data-structures-class-definition-after-identifier - include: identifiers - match: '(?=[^\w\s])' set: data-structures-class-definition-after-identifier - match: '(?=[:{])' set: data-structures-class-definition-after-identifier - match: '(?=;)' pop: true data-structures-class-definition-after-identifier: - meta_content_scope: meta.class.c++ - include: data-structures-definition-common-begin # No matching of identifiers since they should all be macros at this point - include: data-structures-definition-common-end - match: '\{' scope: meta.block.c++ punctuation.section.block.begin.c++ set: - meta_content_scope: meta.class.c++ meta.block.c++ - match: '\}' scope: meta.class.c++ meta.block.c++ punctuation.section.block.end.c++ pop: true - include: data-structures-body data-structures-struct-definition: - meta_scope: meta.struct.c++ - include: data-structures-definition-common-begin - match: '{{identifier}}(?={{data_structures_forward_decl_lookahead}})' scope: entity.name.struct.forward-decl.c++ set: data-structures-struct-definition-after-identifier - match: '(?={{path_lookahead}})' set: - meta_scope: meta.struct.c++ - match: '{{identifier}}(?!\s*::)' scope: entity.name.struct.c++ set: data-structures-struct-definition-after-identifier - include: identifiers - match: '(?=[^\w\s])' set: data-structures-struct-definition-after-identifier - match: '(?=[:{])' set: data-structures-struct-definition-after-identifier - match: '(?=;)' pop: true data-structures-struct-definition-after-identifier: - meta_content_scope: meta.struct.c++ - include: data-structures-definition-common-begin # No matching of identifiers since they should all be macros at this point - include: data-structures-definition-common-end - match: '\{' scope: meta.block.c++ punctuation.section.block.begin.c++ set: - meta_content_scope: meta.struct.c++ meta.block.c++ - match: '\}' scope: meta.struct.c++ meta.block.c++ punctuation.section.block.end.c++ pop: true - include: data-structures-body data-structures-enum-definition: - meta_scope: meta.enum.c++ - include: data-structures-definition-common-begin - match: '{{identifier}}(?={{data_structures_forward_decl_lookahead}})' scope: entity.name.enum.forward-decl.c++ set: data-structures-enum-definition-after-identifier - match: '(?={{path_lookahead}})' set: - meta_scope: meta.enum.c++ - match: '{{identifier}}(?!\s*::)' scope: entity.name.enum.c++ set: data-structures-enum-definition-after-identifier - include: identifiers - match: '(?=[^\w\s])' set: data-structures-enum-definition-after-identifier - match: '(?=[:{])' set: data-structures-enum-definition-after-identifier - match: '(?=;)' pop: true data-structures-enum-definition-after-identifier: - meta_content_scope: meta.enum.c++ - include: data-structures-definition-common-begin # No matching of identifiers since they should all be macros at this point - include: data-structures-definition-common-end - match: '\{' scope: meta.block.c++ punctuation.section.block.begin.c++ set: - meta_content_scope: meta.enum.c++ meta.block.c++ # Enums don't support methods so we have a simplified body - match: '\}' scope: meta.enum.c++ meta.block.c++ punctuation.section.block.end.c++ pop: true - include: statements data-structures-union-definition: - meta_scope: meta.union.c++ - include: data-structures-definition-common-begin - match: '{{identifier}}(?={{data_structures_forward_decl_lookahead}})' scope: entity.name.union.forward-decl.c++ set: data-structures-union-definition-after-identifier - match: '(?={{path_lookahead}})' set: - meta_scope: meta.union.c++ - match: '{{identifier}}(?!\s*::)' scope: entity.name.union.c++ set: data-structures-union-definition-after-identifier - include: identifiers - match: '(?=[^\w\s])' set: data-structures-union-definition-after-identifier - match: '(?=[{])' set: data-structures-union-definition-after-identifier - match: '(?=;)' pop: true data-structures-union-definition-after-identifier: - meta_content_scope: meta.union.c++ - include: data-structures-definition-common-begin # No matching of identifiers since they should all be macros at this point # Unions don't support base classes - include: angle-brackets - match: '\{' scope: meta.block.c++ punctuation.section.block.begin.c++ set: - meta_content_scope: meta.union.c++ meta.block.c++ - match: '\}' scope: meta.union.c++ meta.block.c++ punctuation.section.block.end.c++ pop: true - include: data-structures-body - match: '(?=;)' pop: true data-structures-definition-common-begin: - include: comments - match: '(?=\b(?:{{before_tag}}|{{control_keywords}})\b)' pop: true - include: preprocessor-other - include: modifiers-parens - include: modifiers - include: preprocessor-workaround-eat-macro-before-identifier data-structures-definition-common-end: - include: angle-brackets - match: \bfinal\b scope: storage.modifier.c++ - match: ':' scope: punctuation.separator.c++ push: - include: comments - include: preprocessor-other - include: modifiers-parens - include: modifiers - match: '\b(virtual|{{visibility_modifiers}})\b' scope: storage.modifier.c++ - match: (?={{path_lookahead}}) push: - meta_scope: entity.other.inherited-class.c++ - include: identifiers - match: '' pop: true - include: angle-brackets - match: ',' scope: punctuation.separator.c++ - match: (?=\{|;) pop: true - match: '(?=;)' pop: true data-structures-body: - include: preprocessor-data-structures - match: '(?=\btemplate\b)' push: - include: template - match: (?=\S) set: data-structures-modifier - include: typedef - match: \b({{visibility_modifiers}})\s*(:)(?!:) captures: 1: storage.modifier.c++ 2: punctuation.section.class.c++ - match: '^\s*(?=(?:~?\w+|::))' push: data-structures-modifier - include: expressions-minus-generic-type data-structures-modifier: - match: '\bfriend\b' scope: storage.modifier.c++ push: - match: (?=;) pop: true - match: '\{' scope: punctuation.section.block.begin.c++ set: - meta_scope: meta.block.c++ - match: '\}' scope: punctuation.section.block.end.c++ pop: true - include: statements - match: '\b({{before_tag}})\b' scope: storage.type.c++ - include: expressions-minus-function-call - include: comments - include: modifiers-parens - include: modifiers - match: '\bstatic_assert(?=\s*\()' scope: meta.static-assert.c++ keyword.operator.word.c++ push: - match: '\(' scope: meta.group.c++ punctuation.section.group.begin.c++ set: - meta_content_scope: meta.function-call.c++ meta.group.c++ - match: '\)' scope: meta.function-call.c++ meta.group.c++ punctuation.section.group.end.c++ pop: true - include: expressions # Destructor - match: '(?:{{identifier}}\s*(::)\s*)?~{{identifier}}(?=\s*(\(|$))' scope: meta.method.destructor.c++ entity.name.function.destructor.c++ captures: 1: punctuation.accessor.c++ set: method-definition-params # It's a macro, not a constructor if there is no type in the first param - match: '({{identifier}})\s*(\()(?=\s*(?!void){{identifier}}\s*[),])' captures: 1: variable.function.c++ 2: meta.group.c++ punctuation.section.group.begin.c++ push: - meta_scope: meta.function-call.c++ - meta_content_scope: meta.group.c++ - match: '\)' scope: meta.group.c++ punctuation.section.group.end.c++ pop: true - include: expressions # Constructor - include: preprocessor-workaround-eat-macro-before-identifier - match: '((?!{{before_tag}}|template){{identifier}})(?=\s*\()' scope: meta.method.constructor.c++ entity.name.function.constructor.c++ set: method-definition-params # Long form constructor - match: '({{identifier}}\s*(::)\s*{{identifier}})(?=\s*\()' captures: 1: meta.method.constructor.c++ entity.name.function.constructor.c++ 2: punctuation.accessor.c++ push: method-definition-params - match: '(?=\S)' set: data-structures-type data-structures-type: - include: comments - match: \*|& scope: keyword.operator.c++ # Cast methods - match: '(operator)\s+({{identifier}})(?=\s*(\(|$))' captures: 1: keyword.control.c++ 2: meta.method.c++ entity.name.function.c++ set: method-definition-params - match: '(?=\b({{control_keywords}}|{{operator_keywords}}|{{casts}}|{{memory_operators}}|{{other_keywords}}|operator)\b)' pop: true - match: '(?=\s)' set: data-structures-maybe-method # If a class/struct/enum followed by a name that is not a macro or declspec # then this is likely a return type of a function. This is uncommon. - match: |- (?x: ({{before_tag}}) \s+ (?= (?![[:upper:][:digit:]_]+\b|__declspec|{{before_tag}}) {{path_lookahead}} (\s+{{identifier}}\s*\(|\s*[*&]) ) ) captures: 1: storage.type.c++ set: - include: identifiers - match: '' set: data-structures-maybe-method # The previous match handles return types of struct/enum/etc from a func, # there this one exits the context to allow matching an actual struct/class - match: '(?=\b({{before_tag}})\b)' set: data-structures - match: '(?=\b({{casts}})\b\s*<)' pop: true - match: '{{non_angle_brackets}}' pop: true - include: angle-brackets - include: types - include: variables - include: constants - include: identifiers - match: (?=[&*]) set: data-structures-maybe-method - match: (?=\W) pop: true data-structures-maybe-method: - include: comments # Consume pointer info, macros and any type info that was offset by macros - match: \*|& scope: keyword.operator.c++ - match: '(?=\b({{control_keywords}}|{{operator_keywords}}|{{casts}}|{{memory_operators}}|{{other_keywords}})\b)' pop: true - match: '\b({{type_qualifier}})\b' scope: storage.modifier.c++ - match: '{{non_angle_brackets}}' pop: true - include: angle-brackets - include: types - include: modifiers-parens - include: modifiers # Operator overloading - match: '{{operator_method_name}}(?=\s*(\(|$))' scope: meta.method.c++ entity.name.function.c++ set: method-definition-params # Identifier that is not the function name - likely a macro or type - match: '(?={{path_lookahead}}([ \t]+|[*&])(?!\s*(<|::|\()))' push: - include: identifiers - match: '' pop: true # Real function definition - match: '(?={{path_lookahead}}({{generic_lookahead}})\s*(\())' set: [method-definition-params, data-structures-function-identifier-generic] - match: '(?={{path_lookahead}}\s*(\())' set: [method-definition-params, data-structures-function-identifier] - match: '(?={{path_lookahead}}\s*::\s*$)' set: [method-definition-params, data-structures-function-identifier] - match: '(?=\S)' pop: true data-structures-function-identifier-generic: - include: angle-brackets - match: '(?={{identifier}})' push: - meta_content_scope: entity.name.function.c++ - include: identifiers - match: '(?=<)' pop: true - match: '(?=\()' pop: true data-structures-function-identifier: - meta_content_scope: entity.name.function.c++ - include: identifiers - match: '(?=\S)' pop: true method-definition-params: - meta_content_scope: meta.method.c++ - include: comments - match: '(?=\()' set: - match: \( scope: meta.method.parameters.c++ meta.group.c++ punctuation.section.group.begin.c++ set: - meta_content_scope: meta.method.parameters.c++ meta.group.c++ - match : \) scope: punctuation.section.group.end.c++ set: method-definition-continue - match: '\bvoid\b' scope: storage.type.c++ - match: '{{identifier}}(?=\s*(\[|,|\)|=))' scope: variable.parameter.c++ - match: '=' scope: keyword.operator.assignment.c++ push: - match: '(?=,|\))' pop: true - include: expressions-minus-generic-type - include: expressions-minus-generic-type - match: '(?=\S)' pop: true method-definition-continue: - meta_content_scope: meta.method.c++ - include: comments - match: '(?=;)' pop: true - match: '->' scope: punctuation.separator.c++ set: method-definition-trailing-return - include: function-specifiers - match: '=' scope: keyword.operator.assignment.c++ - match: '&' scope: keyword.operator.c++ - match: \b0\b scope: constant.numeric.c++ - match: \b(default|delete)\b scope: storage.modifier.c++ - match: '(?=:)' set: - match: ':' scope: punctuation.separator.initializer-list.c++ set: - meta_scope: meta.method.constructor.initializer-list.c++ - match: '{{identifier}}' scope: variable.other.readwrite.member.c++ push: - match: \( scope: meta.group.c++ punctuation.section.group.begin.c++ set: - meta_content_scope: meta.group.c++ - match: \) scope: meta.group.c++ punctuation.section.group.end.c++ pop: true - include: expressions - match: \{ scope: meta.group.c++ punctuation.section.group.begin.c++ set: - meta_content_scope: meta.group.c++ - match: \} scope: meta.group.c++ punctuation.section.group.end.c++ pop: true - include: expressions - include: comments - match: (?=\{|;) set: method-definition-continue - include: expressions - match: '(?=\{)' set: method-definition-body - match: '(?=\S)' pop: true method-definition-trailing-return: - include: comments - match: '(?=;)' pop: true - match: '(?=\{)' set: method-definition-body - include: function-specifiers - include: function-trailing-return-type method-definition-body: - meta_content_scope: meta.method.c++ meta.block.c++ - match: '\{' scope: punctuation.section.block.begin.c++ set: - meta_content_scope: meta.method.c++ meta.block.c++ - match: '\}' scope: meta.method.c++ meta.block.c++ punctuation.section.block.end.c++ pop: true - match: (?=^\s*#\s*(elif|else|endif)\b) pop: true - match: '(?=({{before_tag}})([^(;]+$|.*\{))' push: data-structures - include: statements ## Preprocessor for data-structures preprocessor-data-structures: - include: preprocessor-rule-enabled-data-structures - include: preprocessor-rule-disabled-data-structures - include: preprocessor-practical-workarounds preprocessor-rule-disabled-data-structures: - match: ^\s*((#if)\s+(0))\b captures: 1: meta.preprocessor.c++ 2: keyword.control.import.c++ 3: constant.numeric.preprocessor.c++ push: - match: ^\s*(#\s*endif)\b captures: 1: meta.preprocessor.c++ keyword.control.import.c++ pop: true - match: ^\s*(#\s*else)\b captures: 1: meta.preprocessor.c++ keyword.control.import.else.c++ push: - match: (?=^\s*#\s*endif\b) pop: true - include: negated-block - include: data-structures-body - match: "" push: - meta_scope: comment.block.preprocessor.if-branch.c++ - match: (?=^\s*#\s*(else|endif)\b) pop: true - include: scope:source.c#preprocessor-disabled preprocessor-rule-enabled-data-structures: - match: ^\s*((#if)\s+(0*1))\b captures: 1: meta.preprocessor.c++ 2: keyword.control.import.c++ 3: constant.numeric.preprocessor.c++ push: - match: ^\s*(#\s*endif)\b captures: 1: meta.preprocessor.c++ keyword.control.import.c++ pop: true - match: ^\s*(#\s*else)\b captures: 1: meta.preprocessor.c++ keyword.control.import.else.c++ push: - meta_content_scope: comment.block.preprocessor.else-branch.c++ - match: (?=^\s*#\s*endif\b) pop: true - include: scope:source.c#preprocessor-disabled - match: "" push: - match: (?=^\s*#\s*(else|endif)\b) pop: true - include: negated-block - include: data-structures-body ## Preprocessor for global preprocessor-global: - include: preprocessor-rule-enabled-global - include: preprocessor-rule-disabled-global - include: preprocessor-rule-other-global preprocessor-statements: - include: preprocessor-rule-enabled-statements - include: preprocessor-rule-disabled-statements - include: preprocessor-rule-other-statements preprocessor-expressions: - include: scope:source.c#incomplete-inc - include: preprocessor-macro-define - include: scope:source.c#pragma-mark - include: preprocessor-other preprocessor-rule-disabled-global: - match: ^\s*((#if)\s+(0))\b captures: 1: meta.preprocessor.c++ 2: keyword.control.import.c++ 3: constant.numeric.preprocessor.c++ push: - match: ^\s*(#\s*endif)\b captures: 1: meta.preprocessor.c++ keyword.control.import.c++ pop: true - match: ^\s*(#\s*else)\b captures: 1: meta.preprocessor.c++ keyword.control.import.else.c++ push: - match: (?=^\s*#\s*endif\b) pop: true - include: preprocessor-global - include: negated-block - include: global - match: "" push: - meta_scope: comment.block.preprocessor.if-branch.c++ - match: (?=^\s*#\s*(else|endif)\b) pop: true - include: scope:source.c#preprocessor-disabled preprocessor-rule-enabled-global: - match: ^\s*((#if)\s+(0*1))\b captures: 1: meta.preprocessor.c++ 2: keyword.control.import.c++ 3: constant.numeric.preprocessor.c++ push: - match: ^\s*(#\s*endif)\b captures: 1: meta.preprocessor.c++ keyword.control.import.c++ pop: true - match: ^\s*(#\s*else)\b captures: 1: meta.preprocessor.c++ keyword.control.import.else.c++ push: - meta_content_scope: comment.block.preprocessor.else-branch.c++ - match: (?=^\s*#\s*endif\b) pop: true - include: scope:source.c#preprocessor-disabled - match: "" push: - match: (?=^\s*#\s*(else|endif)\b) pop: true - include: preprocessor-global - include: negated-block - include: global preprocessor-rule-other-global: - match: ^\s*(#\s*(?:if|ifdef|ifndef))\b captures: 1: keyword.control.import.c++ push: - meta_scope: meta.preprocessor.c++ - include: scope:source.c#preprocessor-line-continuation - include: scope:source.c#preprocessor-comments - match: \bdefined\b scope: keyword.control.c++ # Enter a new scope where all elif/else branches have their # contexts popped by a subsequent elif/else/endif. This ensures that # preprocessor branches don't push multiple meta.block scopes on # the stack, thus messing up the "global" context's detection of # functions. - match: $\n set: preprocessor-if-branch-global # These gymnastics here ensure that we are properly handling scope even # when the preprocessor is used to create different scope beginnings, such # as a different if/while condition preprocessor-if-branch-global: - match: ^\s*(#\s*endif)\b captures: 1: meta.preprocessor.c++ keyword.control.import.c++ pop: true - match: (?=^\s*#\s*(elif|else)\b) push: preprocessor-elif-else-branch-global - match: \{ scope: punctuation.section.block.begin.c++ set: preprocessor-block-if-branch-global - include: preprocessor-global - include: negated-block - include: global preprocessor-block-if-branch-global: - meta_scope: meta.block.c++ - match: ^\s*(#\s*endif)\b captures: 1: meta.preprocessor.c++ keyword.control.import.c++ set: preprocessor-block-finish-global - match: (?=^\s*#\s*(elif|else)\b) push: preprocessor-elif-else-branch-global - match: \} scope: punctuation.section.block.end.c++ set: preprocessor-if-branch-global - include: statements preprocessor-block-finish-global: - meta_scope: meta.block.c++ - match: ^\s*(#\s*(?:if|ifdef|ifndef))\b captures: 1: meta.preprocessor.c++ keyword.control.import.c++ set: preprocessor-block-finish-if-branch-global - match: \} scope: punctuation.section.block.end.c++ pop: true - include: statements preprocessor-block-finish-if-branch-global: - match: ^\s*(#\s*endif)\b captures: 1: keyword.control.import.c++ pop: true - match: \} scope: punctuation.section.block.end.c++ set: preprocessor-if-branch-global - include: statements preprocessor-elif-else-branch-global: - match: (?=^\s*#\s*(endif)\b) pop: true - include: preprocessor-global - include: negated-block - include: global ## Preprocessor for statements preprocessor-rule-disabled-statements: - match: ^\s*((#if)\s+(0))\b captures: 1: meta.preprocessor.c++ 2: keyword.control.import.c++ 3: constant.numeric.preprocessor.c++ push: - match: ^\s*(#\s*endif)\b captures: 1: meta.preprocessor.c++ keyword.control.import.c++ pop: true - match: ^\s*(#\s*else)\b captures: 1: meta.preprocessor.c++ keyword.control.import.else.c++ push: - match: (?=^\s*#\s*endif\b) pop: true - include: negated-block - include: statements - match: "" push: - meta_scope: comment.block.preprocessor.if-branch.c++ - match: (?=^\s*#\s*(else|endif)\b) pop: true - include: scope:source.c#preprocessor-disabled preprocessor-rule-enabled-statements: - match: ^\s*((#if)\s+(0*1))\b captures: 1: meta.preprocessor.c++ 2: keyword.control.import.c++ 3: constant.numeric.preprocessor.c++ push: - match: ^\s*(#\s*endif)\b captures: 1: meta.preprocessor.c++ keyword.control.import.c++ pop: true - match: ^\s*(#\s*else)\b captures: 1: meta.preprocessor.c++ keyword.control.import.else.c++ push: - meta_content_scope: comment.block.preprocessor.else-branch.c++ - match: (?=^\s*#\s*endif\b) pop: true - include: scope:source.c#preprocessor-disabled - match: "" push: - match: (?=^\s*#\s*(else|endif)\b) pop: true - include: negated-block - include: statements preprocessor-rule-other-statements: - match: ^\s*(#\s*(?:if|ifdef|ifndef))\b captures: 1: keyword.control.import.c++ push: - meta_scope: meta.preprocessor.c++ - include: scope:source.c#preprocessor-line-continuation - include: scope:source.c#preprocessor-comments - match: \bdefined\b scope: keyword.control.c++ # Enter a new scope where all elif/else branches have their # contexts popped by a subsequent elif/else/endif. This ensures that # preprocessor branches don't push multiple meta.block scopes on # the stack, thus messing up the "global" context's detection of # functions. - match: $\n set: preprocessor-if-branch-statements # These gymnastics here ensure that we are properly handling scope even # when the preprocessor is used to create different scope beginnings, such # as a different if/while condition preprocessor-if-branch-statements: - match: ^\s*(#\s*endif)\b captures: 1: meta.preprocessor.c++ keyword.control.import.c++ pop: true - match: (?=^\s*#\s*(elif|else)\b) push: preprocessor-elif-else-branch-statements - match: \{ scope: punctuation.section.block.begin.c++ set: preprocessor-block-if-branch-statements - match: (?=(?!{{non_func_keywords}}){{path_lookahead}}\s*\() set: preprocessor-if-branch-function-call - include: negated-block - include: statements preprocessor-if-branch-function-call: - meta_content_scope: meta.function-call.c++ - include: scope:source.c#c99 - match: '(?:(::)\s*)?{{identifier}}\s*(::)\s*' scope: variable.function.c++ captures: 1: punctuation.accessor.c++ 2: punctuation.accessor.c++ - match: '(?:(::)\s*)?{{identifier}}' scope: variable.function.c++ captures: 1: punctuation.accessor.c++ - match: '\(' scope: meta.group.c++ punctuation.section.group.begin.c++ set: preprocessor-if-branch-function-call-arguments preprocessor-if-branch-function-call-arguments: - meta_content_scope: meta.function-call.c++ meta.group.c++ - match : \) scope: meta.function-call.c++ meta.group.c++ punctuation.section.group.end.c++ set: preprocessor-if-branch-statements - match: ^\s*(#\s*(?:elif|else))\b captures: 1: meta.preprocessor.c++ keyword.control.import.c++ set: preprocessor-if-branch-statements - match: ^\s*(#\s*endif)\b captures: 1: meta.preprocessor.c++ keyword.control.import.c++ set: preprocessor-if-branch-function-call-arguments-finish - include: expressions preprocessor-if-branch-function-call-arguments-finish: - meta_content_scope: meta.function-call.c++ meta.group.c++ - match: \) scope: meta.function-call.c++ meta.group.c++ punctuation.section.group.end.c++ pop: true - include: expressions preprocessor-block-if-branch-statements: - meta_scope: meta.block.c++ - match: ^\s*(#\s*endif)\b captures: 1: meta.preprocessor.c++ keyword.control.import.c++ set: preprocessor-block-finish-statements - match: (?=^\s*#\s*(elif|else)\b) push: preprocessor-elif-else-branch-statements - match: \} scope: punctuation.section.block.end.c++ set: preprocessor-if-branch-statements - include: statements preprocessor-block-finish-statements: - meta_scope: meta.block.c++ - match: ^\s*(#\s*(?:if|ifdef|ifndef))\b captures: 1: meta.preprocessor.c++ keyword.control.import.c++ set: preprocessor-block-finish-if-branch-statements - match: \} scope: punctuation.section.block.end.c++ pop: true - include: statements preprocessor-block-finish-if-branch-statements: - match: ^\s*(#\s*endif)\b captures: 1: keyword.control.import.c++ pop: true - match: \} scope: meta.block.c++ punctuation.section.block.end.c++ set: preprocessor-if-branch-statements - include: statements preprocessor-elif-else-branch-statements: - match: (?=^\s*#\s*endif\b) pop: true - include: negated-block - include: statements ## Preprocessor other negated-block: - match: '\}' scope: punctuation.section.block.end.c++ push: - match: '\{' scope: punctuation.section.block.begin.c++ pop: true - match: (?=^\s*#\s*(elif|else|endif)\b) pop: true - include: statements preprocessor-macro-define: - match: ^\s*(\#\s*define)\b captures: 1: meta.preprocessor.macro.c++ keyword.control.import.define.c++ push: - meta_content_scope: meta.preprocessor.macro.c++ - include: scope:source.c#preprocessor-line-continuation - include: scope:source.c#preprocessor-line-ending - include: scope:source.c#preprocessor-comments - match: '({{identifier}})(?=\()' scope: entity.name.function.preprocessor.c++ set: - match: '\(' scope: punctuation.section.group.begin.c++ set: preprocessor-macro-params - match: '{{identifier}}' scope: entity.name.constant.preprocessor.c++ set: preprocessor-macro-definition preprocessor-macro-params: - meta_scope: meta.preprocessor.macro.parameters.c++ meta.group.c++ - match: '{{identifier}}' scope: variable.parameter.c++ - match: \) scope: punctuation.section.group.end.c++ set: preprocessor-macro-definition - match: ',' scope: punctuation.separator.c++ push: - match: '{{identifier}}' scope: variable.parameter.c++ pop: true - include: scope:source.c#preprocessor-line-continuation - include: scope:source.c#preprocessor-comments - match: '\.\.\.' scope: keyword.operator.variadic.c++ - match: '(?=\))' pop: true - match: (/\*).*(\*/) scope: comment.block.c++ captures: 1: punctuation.definition.comment.c++ 2: punctuation.definition.comment.c++ - match: '\S+' scope: invalid.illegal.unexpected-character.c++ - include: scope:source.c#preprocessor-line-continuation - include: scope:source.c#preprocessor-comments - match: '\.\.\.' scope: keyword.operator.variadic.c++ - match: (/\*).*(\*/) scope: comment.block.c++ captures: 1: punctuation.definition.comment.c++ 2: punctuation.definition.comment.c++ - match: $\n scope: invalid.illegal.unexpected-end-of-line.c++ preprocessor-macro-definition: - meta_content_scope: meta.preprocessor.macro.c++ - include: scope:source.c#preprocessor-line-continuation - include: scope:source.c#preprocessor-line-ending - include: scope:source.c#preprocessor-comments # Don't define blocks in define statements - match: '\{' scope: punctuation.section.block.begin.c++ - match: '\}' scope: punctuation.section.block.end.c++ - include: expressions preprocessor-practical-workarounds: - include: preprocessor-convention-ignore-uppercase-ident-lines - include: scope:source.c#preprocessor-convention-ignore-uppercase-calls-without-semicolon preprocessor-convention-ignore-uppercase-ident-lines: - match: ^(\s*{{macro_identifier}})+\s*$ scope: meta.assumed-macro.c++ push: # It's possible that we are dealing with a function return type on its own line, and the # name of the function is on the subsequent line. - match: '(?={{path_lookahead}}({{generic_lookahead}}({{path_lookahead}})?)\s*\()' set: [function-definition-params, global-function-identifier-generic] - match: '(?={{path_lookahead}}\s*\()' set: [function-definition-params, global-function-identifier] - match: ^ pop: true preprocessor-other: - match: ^\s*(#\s*(?:if|ifdef|ifndef|elif|else|line|pragma|undef))\b captures: 1: keyword.control.import.c++ push: - meta_scope: meta.preprocessor.c++ - include: scope:source.c#preprocessor-line-continuation - include: scope:source.c#preprocessor-line-ending - include: scope:source.c#preprocessor-comments - match: \bdefined\b scope: keyword.control.c++ - match: ^\s*(#\s*endif)\b captures: 1: meta.preprocessor.c++ keyword.control.import.c++ - match: ^\s*(#\s*(?:error|warning))\b captures: 1: keyword.control.import.error.c++ push: - meta_scope: meta.preprocessor.diagnostic.c++ - include: scope:source.c#preprocessor-line-continuation - include: scope:source.c#preprocessor-line-ending - include: scope:source.c#preprocessor-comments - include: strings - match: '\S+' scope: string.unquoted.c++ - match: ^\s*(#\s*(?:include|include_next|import))\b captures: 1: keyword.control.import.include.c++ push: - meta_scope: meta.preprocessor.include.c++ - include: scope:source.c#preprocessor-line-continuation - include: scope:source.c#preprocessor-line-ending - include: scope:source.c#preprocessor-comments - match: '"' scope: punctuation.definition.string.begin.c++ push: - meta_scope: string.quoted.double.include.c++ - match: '"' scope: punctuation.definition.string.end.c++ pop: true - match: < scope: punctuation.definition.string.begin.c++ push: - meta_scope: string.quoted.other.lt-gt.include.c++ - match: '>' scope: punctuation.definition.string.end.c++ pop: true - include: preprocessor-practical-workarounds