Skip to content

Instantly share code, notes, and snippets.

@ziggi
Last active November 3, 2025 17:56
Show Gist options
  • Select an option

  • Save ziggi/016d5f9a66e3f87ccbaedaa527d155d8 to your computer and use it in GitHub Desktop.

Select an option

Save ziggi/016d5f9a66e3f87ccbaedaa527d155d8 to your computer and use it in GitHub Desktop.
pawn.sublime-syntax
%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
name: pawn
file_extensions:
- pawn
- inc
- p
scope: source.c
variables:
# number exponents
dec_exponent: '(?:[eE][-+]??\d+)'
hex_exponent: '(?:[pP][-+]??\d+)'
# number suffixes
dec_suffix: '[a-zA-Z_][[:alnum:]_]*'
hex_suffix: '[g-zG-Z_][[:alnum:]_]*'
integer_suffix: '[lL]{1,2}[uU]?|[uU][lL]{0,2}'
identifier: \b[[:alpha:]_][[:alnum:]_]*\b # upper and lowercase
define_identifier: '[\w\(\,\s%]([\w\d]+)\b'
macro_identifier: \b[[:upper:]_][[:upper:][:digit:]_]{2,}\b # only uppercase, at least 3 chars
control_keywords: 'break|case|continue|default|do|else|for|goto|if|return|switch|while|state|assert|sleep'
basic_types: 'new|asm|__asm__|auto|bool|_Bool|Float|char|_Complex|double|float|_Imaginary|int|long|short|signed|unsigned|void'
before_tag: 'enum'
microsoft_types: '__int8|__int16|__int32|__int64'
windows_types: 'APIENTRY|ATOM|BOOL|BOOLEAN|BYTE|CALLBACK|CCHAR|CHAR|COLORREF|CONST|DWORD|DWORDLONG|DWORD_PTR|DWORD32|DWORD64|FLOAT|HACCEL|HALF_PTR|HANDLE|HBITMAP|HBRUSH|HCOLORSPACE|HCONV|HCONVLIST|HCURSOR|HDC|HDDEDATA|HDESK|HDROP|HDWP|HENHMETAFILE|HFILE|HFONT|HGDIOBJ|HGLOBAL|HHOOK|HICON|HINSTANCE|HKEY|HKL|HLOCAL|HMENU|HMETAFILE|HMODULE|HMONITOR|HPALETTE|HPEN|HRESULT|HRGN|HRSRC|HSZ|HWINSTA|HWND|INT|INT_PTR|INT8|INT16|INT32|INT64|LANGID|LCID|LCTYPE|LGRPID|LONG|LONGLONG|LONG_PTR|LONG32|LONG64|LPARAM|LPBOOL|LPBYTE|LPCOLORREF|LPCSTR|LPCTSTR|LPCVOID|LPCWSTR|LPDWORD|LPHANDLE|LPINT|LPLONG|LPSTR|LPTSTR|LPVOID|LPWORD|LPWSTR|LRESULT|PBOOL|PBOOLEAN|PBYTE|PCHAR|PCSTR|PCTSTR|PCWSTR|PDWORD|PDWORDLONG|PDWORD_PTR|PDWORD32|PDWORD64|PFLOAT|PHALF_PTR|PHANDLE|PHKEY|PINT|PINT_PTR|PINT8|PINT16|PINT32|PINT64|PLCID|PLONG|PLONGLONG|PLONG_PTR|PLONG32|PLONG64|POINTER_32|POINTER_64|POINTER_SIGNED|POINTER_UNSIGNED|PSHORT|PSIZE_T|PSSIZE_T|PSTR|PTBYTE|PTCHAR|PTSTR|PUCHAR|PUHALF_PTR|PUINT|PUINT_PTR|PUINT8|PUINT16|PUINT32|PUINT64|PULONG|PULONGLONG|PULONG_PTR|PULONG32|PULONG64|PUSHORT|PVOID|PWCHAR|PWORD|PWSTR|QWORD|SC_HANDLE|SC_LOCK|SERVICE_STATUS_HANDLE|SHORT|SIZE_T|SSIZE_T|TBYTE|TCHAR|UCHAR|UHALF_PTR|UINT|UINT_PTR|UINT8|UINT16|UINT32|UINT64|ULONG|ULONGLONG|ULONG_PTR|ULONG32|ULONG64|UNICODE_STRING|USHORT|USN|VOID|WCHAR|WINAPI|WORD|WPARAM'
stdint: 'int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|int_least8_t|int_least16_t|int_least32_t|int_least64_t|uint_least8_t|uint_least16_t|uint_least32_t|uint_least64_t|int_fast8_t|int_fast16_t|int_fast32_t|int_fast64_t|uint_fast8_t|uint_fast16_t|uint_fast32_t|uint_fast64_t|intptr_t|uintptr_t|intmax_t|intmax_t|uintmax_t|uintmax_t'
declspec: '__declspec\(\s*\w+(?:\([^)]+\))?\s*\)'
modifiers: 'public|forward|native|char|const|static|stock'
non_func_keywords: 'if|for|switch|while|decltype|sizeof|__declspec|__attribute__'
contexts:
main:
- include: preprocessor-global
- include: global
#############################################################################
# Reusable contexts
#
# The follow contexts are currently constructed to be reused in the C++
# syntax. They are specifically constructed to not push into sub-contexts,
# which ensures that C++ code isn't accidentally lexed as plain C. They also
# should not use the {{identifier}} variable since that is different for C++.
#############################################################################
comments:
- match: ^/\* =(\s*.*?)\s*= \*/$\n?
scope: comment.block.c
captures:
1: meta.toc-list.banner.block.c
- match: /\*
scope: punctuation.definition.comment.c
push:
- meta_scope: comment.block.c
- match: \*/
scope: punctuation.definition.comment.c
pop: true
- match: ^\s*(\*)(?!/)
captures:
1: punctuation.definition.comment.c
- match: \*/(?!\*)
scope: invalid.illegal.stray-comment-end.c
- match: ^// =(\s*.*?)\s*=\s*$\n?
scope: comment.line.banner.c
captures:
1: meta.toc-list.banner.line.c
- match: //
scope: punctuation.definition.comment.c
push:
- meta_scope: comment.line.double-slash.c
- match: '(\\)$\n'
captures:
1: punctuation.separator.continuation.c
- match: \n
pop: true
strings:
- match: '(L|u8|u|U)?(")'
captures:
1: storage.type.string.c
2: punctuation.definition.string.begin.c
push:
- meta_scope: string.quoted.double.c
- match: '"'
scope: punctuation.definition.string.end.c
pop: true
- include: string_escaped_char
- include: string_placeholder
- match: "(L|u8|u|U)?(')"
captures:
1: storage.type.string.c
2: punctuation.definition.string.begin.c
push:
- meta_scope: string.quoted.single.c
- match: "'"
scope: punctuation.definition.string.end.c
pop: true
- include: string_escaped_char
string_escaped_char:
- match: '(\\)$\n'
captures:
1: punctuation.separator.continuation.c
- match: \\(?:\\|[abefnrtv\'"?]|[0-3][0-9]{0,2}|[4-7][0-9]?|x[a-fA-F0-9]+|u[a-fA-F0-9]{4}|U[a-fA-F0-9]{8})
scope: constant.character.escape.c
- match: \\.
scope: invalid.illegal.unknown-escape.c
string_placeholder:
- match: |-
(?x)%
(\d+\$)? # field (argument #)
[#0\- +']* # flags
[,;:_]? # separator character (AltiVec)
((-?\d+)|\*(-?\d+\$)?)? # minimum field width
(\.((-?\d+)|\*(-?\d+\$)?)?)? # precision
(hh|h|ll|l|j|t|z|q|L|vh|vl|v|hv|hl)? # length modifier
(\[[^\]]+\]|[am]s|[diouxXDOUeEfFgGaACcSspn%]) # conversion type
scope: constant.other.placeholder.c
keywords:
- 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: \b({{control_keywords}})\b
scope: keyword.control.c
- match: \bsizeof\b
scope: keyword.operator.word.c
modifiers:
- match: \b({{modifiers}})\b
scope: storage.modifier.c
variables:
- match: '\bg[A-Z]\w*\b'
scope: variable.other.readwrite.global.mac-classic.c
- match: '\bs[A-Z]\w*\b'
scope: variable.other.readwrite.static.mac-classic.c
constants:
- match: \b(__func__|NULL|true|false|TRUE|FALSE)\b
scope: constant.language.c
- match: \b(__FILE__|__FUNCTION__|__LINE__)\b
scope: support.constant.c
# common C constant naming idiom -- kConstantVariable
- match: '\bk[A-Z]\w*\b'
scope: constant.other.variable.mac-classic.c
- match: \b(noErr|kNilOptions|kInvalidID|kVariableLengthArray)\b
scope: support.constant.mac-classic.c
c99:
- match: \b(hypot(f|l)?|s(scanf|ystem|nprintf|ca(nf|lb(n(f|l)?|ln(f|l)?))|i(n(h(f|l)?|f|l)?|gn(al|bit))|tr(s(tr|pn)|nc(py|at|mp)|c(spn|hr|oll|py|at|mp)|to(imax|d|u(l(l)?|max)|k|f|l(d|l)?)|error|pbrk|ftime|len|rchr|xfrm)|printf|et(jmp|vbuf|locale|buf)|qrt(f|l)?|w(scanf|printf)|rand)|n(e(arbyint(f|l)?|xt(toward(f|l)?|after(f|l)?))|an(f|l)?)|c(s(in(h(f|l)?|f|l)?|qrt(f|l)?)|cos(h(f)?|f|l)?|imag(f|l)?|t(ime|an(h(f|l)?|f|l)?)|o(s(h(f|l)?|f|l)?|nj(f|l)?|pysign(f|l)?)|p(ow(f|l)?|roj(f|l)?)|e(il(f|l)?|xp(f|l)?)|l(o(ck|g(f|l)?)|earerr)|a(sin(h(f|l)?|f|l)?|cos(h(f|l)?|f|l)?|tan(h(f|l)?|f|l)?|lloc|rg(f|l)?|bs(f|l)?)|real(f|l)?|brt(f|l)?)|t(ime|o(upper|lower)|an(h(f|l)?|f|l)?|runc(f|l)?|gamma(f|l)?|mp(nam|file))|i(s(space|n(ormal|an)|cntrl|inf|digit|u(nordered|pper)|p(unct|rint)|finite|w(space|c(ntrl|type)|digit|upper|p(unct|rint)|lower|al(num|pha)|graph|xdigit|blank)|l(ower|ess(equal|greater)?)|al(num|pha)|gr(eater(equal)?|aph)|xdigit|blank)|logb(f|l)?|max(div|abs))|di(v|fftime)|_Exit|unget(c|wc)|p(ow(f|l)?|ut(s|c(har)?|wc(har)?)|error|rintf)|e(rf(c(f|l)?|f|l)?|x(it|p(2(f|l)?|f|l|m1(f|l)?)?))|v(s(scanf|nprintf|canf|printf|w(scanf|printf))|printf|f(scanf|printf|w(scanf|printf))|w(scanf|printf)|a_(start|copy|end|arg))|qsort|f(s(canf|e(tpos|ek))|close|tell|open|dim(f|l)?|p(classify|ut(s|c|w(s|c))|rintf)|e(holdexcept|set(e(nv|xceptflag)|round)|clearexcept|testexcept|of|updateenv|r(aiseexcept|ror)|get(e(nv|xceptflag)|round))|flush|w(scanf|ide|printf|rite)|loor(f|l)?|abs(f|l)?|get(s|c|pos|w(s|c))|re(open|e|ad|xp(f|l)?)|m(in(f|l)?|od(f|l)?|a(f|l|x(f|l)?)?))|l(d(iv|exp(f|l)?)|o(ngjmp|cal(time|econv)|g(1(p(f|l)?|0(f|l)?)|2(f|l)?|f|l|b(f|l)?)?)|abs|l(div|abs|r(int(f|l)?|ound(f|l)?))|r(int(f|l)?|ound(f|l)?)|gamma(f|l)?)|w(scanf|c(s(s(tr|pn)|nc(py|at|mp)|c(spn|hr|oll|py|at|mp)|to(imax|d|u(l(l)?|max)|k|f|l(d|l)?|mbs)|pbrk|ftime|len|r(chr|tombs)|xfrm)|to(b|mb)|rtomb)|printf|mem(set|c(hr|py|mp)|move))|a(s(sert|ctime|in(h(f|l)?|f|l)?)|cos(h(f|l)?|f|l)?|t(o(i|f|l(l)?)|exit|an(h(f|l)?|2(f|l)?|f|l)?)|b(s|ort))|g(et(s|c(har)?|env|wc(har)?)|mtime)|r(int(f|l)?|ound(f|l)?|e(name|alloc|wind|m(ove|quo(f|l)?|ainder(f|l)?))|a(nd|ise))|b(search|towc)|m(odf(f|l)?|em(set|c(hr|py|mp)|move)|ktime|alloc|b(s(init|towcs|rtowcs)|towc|len|r(towc|len))))\b
scope: support.function.C99.c
types:
- match: \b({{basic_types}}|{{before_tag}})\b
scope: storage.type.c
- match: \b(u_char|u_short|u_int|u_long|ushort|uint|u_quad_t|quad_t|qaddr_t|caddr_t|daddr_t|dev_t|fixpt_t|blkcnt_t|blksize_t|gid_t|in_addr_t|in_port_t|ino_t|key_t|mode_t|nlink_t|id_t|pid_t|off_t|segsz_t|swblk_t|uid_t|id_t|clock_t|size_t|ssize_t|time_t|useconds_t|suseconds_t|ptrdiff_t)\b
scope: support.type.sys-types.c
- match: \b(pthread_attr_t|pthread_cond_t|pthread_condattr_t|pthread_mutex_t|pthread_mutexattr_t|pthread_once_t|pthread_rwlock_t|pthread_rwlockattr_t|pthread_t|pthread_key_t)\b
scope: support.type.pthread.c
- match: \b({{stdint}})\b
scope: support.type.stdint.c
- match: '\b({{microsoft_types}})\b'
scope: support.type.microsoft.c
- match: '\b({{windows_types}})\b'
scope: support.type.windows.c
- match: \b(AbsoluteTime|Boolean|Byte|ByteCount|ByteOffset|BytePtr|CompTimeValue|ConstLogicalAddress|ConstStrFileNameParam|ConstStringPtr|Duration|Fixed|FixedPtr|Float32|Float32Point|Float64|Float80|Float96|FourCharCode|Fract|FractPtr|Handle|ItemCount|LogicalAddress|OptionBits|OSErr|OSStatus|OSType|OSTypePtr|PhysicalAddress|ProcessSerialNumber|ProcessSerialNumberPtr|ProcHandle|Ptr|ResType|ResTypePtr|ShortFixed|ShortFixedPtr|SignedByte|SInt16|SInt32|SInt64|SInt8|Size|StrFileName|StringHandle|StringPtr|TimeBase|TimeRecord|TimeScale|TimeValue|TimeValue64|UInt16|UInt32|UInt64|UInt8|UniChar|UniCharCount|UniCharCountPtr|UniCharPtr|UnicodeScalarValue|UniversalProcHandle|UniversalProcPtr|UnsignedFixed|UnsignedFixedPtr|UnsignedWide|UTF16Char|UTF32Char|UTF8Char)\b
scope: support.type.mac-classic.c
numbers:
# https://en.cppreference.com/w/c/language/floating_constant
# decimal floats
- match: |-
(?x:
\b\d+
(?:
(?: (\.) (?: \d+ {{dec_exponent}}? | {{dec_exponent}} | (?=[^.])) | {{dec_exponent}} )
(?: ([fFlL])\b | ({{dec_suffix}})? ) | ([fF])\b
)
| (\.) \d+ {{dec_exponent}}? (?: ([fFlL])\b | ({{dec_suffix}})? )
)
scope: constant.numeric.float.decimal.c
captures:
1: punctuation.separator.decimal.c
2: storage.type.numeric.c
3: invalid.illegal.numeric.suffix.c
4: storage.type.numeric.c
5: punctuation.separator.decimal.c
6: storage.type.numeric.c
7: invalid.illegal.numeric.suffix.c
# hexadecimal float (C99)
- match: \b0[xX](?=[[:alnum:].]+?[pP])
scope: punctuation.definition.numeric.base.c
push:
- meta_include_prototype: false
- meta_scope: constant.numeric.float.hexadecimal.c
- match: '{{hex_exponent}}\b'
pop: true
- match: \.
scope: punctuation.separator.decimal.c
- match: \H
scope: invalid.illegal.numeric.digit.c
# https://en.cppreference.com/w/c/language/integer_constant
# hexadecimal integer
- match: \b0[xX]
scope: punctuation.definition.numeric.base.c
push:
- meta_include_prototype: false
- meta_scope: constant.numeric.integer.hexadecimal.c
- include: hexadecimal-suffix
# octal integer
- match: \b0(?=\d)
scope: punctuation.definition.numeric.base.c
push:
- meta_include_prototype: false
- meta_scope: constant.numeric.integer.octal.c
- match: '[89]'
scope: invalid.illegal.numeric.digit.c
- include: decimal-suffix
# decimal integer
- match: \b\d+
push:
- meta_include_prototype: false
- meta_scope: constant.numeric.integer.decimal.c
- include: decimal-suffix
decimal-suffix:
- match: (?:{{integer_suffix}})?\b
scope: storage.type.numeric.c
pop: true
- match: '{{dec_suffix}}'
scope: invalid.illegal.numeric.suffix.c
pop: true
hexadecimal-suffix:
- match: (?:{{integer_suffix}})?\b
scope: storage.type.numeric.c
pop: true
- match: '{{hex_suffix}}'
scope: invalid.illegal.numeric.suffix.c
pop: true
operators:
- match: (?:\+\+|--)
scope: keyword.operator.arithmetic.c
- match: '->'
scope: punctuation.accessor.c
- match: \+\=|-\=|\*\=|/\=|%\=|&\=|\|\=|\^\=|>>\=|<<\=
scope: keyword.operator.assignment.augmented.c
- match: <<|>>|&&|\|\|
scope: keyword.operator.arithmetic.c
- match: <\=|>\=|\=\=|<|>|\!\=
scope: keyword.operator.comparison.c
- match: \+|\-|/|%|\||\^|~|!
scope: keyword.operator.arithmetic.c
# These two operator can be both arithmetic and pointer/address related
- match: \*|&
scope: keyword.operator.c
- match: \=
scope: keyword.operator.assignment.c
# Negative lookahead prevents match :: when included in C++
- match: '\?|:(?!:)'
scope: keyword.operator.ternary.c
- match: '\.\.\.'
scope: keyword.operator.variadic.c
label:
- match: '^\s*((?!default){{identifier}})(:)(?!:)'
captures:
1: entity.name.label.c
2: punctuation.separator.c
preprocessor-disabled:
- match: ^\s*(#\s*if(n?def)?)\b
captures:
1: meta.preprocessor.c
push:
- match: ^\s*(#\s*endif)\b
captures:
1: meta.preprocessor.c
pop: true
- include: preprocessor-disabled
- include: pragma-mark
- include: pragma-mark
preprocessor-line-continuation:
- match: '(\\)$\n'
captures:
1: punctuation.separator.continuation.c
- match: \\(\s+?)$
captures:
1: invalid.illegal.space-after-continuation.c
preprocessor-line-ending:
- match: $\n
pop: true
# Comment handling in preprocessor directives are complicated by the fact
# that a single-line comment will normally consume the newline to prevent
# completions from being presented to the user. Additionally, a multi-line
# comment without a line continuation ends at the newline.
preprocessor-comments:
- match: /\*
scope: punctuation.definition.comment.c
push:
- meta_scope: comment.block.c
- match: '\\$\n'
scope: punctuation.separator.continuation.c
- match: \*/
scope: punctuation.definition.comment.c
pop: true
- match: //
scope: punctuation.definition.comment.c
push:
- meta_scope: comment.line.double-slash.c
- match: '(\\)$\n'
captures:
1: punctuation.separator.continuation.c
pop: true
- match: (?=\n)
pop: true
pragma-mark:
- match: ^\s*((#\s*pragma\s+mark)\s+(.*))
scope: meta.section.c
captures:
1: meta.preprocessor.c
2: keyword.control.import.pragma.c
3: meta.toc-list.pragma-mark.c
# Used by "inc" snippets to prevent double ##include
incomplete-inc:
- match: '^\s*(#i(nc?)?)\b\s*'
scope: meta.preprocessor.incomplete.c
#############################################################################
# The following are C-specific scopes that should not be reused. This is
# because they push into subcontexts and use variables that are C-specific.
#############################################################################
global:
- include: early-expressions
- match: '^\s*(?=\w+)'
push: global-modifier
- include: late-expressions
statements:
- include: preprocessor-statements
- include: label
- include: expressions
expressions:
- include: early-expressions
- include: late-expressions
early-expressions:
- include: preprocessor-expressions
- include: comments
- include: case-default
- include: typedef
- include: keywords-parens
- include: keywords
- include: numbers
- include: operators
- 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
late-expressions:
- include: modifiers-parens
- include: modifiers
- include: types
- include: function-call
- match: ';'
scope: punctuation.terminator.c
## C-specific contexts
global-modifier:
- include: comments
- include: modifiers-parens
- include: modifiers
- match: '(?=\S)'
set: global-type
global-type:
- include: comments
- match: \*
scope: keyword.operator.c
- match: |-
(?x:
({{before_tag}})
\s+
(?=
{{identifier}}
(\s+{{identifier}}(?!\s*[{=;])|\s*\*+)
)
)
captures:
1: storage.type.c
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/union
- match: '(?=\b({{before_tag}})\b)'
set: data-structures
- match: '(?=\b({{control_keywords}})\b)'
pop: true
- match: '(?=\s)'
set: global-maybe-function
# 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: (?={{identifier}}\s*\()
set:
- include: function-call
- match: ''
pop: true
- include: types
- match: '{{identifier}}'
- 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
- include: types
- include: modifiers-parens
- include: modifiers
# All uppercase identifier just before a newline is most likely a macro
- match: '[[:upper:][:digit:]_]+\s*$'
# Identifier that is not the function name - likely a macro
- match: '{{identifier}}(?!\s*(\(|$))'
# Real function definition
- match: '{{identifier}}(?=\s*(\(|$))'
scope: meta.function.c entity.name.function.c
set: function-definition-params
- 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
- include: expressions
- include: preprocessor-line-continuation
- match: (?=\S)
pop: true
function-definition-continue:
- meta_content_scope: meta.function.c
- include: comments
- match: '(?=;)'
pop: true
- match: \b(const|final|noexcept|override)\b
scope: storage.modifier.c
- match: '(?=\{)'
set: function-definition-body
- match: '(?=\S)'
pop: true
function-definition-body:
- meta_content_scope: meta.function.c
- match: '\{'
scope: meta.block.c 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*(elseif|else|endif)\b)
pop: true
- match: '(?=({{before_tag}})([^(;]+$|.*\{))'
push: data-structures
- include: statements
data-structures:
# Detect variable type definitions using struct/enum/union followed by a tag
- match: '\b({{before_tag}})(?=\s+{{identifier}}\s+{{identifier}}\s*[=;\[])'
scope: storage.type.c
- match: '\bstruct\b'
scope: storage.type.c
set: data-structures-struct-definition
- match: '\benum\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
data-structures-struct-definition:
- meta_scope: meta.struct.c
- include: data-structures-definition-common-begin
- include: data-structures-definition-common-macro
- match: '{{identifier}}(?=\s*;)'
scope: entity.name.struct.forward-decl.c
- match: '{{identifier}}'
scope: entity.name.struct.c
set: data-structures-struct-definition-after-name
- include: data-structures-struct-definition-block-start
- match: '(?=;)'
pop: true
data-structures-struct-definition-after-name:
- meta_scope: meta.struct.c
- include: data-structures-definition-common-begin
- match: '(?=;)'
pop: true
- include: data-structures-struct-definition-block-start
data-structures-struct-definition-block-start:
- 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
- include: data-structures-definition-common-macro
- match: '{{identifier}}(?=\s*;)'
scope: entity.name.enum.forward-decl.c
- match: '{{identifier}}'
scope: entity.name.enum.c
set: data-structures-enum-definition-after-name
- include: data-structures-enum-definition-block-start
- match: '(?=;)'
pop: true
data-structures-enum-definition-after-name:
- meta_scope: meta.enum.c
- include: data-structures-definition-common-begin
- match: '(?=;)'
pop: true
- include: data-structures-enum-definition-block-start
data-structures-enum-definition-block-start:
- 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: data-structures-body
data-structures-union-definition:
- meta_scope: meta.union.c
- include: data-structures-definition-common-begin
- include: data-structures-definition-common-macro
- match: '{{identifier}}(?=\s*;)'
scope: entity.name.union.forward-decl.c
- match: '{{identifier}}'
scope: entity.name.union.c
set: data-structures-union-definition-after-name
- include: data-structures-union-definition-block-start
- match: '(?=;)'
pop: true
data-structures-union-definition-after-name:
- meta_scope: meta.union.c
- include: data-structures-definition-common-begin
- match: '(?=;)'
pop: true
- include: data-structures-union-definition-block-start
data-structures-union-definition-block-start:
- 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
data-structures-definition-common-begin:
- include: comments
- match: '(?=\b(?:{{before_tag}}|{{control_keywords}})\b)'
pop: true
- include: modifiers-parens
- include: modifiers
data-structures-definition-common-macro:
# Handle macros so they aren't matched as the class name
- match: '\b[[:upper:][:digit:]_]+\b(?!\s*($|\{))'
data-structures-definition-common-end:
- match: '(?=;)'
pop: true
data-structures-body:
- include: preprocessor-data-structures
- match: '(?={{before_tag}})'
push: data-structures
- include: expressions
block:
- match: '\{'
scope: punctuation.section.block.begin.c
push:
- meta_scope: meta.block.c
- match: (?=^\s*#\s*(elseif|else|endif)\b)
pop: true
- match: '\}'
scope: punctuation.section.block.end.c
pop: true
- include: statements
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
case-default:
- match: '\b(default|case)\b'
scope: keyword.control.c
push:
- match: ':'
scope: punctuation.separator.c
pop: true
- include: expressions
modifiers-parens:
- 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
keywords-parens:
- match: '\b(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
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}})
captures:
1: storage.type.c
- include: expressions
function-call:
- match: (?={{identifier}}\s*\()
push:
- meta_content_scope: meta.function-call.c
- include: c99
- match: '{{identifier}}'
scope: variable.function.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
## Preprocessor for data-structures
preprocessor-data-structures:
- include: preprocessor-rule-enabled-data-structures
- include: preprocessor-rule-disabled-data-structures
preprocessor-rule-disabled-data-structures:
- match: ^\s*((#if)\s+(0))\b
captures:
1: meta.preprocessor.c
2: keyword.control.import.c
3: constant.numeric.integer.decimal.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: 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.integer.decimal.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: 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: incomplete-inc
- include: preprocessor-macro-define
- include: 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.integer.decimal.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: 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.integer.decimal.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: 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: preprocessor-line-continuation
- include: 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*(elseif|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*(elseif|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: meta.preprocessor.c 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: negated-block
- include: preprocessor-global
- 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.integer.decimal.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: 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.integer.decimal.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: 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: preprocessor-line-continuation
- include: 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*(elseif|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}}){{identifier}}\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: c99
- match: '{{identifier}}'
scope: variable.function.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*(?:elseif|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*(elseif|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: meta.preprocessor.c keyword.control.import.c
pop: true
- match: \}
scope: 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*(elseif|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: preprocessor-line-continuation
- include: preprocessor-line-ending
- include: preprocessor-comments
- match: '({{define_identifier}})(?=\()'
scope: entity.name.function.preprocessor.c
set:
- match: '\('
scope: punctuation.section.group.begin.c
set: preprocessor-macro-params
- match: '{{define_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: '{{define_identifier}}'
scope: variable.parameter.c
- match: \)
scope: punctuation.section.group.end.c
set: preprocessor-macro-definition
- match: ','
scope: punctuation.separator.c
push:
- match: '{{define_identifier}}'
scope: variable.parameter.c
pop: true
- include: preprocessor-line-continuation
- include: 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: preprocessor-line-continuation
- include: 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: preprocessor-line-continuation
- include: preprocessor-line-ending
- include: 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: 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: \s*({{identifier}})(?=\s*\()
captures:
1: meta.function.c entity.name.function.c
set: function-definition-params
- match: ^
pop: true
preprocessor-convention-ignore-uppercase-calls-without-semicolon:
- match: ^\s*({{macro_identifier}})\s*(\()(?=[^)]*\)\s*$)
captures:
1: variable.function.assumed-macro.c
2: punctuation.section.group.begin.c
push:
- meta_scope: meta.assumed-macro.c
- match: \)
scope: punctuation.section.group.end.c
pop: true
- include: expressions
preprocessor-other:
- match: ^\s*(#\s*(?:if|ifdef|ifndef|elseif|else|line|endinput|undef|pragma))\b
captures:
1: keyword.control.import.c
push:
- meta_scope: meta.preprocessor.c
- include: preprocessor-line-continuation
- include: preprocessor-line-ending
- include: 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: preprocessor-line-continuation
- include: preprocessor-line-ending
- include: preprocessor-comments
- include: strings
- match: '\S+'
scope: string.unquoted.c
- match: ^\s*(#\s*(?:include|tryinclude))\b
captures:
1: keyword.control.import.include.c
push:
- meta_scope: meta.preprocessor.include.c
- include: preprocessor-line-continuation
- include: preprocessor-line-ending
- include: 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment