@wooorm/starry-night
Version:
Syntax highlighting, like GitHub
644 lines (641 loc) • 23.4 kB
JavaScript
// This is a TextMate grammar distributed by `starry-night`.
// This grammar is developed at
// <https://github.com/godotengine/godot-vscode-plugin>
// and licensed `mit`.
// See <https://github.com/wooorm/starry-night> for more info.
/**
* @import {Grammar} from '@wooorm/starry-night'
*/
/** @type {Grammar} */
const grammar = {
extensions: [],
names: ['gdscript'],
patterns: [{include: '#statement'}, {include: '#expression'}],
repository: {
annotated_parameter: {
begin: '(?x)\n \\s* ([a-zA-Z_]\\w*) \\s* (:)\\s* ([a-zA-Z_]\\w*)? \n',
beginCaptures: {
1: {name: 'variable.parameter.function.language.gdscript'},
2: {name: 'punctuation.separator.annotation.gdscript'},
3: {name: 'entity.name.type.class.gdscript'}
},
end: '(,)|(?=\\))',
endCaptures: {1: {name: 'punctuation.separator.parameters.gdscript'}},
patterns: [
{include: '#expression'},
{match: '=(?!=)', name: 'keyword.operator.assignment.gdscript'}
]
},
annotations: {
captures: {
1: {name: 'entity.name.function.decorator.gdscript'},
2: {name: 'entity.name.function.decorator.gdscript'}
},
match:
'(@)(abstract|export|export_category|export_color_no_alpha|export_custom|export_dir|export_enum|export_exp_easing|export_file|export_file_path|export_flags|export_flags_2d_navigation|export_flags_2d_physics|export_flags_2d_render|export_flags_3d_navigation|export_flags_3d_physics|export_flags_3d_render|export_flags_avoidance|export_global_dir|export_global_file|export_group|export_multiline|export_node_path|export_placeholder|export_range|export_storage|export_subgroup|export_tool_button|icon|onready|rpc|static_unload|tool|warning_ignore|warning_ignore_restore|warning_ignore_start)\\b'
},
any_method: {
match: '\\b([A-Za-z_]\\w*)\\b(?=\\s*(?:[(]))',
name: 'entity.name.function.other.gdscript'
},
any_property: {
captures: {
1: {name: 'punctuation.accessor.gdscript'},
2: {name: 'constant.language.gdscript'},
3: {name: 'variable.other.property.gdscript'}
},
match:
'\\b(\\.)\\s*(?<![@\\$#%])(?:([A-Z_][A-Z_0-9]*)|([A-Za-z_]\\w*))\\b(?![(])'
},
any_variable: {
match: '\\b(?<![@\\$#%])([A-Za-z_]\\w*)\\b(?![(])',
name: 'variable.other.gdscript'
},
arithmetic_operator: {
match:
'->|\\+=|-=|\\*\\*=|\\*=|\\^=|/=|%=|&=|~=|\\|=|\\*\\*|\\*|/|%|\\+|-',
name: 'keyword.operator.arithmetic.gdscript'
},
assignment_operator: {
match: '=',
name: 'keyword.operator.assignment.gdscript'
},
base_expression: {
patterns: [
{include: '#builtin_get_node_shorthand'},
{include: '#nodepath_object'},
{include: '#nodepath_function'},
{include: '#strings'},
{include: '#builtin_classes'},
{include: '#const_vars'},
{include: '#keywords'},
{include: '#operators'},
{include: '#lambda_declaration'},
{include: '#class_declaration'},
{include: '#variable_declaration'},
{include: '#signal_declaration_bare'},
{include: '#signal_declaration'},
{include: '#function_declaration'},
{include: '#statement_keyword'},
{include: '#assignment_operator'},
{include: '#in_keyword'},
{include: '#control_flow'},
{include: '#match_keyword'},
{include: '#curly_braces'},
{include: '#square_braces'},
{include: '#round_braces'},
{include: '#function_call'},
{include: '#region'},
{include: '#comment'},
{include: '#func'},
{include: '#letter'},
{include: '#numbers'},
{include: '#pascal_case_class'},
{include: '#line_continuation'}
]
},
bitwise_operator: {
match: '&|\\||<<=|>>=|<<|>>|\\^|~',
name: 'keyword.operator.bitwise.gdscript'
},
boolean_operator: {
match: '(&&|\\|\\|)',
name: 'keyword.operator.boolean.gdscript'
},
builtin_classes: {
match:
'(?<![^.]\\.|:)\\b(Vector2|Vector2i|Vector3|Vector3i|Vector4|Vector4i|Color|Rect2|Rect2i|Array|Basis|Dictionary|Plane|Quat|RID|Rect3|Transform|Transform2D|Transform3D|AABB|String|Color|NodePath|PoolByteArray|PoolIntArray|PoolRealArray|PoolStringArray|PoolVector2Array|PoolVector3Array|PoolColorArray|bool|int|float|Signal|Callable|StringName|Quaternion|Projection|PackedByteArray|PackedInt32Array|PackedInt64Array|PackedFloat32Array|PackedFloat64Array|PackedStringArray|PackedVector2Array|PackedVector2iArray|PackedVector3Array|PackedVector3iArray|PackedVector4Array|PackedColorArray|JSON|UPNP|OS|IP|JSONRPC|XRVRS|Variant|void)\\b',
name: 'entity.name.type.class.builtin.gdscript'
},
builtin_get_node_shorthand: {
patterns: [
{include: '#builtin_get_node_shorthand_quoted'},
{include: '#builtin_get_node_shorthand_bare'},
{include: '#builtin_get_node_shorthand_bare_multi'}
]
},
builtin_get_node_shorthand_bare: {
captures: {
1: {name: 'keyword.control.flow.gdscript'},
2: {name: 'constant.character.escape.gdscript'},
3: {name: 'constant.character.escape.gdscript'},
4: {name: 'constant.character.escape.gdscript'}
},
name: 'meta.literal.nodepath.bare.gdscript'
},
builtin_get_node_shorthand_bare_multi: {
begin: '(\\$\\s*|%|\\$%\\s*)(/\\s*)?([a-zA-Z_]\\w*)',
beginCaptures: {
1: {name: 'keyword.control.flow.gdscript'},
2: {name: 'constant.character.escape.gdscript'},
3: {name: 'constant.character.escape.gdscript'}
},
end: '(?!\\s*/\\s*%?\\s*[a-zA-Z_]\\w*)',
name: 'meta.literal.nodepath.bare.gdscript',
patterns: [
{
captures: {
1: {name: 'constant.character.escape.gdscript'},
2: {name: 'keyword.control.flow.gdscript'},
3: {name: 'constant.character.escape.gdscript'}
},
match: '(/)\\s*(%)?\\s*([a-zA-Z_]\\w*)\\s*'
}
]
},
builtin_get_node_shorthand_quoted: {
begin: '(?:(\\$|%)|(&|\\^|@))("|\')',
beginCaptures: {
1: {name: 'keyword.control.flow.gdscript'},
2: {name: 'variable.other.enummember.gdscript'}
},
end: '(\\3)',
name: 'string.quoted.gdscript meta.literal.nodepath.gdscript constant.character.escape.gdscript',
patterns: [{match: '%', name: 'keyword.control.flow'}]
},
class_declaration: {
captures: {
1: {name: 'entity.name.type.class.gdscript'},
2: {name: 'class.other.gdscript'}
},
match: '(?<=^class)\\s+([a-zA-Z_]\\w*)\\s*(?=:)'
},
class_enum: {
captures: {
1: {name: 'entity.name.type.class.gdscript'},
2: {name: 'variable.other.enummember.gdscript'}
},
match: '\\b([A-Z][a-zA-Z_0-9]*)\\.([A-Z_0-9]+)'
},
class_is: {
captures: {
1: {name: 'storage.type.is.gdscript'},
2: {name: 'entity.name.type.class.gdscript'}
},
match: '\\s+(is)\\s+([a-zA-Z_]\\w*)'
},
class_name: {
captures: {
1: {name: 'entity.name.type.class.gdscript'},
2: {name: 'class.other.gdscript'}
},
match: '(?<=class_name)\\s+([a-zA-Z_]\\w*(\\.([a-zA-Z_]\\w*))?)'
},
class_new: {
captures: {
1: {name: 'entity.name.type.class.gdscript'},
2: {name: 'storage.type.new.gdscript'},
3: {name: 'punctuation.parenthesis.begin.gdscript'}
},
match: '\\b([a-zA-Z_]\\w*).(new)\\('
},
comment: {
captures: {
1: {name: 'punctuation.definition.comment.number-sign.gdscript'}
},
match: '(##|#).*$\\n?',
name: 'comment.line.number-sign.gdscript'
},
compare_operator: {
match: '<=|>=|==|<|>|!=|!',
name: 'keyword.operator.comparison.gdscript'
},
const_vars: {
match: '\\b([A-Z_][A-Z_0-9]*)\\b',
name: 'variable.other.constant.gdscript'
},
control_flow: {
match:
'\\b(?:if|elif|else|while|break|continue|pass|return|when|yield|await)\\b',
name: 'keyword.control.gdscript'
},
curly_braces: {
begin: '\\{',
beginCaptures: {0: {name: 'punctuation.definition.dict.begin.gdscript'}},
end: '\\}',
endCaptures: {0: {name: 'punctuation.definition.dict.end.gdscript'}},
patterns: [{include: '#base_expression'}, {include: '#any_variable'}]
},
expression: {
patterns: [
{include: '#getter_setter_godot4'},
{include: '#base_expression'},
{include: '#assignment_operator'},
{include: '#annotations'},
{include: '#class_name'},
{include: '#builtin_classes'},
{include: '#class_new'},
{include: '#class_is'},
{include: '#class_enum'},
{include: '#any_method'},
{include: '#any_variable'},
{include: '#any_property'}
]
},
extends_statement: {
captures: {
1: {name: 'keyword.language.gdscript'},
2: {name: 'entity.other.inherited-class.gdscript'}
},
match: '(extends)\\s+([a-zA-Z_]\\w*\\.[a-zA-Z_]\\w*)?'
},
func: {
match: '\\bfunc\\b',
name: 'keyword.language.gdscript storage.type.function.gdscript'
},
function_arguments: {
begin: '(\\()',
beginCaptures: {
1: {name: 'punctuation.definition.arguments.begin.gdscript'}
},
contentName: 'meta.function.parameters.gdscript',
end: '(?=\\))(?!\\)\\s*\\()',
patterns: [
{match: '(,)', name: 'punctuation.separator.arguments.gdscript'},
{
captures: {
1: {name: 'variable.parameter.function-call.gdscript'},
2: {name: 'keyword.operator.assignment.gdscript'}
},
match: '\\b([a-zA-Z_]\\w*)\\s*(=)(?!=)'
},
{match: '=(?!=)', name: 'keyword.operator.assignment.gdscript'},
{include: '#base_expression'},
{
captures: {
1: {name: 'punctuation.definition.arguments.end.gdscript'},
2: {name: 'punctuation.definition.arguments.begin.gdscript'}
},
match: '\\s*(\\))\\s*(\\()'
},
{include: '#letter'},
{include: '#any_variable'},
{include: '#any_property'},
{include: '#keywords'}
]
},
function_call: {
begin: '(?=\\b[a-zA-Z_]\\w*\\b\\()',
end: '(\\))',
endCaptures: {1: {name: 'punctuation.definition.arguments.end.gdscript'}},
name: 'meta.function-call.gdscript',
patterns: [{include: '#function_name'}, {include: '#function_arguments'}]
},
function_declaration: {
begin: '(?x) \\s*\n (func) \\s+\n ([a-zA-Z_]\\w*) \\s*\n (?=\\()',
beginCaptures: {
1: {name: 'keyword.language.gdscript storage.type.function.gdscript'},
2: {name: 'entity.name.function.gdscript'}
},
end: '(:)',
endCaptures: {1: {name: 'punctuation.section.function.begin.gdscript'}},
name: 'meta.function.gdscript',
patterns: [
{include: '#parameters'},
{include: '#line_continuation'},
{include: '#base_expression'}
]
},
function_name: {
patterns: [
{include: '#builtin_classes'},
{match: '\\b(preload)\\b', name: 'keyword.language.gdscript'},
{match: '\\b([a-zA-Z_]\\w*)\\b', name: 'entity.name.function.gdscript'}
]
},
getter_setter_godot4: {
patterns: [
{
captures: {
1: {name: 'entity.name.function.gdscript'},
2: {name: 'punctuation.separator.annotation.gdscript'}
},
match: '(get)\\s*(:)',
name: 'meta.variable.declaration.getter.gdscript'
},
{
captures: {
1: {name: 'entity.name.function.gdscript'},
2: {name: 'punctuation.definition.arguments.begin.gdscript'},
3: {name: 'variable.other.gdscript'},
4: {name: 'punctuation.definition.arguments.end.gdscript'},
5: {name: 'punctuation.separator.annotation.gdscript'}
},
match: '(set)\\s*(\\()\\s*([A-Za-z_]\\w*)\\s*(\\))\\s*(:)',
name: 'meta.variable.declaration.setter.gdscript'
}
]
},
in_keyword: {
patterns: [
{
begin: '\\b(for)\\b',
captures: {1: {name: 'keyword.control.gdscript'}},
end: ':',
patterns: [
{match: '\\bin\\b', name: 'keyword.control.gdscript'},
{include: '#base_expression'},
{include: '#any_variable'},
{include: '#any_property'}
]
},
{match: '\\bin\\b', name: 'keyword.operator.wordlike.gdscript'}
]
},
keywords: {
match:
'\\b(?:class|class_name|is|onready|tool|static|export|as|enum|assert|breakpoint|sync|remote|master|puppet|slave|remotesync|mastersync|puppetsync|trait|namespace|super|self)\\b',
name: 'keyword.language.gdscript'
},
lambda_declaration: {
begin: '(func)\\s?(?=\\()',
beginCaptures: {
1: {name: 'keyword.language.gdscript storage.type.function.gdscript'},
2: {name: 'entity.name.function.gdscript'}
},
end: '(:|(?=[#\'"\\n]))',
name: 'meta.function.gdscript',
patterns: [
{include: '#parameters'},
{include: '#line_continuation'},
{include: '#base_expression'},
{include: '#any_variable'},
{include: '#any_property'}
]
},
letter: {
match: '\\b(?:true|false|null)\\b',
name: 'constant.language.gdscript'
},
line_continuation: {
patterns: [
{
captures: {
1: {name: 'punctuation.separator.continuation.line.gdscript'},
2: {name: 'invalid.illegal.line.continuation.gdscript'}
},
match: '(\\\\)\\s*(\\S.*$\\n?)'
},
{
begin: '(\\\\)\\s*$\\n?',
beginCaptures: {
1: {name: 'punctuation.separator.continuation.line.gdscript'}
},
end: "(?x)\n (?=^\\s*$)\n |\n (?! (\\s* [rR]? (\\'\\'\\'|\\\"\\\"\\\"|\\'|\\\"))\n |\n (\\G $) (?# '\\G' is necessary for ST)\n )\n",
patterns: [{include: '#base_expression'}]
}
]
},
loose_default: {
begin: '(=)',
beginCaptures: {1: {name: 'keyword.operator.gdscript'}},
end: '(,)|(?=\\))',
endCaptures: {1: {name: 'punctuation.separator.parameters.gdscript'}},
patterns: [{include: '#expression'}]
},
match_keyword: {
captures: {1: {name: 'keyword.control.gdscript'}},
match: '^\n\\s*(match)'
},
nodepath_function: {
begin:
'(get_node_or_null|has_node|has_node_and_resource|find_node|get_node)\\s*(\\()',
beginCaptures: {
1: {name: 'entity.name.function.gdscript'},
2: {name: 'punctuation.definition.parameters.begin.gdscript'}
},
contentName: 'meta.function.parameters.gdscript',
end: '(\\))',
endCaptures: {
1: {name: 'punctuation.definition.parameters.end.gdscript'}
},
name: 'meta.function.gdscript',
patterns: [
{
begin: '("|\')',
end: '\\1',
name: 'string.quoted.gdscript meta.literal.nodepath.gdscript constant.character.escape.gdscript',
patterns: [{match: '%', name: 'keyword.control.flow.gdscript'}]
},
{include: '#expression'}
]
},
nodepath_object: {
begin: '(NodePath)\\s*(?:\\()',
beginCaptures: {1: {name: 'support.class.library.gdscript'}},
end: '(?:\\))',
name: 'meta.literal.nodepath.gdscript',
patterns: [
{
begin: '("|\')',
end: '\\1',
name: 'string.quoted.gdscript constant.character.escape.gdscript',
patterns: [{match: '%', name: 'keyword.control.flow.gdscript'}]
}
]
},
numbers: {
patterns: [
{match: '0b[01_]+', name: 'constant.numeric.integer.binary.gdscript'},
{
match: '0x[0-9A-Fa-f_]+',
name: 'constant.numeric.integer.hexadecimal.gdscript'
},
{
match: '\\.[0-9][0-9_]*([eE][+-]?[0-9_]+)?',
name: 'constant.numeric.float.gdscript'
},
{
match: '([0-9][0-9_]*)\\.[0-9_]*([eE][+-]?[0-9_]+)?',
name: 'constant.numeric.float.gdscript'
},
{
match: '([0-9][0-9_]*)?\\.[0-9_]*([eE][+-]?[0-9_]+)',
name: 'constant.numeric.float.gdscript'
},
{
match: '[0-9][0-9_]*[eE][+-]?[0-9_]+',
name: 'constant.numeric.float.gdscript'
},
{match: '[-]?[0-9][0-9_]*', name: 'constant.numeric.integer.gdscript'}
]
},
operators: {
patterns: [
{include: '#wordlike_operator'},
{include: '#boolean_operator'},
{include: '#arithmetic_operator'},
{include: '#bitwise_operator'},
{include: '#compare_operator'}
]
},
parameters: {
begin: '(\\()',
beginCaptures: {
1: {name: 'punctuation.definition.parameters.begin.gdscript'}
},
end: '(\\))',
endCaptures: {
1: {name: 'punctuation.definition.parameters.end.gdscript'}
},
name: 'meta.function.parameters.gdscript',
patterns: [
{include: '#annotated_parameter'},
{
captures: {
1: {name: 'variable.parameter.function.language.gdscript'},
2: {name: 'punctuation.separator.parameters.gdscript'}
},
match: '(?x)\n ([a-zA-Z_]\\w*)\n \\s* (?: (,) | (?=[)#\\n=]))\n'
},
{include: '#comment'},
{include: '#loose_default'}
]
},
pascal_case_class: {
match: '\\b[A-Z]+(?:[a-z]+[A-Za-z0-9_]*)+\\b',
name: 'entity.name.type.class.gdscript'
},
region: {
match: '#(end)?region.*$\\n?',
name: 'keyword.language.region.gdscript'
},
round_braces: {
begin: '\\(',
beginCaptures: {0: {name: 'punctuation.parenthesis.begin.gdscript'}},
end: '\\)',
endCaptures: {0: {name: 'punctuation.parenthesis.end.gdscript'}},
patterns: [{include: '#base_expression'}, {include: '#any_variable'}]
},
signal_declaration: {
begin: '(?x) \\s*\n (signal) \\s+\n ([a-zA-Z_]\\w*) \\s*\n (?=\\()',
beginCaptures: {
1: {name: 'keyword.language.gdscript storage.type.function.gdscript'},
2: {name: 'entity.name.function.gdscript'}
},
end: '((?=[#\'"\\n]))',
name: 'meta.signal.gdscript',
patterns: [{include: '#parameters'}, {include: '#line_continuation'}]
},
signal_declaration_bare: {
captures: {
1: {name: 'keyword.language.gdscript storage.type.function.gdscript'},
2: {name: 'entity.name.function.gdscript'}
},
match: '(?x) \\s*\n (signal) \\s+\n ([a-zA-Z_]\\w*)(?=[\\n\\s])',
name: 'meta.signal.gdscript'
},
square_braces: {
begin: '\\[',
beginCaptures: {0: {name: 'punctuation.definition.list.begin.gdscript'}},
end: '\\]',
endCaptures: {0: {name: 'punctuation.definition.list.end.gdscript'}},
patterns: [{include: '#base_expression'}, {include: '#any_variable'}]
},
statement: {patterns: [{include: '#extends_statement'}]},
statement_keyword: {
patterns: [
{
match:
'(?x)\n \\b(?<!\\.)(\n continue | assert | break | elif | else | if | pass | return | while )\\b\n',
name: 'keyword.control.flow.gdscript'
},
{match: '\\b(?<!\\.)(class)\\b', name: 'storage.type.class.gdscript'},
{
captures: {1: {name: 'keyword.control.flow.gdscript'}},
match:
'(?x)\n ^\\s*(\n case | match\n )(?=\\s*([-+\\w\\d(\\[{\'":#]|$))\\b\n'
}
]
},
string_bracket_placeholders: {
patterns: [
{
captures: {
1: {name: 'constant.character.format.placeholder.other.gdscript'},
3: {name: 'storage.type.format.gdscript'},
4: {name: 'storage.type.format.gdscript'}
},
match:
'(?x)\n (\n {{ | }}\n | (?:\n {\n \\w* (\\.[[:alpha:]_]\\w* | \\[[^\\]\'"]+\\])*\n (![rsa])?\n ( : \\w? [<>=^]? [-+ ]? \\#?\n \\d* ,? (\\.\\d+)? [bcdeEfFgGnosxX%]? )?\n })\n )\n',
name: 'meta.format.brace.gdscript'
},
{
captures: {
1: {name: 'constant.character.format.placeholder.other.gdscript'},
3: {name: 'storage.type.format.gdscript'},
4: {name: 'storage.type.format.gdscript'}
},
match:
'(?x)\n (\n {\n \\w* (\\.[[:alpha:]_]\\w* | \\[[^\\]\'"]+\\])*\n (![rsa])?\n (:)\n [^\'"{}\\n]* (?:\n \\{ [^\'"}\\n]*? \\} [^\'"{}\\n]*\n )*\n }\n )\n',
name: 'meta.format.brace.gdscript'
}
]
},
string_percent_placeholders: {
captures: {
1: {name: 'constant.character.format.placeholder.other.gdscript'}
},
match:
'(?x)\n (\n % (\\([\\w\\s]*\\))?\n [-+#0 ]*\n (\\d+|\\*)? (\\.(\\d+|\\*))?\n ([hlL])?\n [diouxXeEfFgGcrsab%]\n )\n',
name: 'meta.format.percent.gdscript'
},
strings: {
begin: '(r)?("""|\'\'\'|"|\')',
beginCaptures: {1: {name: 'constant.character.escape.gdscript'}},
end: '\\2',
name: 'string.quoted.gdscript',
patterns: [
{match: '\\\\.', name: 'constant.character.escape.gdscript'},
{include: '#string_percent_placeholders'},
{include: '#string_bracket_placeholders'}
]
},
variable_declaration: {
begin: '\\b(?:(var)|(const))\\b',
beginCaptures: {
1: {name: 'keyword.language.gdscript storage.type.var.gdscript'},
2: {name: 'keyword.language.gdscript storage.type.const.gdscript'}
},
end: '$|;',
name: 'meta.variable.declaration.gdscript',
patterns: [
{
captures: {
1: {name: 'punctuation.separator.annotation.gdscript'},
2: {name: 'entity.name.function.gdscript'},
3: {name: 'entity.name.function.gdscript'}
},
match: '(:)?\\s*(set|get)\\s+=\\s+([a-zA-Z_]\\w*)'
},
{match: ':=|=(?!=)', name: 'keyword.operator.assignment.gdscript'},
{
captures: {
1: {name: 'punctuation.separator.annotation.gdscript'},
2: {name: 'entity.name.type.class.gdscript'}
},
match: '(:)\\s*([a-zA-Z_]\\w*)?'
},
{
captures: {
1: {name: 'keyword.language.gdscript'},
2: {name: 'entity.name.function.gdscript'},
3: {name: 'entity.name.function.gdscript'}
},
match: '(setget)\\s+([a-zA-Z_]\\w*)(?:[,]\\s*([a-zA-Z_]\\w*))?'
},
{include: '#expression'},
{include: '#letter'},
{include: '#any_variable'},
{include: '#any_property'},
{include: '#keywords'}
]
},
wordlike_operator: {
match: '\\b(and|or|not)\\b',
name: 'keyword.operator.wordlike.gdscript'
}
},
scopeName: 'source.gdscript'
}
export default grammar