on master help sign in
Add support for Zig

Adds syntax support for source code for the Zig programming language. https://ziglang.org/

commitc76e27851cfea1563ed8ff4b55b989706f433f35 authorPaul Smith <paulsmith@gmail.com> dateSat 2 Jan 2021, 13:22 (6 years ago) parent8c0dcf3
5 files changed+483
.gitmodules+3 assets/syntaxes/02_Extra/Zig+1 assets/syntaxes/02_Extra/Zig.sublime-syntax+265 tests/syntax-tests/highlighted/Zig/example.zig+107 tests/syntax-tests/source/Zig/example.zig+107
.gitmodules+3
@@ -210,3 +210,6 @@
210210[submodule "assets/syntaxes/02_Extra/Lean"]
211211 path = assets/syntaxes/02_Extra/Lean
212212 url = https://github.com/leanprover/vscode-lean.git
213+[submodule "assets/syntaxes/02_Extra/Zig"]
214+ path = assets/syntaxes/02_Extra/Zig
215+ url = https://github.com/ziglang/sublime-zig-language.git
assets/syntaxes/02_Extra/Zignew file+1

Submodule changed.

assets/syntaxes/02_Extra/Zig.sublime-syntaxnew file+265
@@ -0,0 +1,265 @@
1+%YAML 1.2
2+---
3+# http://www.sublimetext.com/docs/3/syntax.html
4+name: Zig
5+file_extensions:
6+ - zig
7+scope: source.zig
8+contexts:
9+ main:
10+ - include: dummy_main
11+ block:
12+ - match: '([a-zA-Z_][\w.]*|@\".+\")?\s*(\{)'
13+ captures:
14+ 1: storage.type.zig
15+ 2: punctuation.section.braces.begin.zig
16+ push:
17+ - match: '(\})'
18+ captures:
19+ 1: punctuation.section.braces.end.zig
20+ pop: true
21+ - include: dummy_main
22+ character_escapes:
23+ - match: \\n
24+ scope: constant.character.escape.newline.zig
25+ - match: \\r
26+ scope: constant.character.escape.carrigereturn.zig
27+ - match: \\t
28+ scope: constant.character.escape.tabulator.zig
29+ - match: \\\\
30+ scope: constant.character.escape.backslash.zig
31+ - match: \\'
32+ scope: constant.character.escape.single-quote.zig
33+ - match: \\\"
34+ scope: constant.character.escape.double-quote.zig
35+ - match: '\\x[a-fA-F\d]{2}'
36+ scope: constant.character.escape.hexidecimal.zig
37+ - match: '\\u\{[a-fA-F\d]{1,6}\}'
38+ scope: constant.character.escape.hexidecimal.zig
39+ comments:
40+ - match: ///
41+ push:
42+ - meta_scope: comment.line.documentation.zig
43+ - match: $\n?
44+ pop: true
45+ - match: '//[^/]\s*TODO'
46+ push:
47+ - meta_scope: comment.line.todo.zig
48+ - match: $\n?
49+ pop: true
50+ - match: "//[^/]*"
51+ push:
52+ - meta_scope: comment.line.zig
53+ - match: $\n?
54+ pop: true
55+ constants:
56+ - match: \b(null|undefined|true|false)\b
57+ scope: constant.language.zig
58+ - match: '\b(?<!\.)(-?[\d_]+)(?!\.)\b'
59+ scope: constant.numeric.integer.zig
60+ - match: '\b(?<!\.)(0x[a-fA-F\d_]+)(?!\.)\b'
61+ scope: constant.numeric.integer.hexadecimal.zig
62+ - match: '\b(?<!\.)(0o[0-7_]+)(?!\.)\b'
63+ scope: constant.numeric.integer.octal.zig
64+ - match: '\b(?<!\.)(0b[01_]+)(?!\.)\b'
65+ scope: constant.numeric.integer.binary.zig
66+ - match: '(?<!\.)(-?\b[\d_]+(?:\.[\d_]+)?(?:[eE][+-]?[\d_]+)?)(?!\.)\b'
67+ scope: constant.numeric.float.zig
68+ - match: '(?<!\.)(-?\b0x[a-fA-F\d_]+(?:\.[a-fA-F\d_]+)?[pP]?(?:[+-]?[\d_]+)?)(?!\.)\b'
69+ scope: constant.numeric.float.hexadecimal.zig
70+ container_decl:
71+ - match: '\b(?!\d)([a-zA-Z_]\w*|@\".+\")?(?=\s*=\s*(?:extern|packed)?\b\s*(?:union)\s*[(\{])'
72+ scope: entity.name.union.zig
73+ - match: '\b(?!\d)([a-zA-Z_]\w*|@\".+\")?(?=\s*=\s*(?:extern|packed)?\b\s*(?:struct)\s*[(\{])'
74+ scope: entity.name.struct.zig
75+ - match: '\b(?!\d)([a-zA-Z_]\w*|@\".+\")?(?=\s*=\s*(?:extern|packed)?\b\s*(?:enum)\s*[(\{])'
76+ scope: entity.name.enum.zig
77+ - match: '\b(?!\d)([a-zA-Z_]\w*|@\".+\")?(?=\s*=\s*(?:error)\s*[(\{])'
78+ scope: entity.name.error.zig
79+ - match: '\b(error)(\.)([a-zA-Z_]\w*|@\".+\")'
80+ captures:
81+ 1: storage.type.error.zig
82+ 2: punctuation.accessor.zig
83+ 3: entity.name.error.zig
84+ dummy_main:
85+ - include: label
86+ - include: function_type
87+ - include: punctuation
88+ - include: storage_modifier
89+ - include: container_decl
90+ - include: constants
91+ - include: comments
92+ - include: strings
93+ - include: storage
94+ - include: keywords
95+ - include: operators
96+ - include: support
97+ - include: field_decl
98+ - include: block
99+ - include: function_def
100+ - include: function_call
101+ - include: enum_literal
102+ enum_literal:
103+ - match: '(?<!\w|\)|\?|\}|\]|\*)(\.(?:[a-zA-Z_]\w*\b|@\"[^\"]*\"))(?!\(|\s*=[^=>])'
104+ scope: constant.language.enum
105+ field_decl:
106+ - match: '([a-zA-Z_]\w*|@\".+\")\s*(:)\s*'
107+ captures:
108+ 1: variable.other.member.zig
109+ 2: punctuation.separator.zig
110+ push:
111+ - match: '([a-zA-Z_][\w.]*|@\".+\")?\s*(?:(,)|(=)|$)'
112+ captures:
113+ 1: storage.type.zig
114+ 2: punctuation.separator.zig
115+ 3: keyword.operator.assignment.zig
116+ pop: true
117+ - include: dummy_main
118+ function_call:
119+ - match: '(?<!fn)\b([a-zA-Z_]\w*|@\".+\")(?=\s*\()'
120+ scope: variable.function.zig
121+ function_def:
122+ - match: '(?<=fn)\s+([a-zA-Z_]\w*|@\".+\")(\()'
123+ captures:
124+ 1: entity.name.function
125+ 2: punctuation.section.parens.begin.zig
126+ push:
127+ - match: '(?<=\)[^\)])\s*([a-zA-Z_][\w.]*|@\".+\")?(!)?\s*(?:([a-zA-Z_][\w.]*|@\".+\")\b(?!\s*\())?'
128+ captures:
129+ 1: storage.type.zig
130+ 2: keyword.operator.zig
131+ 3: storage.type.zig
132+ pop: true
133+ - include: label
134+ - include: param_list
135+ - match: '([a-zA-Z_][\w.]*|@\".+\")'
136+ scope: storage.type.zig
137+ - include: dummy_main
138+ function_type:
139+ - match: \b(fn)\s*(\()
140+ captures:
141+ 1: storage.type.function.zig
142+ 2: punctuation.section.parens.begin.zig
143+ push:
144+ - meta_content_scope: meta.function.parameters.zig
145+ - match: '(?<=\)|\})\s*([a-zA-Z_][\w.]*|@\".+\")?\s*(!)?\s*([a-zA-Z_][\w.]*|@\".+\")'
146+ captures:
147+ 1: storage.type.zig
148+ 2: keyword.operator.zig
149+ 3: storage.type.zig
150+ pop: true
151+ - include: label
152+ - include: param_list
153+ - match: '([a-zA-Z_][\w.]*|@\".+\")'
154+ scope: storage.type.zig
155+ - include: dummy_main
156+ keywords:
157+ - match: \b(while|for|break|return|continue|asm|defer|errdefer|unreachable)\b
158+ scope: keyword.control.zig
159+ - match: \b(async|await|suspend|nosuspend|resume)\b
160+ scope: keyword.control.async.zig
161+ - match: \b(if|else|switch|try|catch|orelse)\b
162+ scope: keyword.control.conditional.zig
163+ - match: (?<!\w)(@import|@cImport|@cInclude)\b
164+ scope: keyword.control.import.zig
165+ - match: \b(usingnamespace)\b
166+ scope: keyword.other.usingnamespace.zig
167+ label:
168+ - match: '\b(break|continue)\s*:\s*([a-zA-Z_]\w*|@\".+\")\b|\b(?!\d)([a-zA-Z_]\w*|@\".+\")\b(?=\s*:\s*(?:\{|while\b))'
169+ captures:
170+ 1: keyword.control.zig
171+ 2: entity.name.label.zig
172+ 3: entity.name.label.zig
173+ operators:
174+ - match: \b!\b
175+ scope: keyword.operator.zig
176+ - match: (==|(?:!|>|<)=?)
177+ scope: keyword.operator.logical.zig
178+ - match: \b(and|or)\b
179+ scope: keyword.operator.word.zig
180+ - match: '((?:(?:\+|-|\*)\%?|/|%|<<|>>|&|\|(?=[^\|])|\^)?=)'
181+ scope: keyword.operator.assignment.zig
182+ - match: ((?:\+|-|\*)\%?|/(?!/)|%)
183+ scope: keyword.operator.arithmetic.zig
184+ - match: '(<<|>>|&(?=[a-zA-Z_]|@\")|\|(?=[^\|])|\^|~)'
185+ scope: keyword.operator.bitwise.zig
186+ - match: '(\+\+|\*\*|->|\.\?|\.\*|&(?=[a-zA-Z_]|@\")|\?|\|\||\.{2,3})'
187+ scope: keyword.operator.other.zig
188+ param_list:
189+ - match: '([a-zA-Z_]\w*|@\".+\")\s*(:)\s*'
190+ captures:
191+ 1: variable.parameter.zig
192+ 2: punctuation.separator.zig
193+ push:
194+ - match: '([a-zA-Z_][\w.]*|@\".+\")?\s*(?:(,)|(\)))'
195+ captures:
196+ 1: storage.type.zig
197+ 2: punctuation.separator.zig
198+ 3: punctuation.section.parens.end.zig
199+ pop: true
200+ - include: dummy_main
201+ - match: '([a-zA-Z_][\w.]*|@\".+\")'
202+ scope: storage.type.zig
203+ punctuation:
204+ - match: ","
205+ scope: punctuation.separator.zig
206+ - match: ;
207+ scope: punctuation.terminator.zig
208+ - match: (\()
209+ scope: punctuation.section.parens.begin.zig
210+ - match: (\))
211+ scope: punctuation.section.parens.end.zig
212+ storage:
213+ - match: \b(bool|void|noreturn|type|anyerror|anytype)\b
214+ scope: storage.type.zig
215+ - match: '\b(?<!\.)([iu]\d+|[iu]size|comptime_int)\b'
216+ scope: storage.type.integer.zig
217+ - match: \b(f16|f32|f64|f128|comptime_float)\b
218+ scope: storage.type.float.zig
219+ - match: \b(c_short|c_ushort|c_int|c_uint|c_long|c_ulong|c_longlong|c_ulonglong|c_longdouble|c_void)\b
220+ scope: storage.type.c_compat.zig
221+ - match: '\b(anyframe)\b\s*(->)?\s*(?:([a-zA-Z_][\w.]*|@\".+\")\b(?!\s*\())?'
222+ captures:
223+ 1: storage.type.zig
224+ 2: keyword.operator.zig
225+ 3: storage.type.zig
226+ - match: \bfn\b
227+ scope: storage.type.function.zig
228+ - match: \btest\b
229+ scope: storage.type.test.zig
230+ - match: \bstruct\b
231+ scope: storage.type.struct.zig
232+ - match: \benum\b
233+ scope: storage.type.enum.zig
234+ - match: \bunion\b
235+ scope: storage.type.union.zig
236+ - match: \berror\b
237+ scope: storage.type.error.zig
238+ storage_modifier:
239+ - match: \b(const|var|extern|packed|export|pub|noalias|inline|noinline|comptime|volatile|align|linksection|threadlocal|allowzero)\b
240+ scope: storage.modifier.zig
241+ strings:
242+ - match: \'
243+ push:
244+ - meta_scope: string.quoted.single.zig
245+ - match: \'
246+ pop: true
247+ - include: character_escapes
248+ - match: '\\[^\''][^\'']*?'
249+ scope: invalid.illegal.character.zig
250+ - match: c?\"
251+ push:
252+ - meta_scope: string.quoted.double.zig
253+ - match: \"
254+ pop: true
255+ - include: character_escapes
256+ - match: '\\[^\''][^\'']*?'
257+ scope: invalid.illegal.character.zig
258+ - match: c?\\\\
259+ push:
260+ - meta_scope: string.quoted.other.zig
261+ - match: $\n?
262+ pop: true
263+ support:
264+ - match: '(?<!\w)@[^\"\d][a-zA-Z_]\w*\b'
265+ scope: support.function.zig
tests/syntax-tests/highlighted/Zig/example.zignew file+107
@@ -0,0 +1,107 @@
1+//! this is a top level doc, starts with "//!"
2+
3+const std = @import("std");
4+
5+pub fn main() anyerror!void {
6+ const stdout = std.io.getStdOut().writer();
7+ try stdout.print("Hello, {}!\n", .{"world"});
8+}
9+
10+const expect = std.testing.expect;
11+
12+test "comments" {
13+ // comments start with "//" until newline
14+ // foo bar baz
15+ const x = true; // another comment
16+ expect(x);
17+}
18+
19+/// a doc comment starts with "///"
20+/// multiple lines are merged together
21+const Timestamp = struct {
22+ /// number of seconds since epoch
23+ seconds: i64,
24+
25+ /// number of nanoseconds past the second
26+ nano: u32,
27+
28+ const Self = @This();
29+
30+ pub fn unixEpoch() Self {
31+ return Self{
32+ .seconds = 0,
33+ .nanos = 0,
34+ };
35+ }
36+};
37+
38+const my_val = switch (std.Target.current.os.tag) {
39+ .linux => "Linux",
40+ else => "not Linux",
41+};
42+
43+const Book = enum {
44+ paperback,
45+ hardcover,
46+ ebook,
47+ pdf,
48+};
49+
50+const TokenType = union(enum) {
51+ int: isize,
52+ float: f64,
53+ string: []const u8,
54+};
55+
56+const array_lit: [4]u8 = .{ 11, 22, 33, 44 };
57+const sentinal_lit = [_:0]u8{ 1, 2, 3, 4 };
58+
59+test "address of syntax" {
60+ // Get the address of a variable:
61+ const x: i32 = 1234;
62+ const x_ptr = &x;
63+
64+ // Dereference a pointer:
65+ expect(x_ptr.* == 1234);
66+
67+ // When you get the address of a const variable, you get a const pointer to a single item.
68+ expect(@TypeOf(x_ptr) == *const i32);
69+
70+ // If you want to mutate the value, you'd need an address of a mutable variable:
71+ var y: i32 = 5678;
72+ const y_ptr = &y;
73+ expect(@TypeOf(y_ptr) == *i32);
74+ y_ptr.* += 1;
75+ expect(y_ptr.* == 5679);
76+}
77+
78+// integer literals
79+const decimal_int = 98222;
80+const hex_int = 0xff;
81+const another_hex_int = 0xFF;
82+const octal_int = 0o755;
83+const binary_int = 0b11110000;
84+
85+// underscores may be placed between two digits as a visual separator
86+const one_billion = 1_000_000_000;
87+const binary_mask = 0b1_1111_1111;
88+const permissions = 0o7_5_5;
89+const big_address = 0xFF80_0000_0000_0000;
90+
91+// float literals
92+const floating_point = 123.0E+77;
93+const another_float = 123.0;
94+const yet_another = 123.0e+77;
95+
96+const hex_floating_point = 0x103.70p-5;
97+const another_hex_float = 0x103.70;
98+const yet_another_hex_float = 0x103.70P-5;
99+
100+// underscores may be placed between two digits as a visual separator
101+const lightspeed = 299_792_458.000_000;
102+const nanosecond = 0.000_000_001;
103+const more_hex = 0x1234_5678.9ABC_CDEFp-10;
104+
105+fn max(comptime T: type, a: T, b: T) T {
106+ return if (a > b) a else b;
107+}
tests/syntax-tests/source/Zig/example.zignew file+107
@@ -0,0 +1,107 @@
1+//! this is a top level doc, starts with "//!"
2+
3+const std = @import("std");
4+
5+pub fn main() anyerror!void {
6+ const stdout = std.io.getStdOut().writer();
7+ try stdout.print("Hello, {}!\n", .{"world"});
8+}
9+
10+const expect = std.testing.expect;
11+
12+test "comments" {
13+ // comments start with "//" until newline
14+ // foo bar baz
15+ const x = true; // another comment
16+ expect(x);
17+}
18+
19+/// a doc comment starts with "///"
20+/// multiple lines are merged together
21+const Timestamp = struct {
22+ /// number of seconds since epoch
23+ seconds: i64,
24+
25+ /// number of nanoseconds past the second
26+ nano: u32,
27+
28+ const Self = @This();
29+
30+ pub fn unixEpoch() Self {
31+ return Self{
32+ .seconds = 0,
33+ .nanos = 0,
34+ };
35+ }
36+};
37+
38+const my_val = switch (std.Target.current.os.tag) {
39+ .linux => "Linux",
40+ else => "not Linux",
41+};
42+
43+const Book = enum {
44+ paperback,
45+ hardcover,
46+ ebook,
47+ pdf,
48+};
49+
50+const TokenType = union(enum) {
51+ int: isize,
52+ float: f64,
53+ string: []const u8,
54+};
55+
56+const array_lit: [4]u8 = .{ 11, 22, 33, 44 };
57+const sentinal_lit = [_:0]u8{ 1, 2, 3, 4 };
58+
59+test "address of syntax" {
60+ // Get the address of a variable:
61+ const x: i32 = 1234;
62+ const x_ptr = &x;
63+
64+ // Dereference a pointer:
65+ expect(x_ptr.* == 1234);
66+
67+ // When you get the address of a const variable, you get a const pointer to a single item.
68+ expect(@TypeOf(x_ptr) == *const i32);
69+
70+ // If you want to mutate the value, you'd need an address of a mutable variable:
71+ var y: i32 = 5678;
72+ const y_ptr = &y;
73+ expect(@TypeOf(y_ptr) == *i32);
74+ y_ptr.* += 1;
75+ expect(y_ptr.* == 5679);
76+}
77+
78+// integer literals
79+const decimal_int = 98222;
80+const hex_int = 0xff;
81+const another_hex_int = 0xFF;
82+const octal_int = 0o755;
83+const binary_int = 0b11110000;
84+
85+// underscores may be placed between two digits as a visual separator
86+const one_billion = 1_000_000_000;
87+const binary_mask = 0b1_1111_1111;
88+const permissions = 0o7_5_5;
89+const big_address = 0xFF80_0000_0000_0000;
90+
91+// float literals
92+const floating_point = 123.0E+77;
93+const another_float = 123.0;
94+const yet_another = 123.0e+77;
95+
96+const hex_floating_point = 0x103.70p-5;
97+const another_hex_float = 0x103.70;
98+const yet_another_hex_float = 0x103.70P-5;
99+
100+// underscores may be placed between two digits as a visual separator
101+const lightspeed = 299_792_458.000_000;
102+const nanosecond = 0.000_000_001;
103+const more_hex = 0x1234_5678.9ABC_CDEFp-10;
104+
105+fn max(comptime T: type, a: T, b: T) T {
106+ return if (a > b) a else b;
107+}