Skip to content

Commit 9391121

Browse files
iamvukasinalecthomas
authored andcommitted
Add Metal lexer
1 parent b5d03c0 commit 9391121

File tree

3 files changed

+319
-0
lines changed

3 files changed

+319
-0
lines changed

Diff for: lexers/m/metal.go

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package m
2+
3+
import (
4+
. "github.com/alecthomas/chroma" // nolint
5+
"github.com/alecthomas/chroma/lexers/internal"
6+
)
7+
8+
// Metal lexer.
9+
var Metal = internal.Register(MustNewLazyLexer(
10+
&Config{
11+
Name: "Metal",
12+
Aliases: []string{"metal"},
13+
Filenames: []string{"*.metal"},
14+
MimeTypes: []string{"text/x-metal"},
15+
EnsureNL: true,
16+
},
17+
metalRules,
18+
))
19+
20+
func metalRules() Rules {
21+
return Rules{
22+
"statements": {
23+
{Words(``, `\b`, `namespace`, `operator`, `template`, `this`, `using`, `constexpr`), Keyword, nil},
24+
{`(enum)\b(\s+)(class)\b(\s*)`, ByGroups(Keyword, Text, Keyword, Text), Push("classname")},
25+
{`(class|struct|enum|union)\b(\s*)`, ByGroups(Keyword, Text), Push("classname")},
26+
{`\[\[.+\]\]`, NameAttribute, nil},
27+
{`(\d+\.\d*|\.\d+|\d+)[eE][+-]?\d+[LlUu]*`, LiteralNumberFloat, nil},
28+
{`(\d+\.\d*|\.\d+|\d+[fF])[fF]?`, LiteralNumberFloat, nil},
29+
{`0[xX]([0-9A-Fa-f]('?[0-9A-Fa-f]+)*)[LlUu]*`, LiteralNumberHex, nil},
30+
{`0('?[0-7]+)+[LlUu]*`, LiteralNumberOct, nil},
31+
{`0[Bb][01]('?[01]+)*[LlUu]*`, LiteralNumberBin, nil},
32+
{`[0-9]('?[0-9]+)*[LlUu]*`, LiteralNumberInteger, nil},
33+
{`\*/`, Error, nil},
34+
{`[~!%^&*+=|?:<>/-]`, Operator, nil},
35+
{`[()\[\],.]`, Punctuation, nil},
36+
{Words(``, `\b`, `break`, `case`, `const`, `continue`, `do`, `else`, `enum`, `extern`, `for`, `if`, `return`, `sizeof`, `static`, `struct`, `switch`, `typedef`, `union`, `while`), Keyword, nil},
37+
{`(bool|float|half|long|ptrdiff_t|size_t|unsigned|u?char|u?int((8|16|32|64)_t)?|u?short)\b`, KeywordType, nil},
38+
{`(bool|float|half|u?(char|int|long|short))(2|3|4)\b`, KeywordType, nil},
39+
{`packed_(float|half|long|u?(char|int|short))(2|3|4)\b`, KeywordType, nil},
40+
{`(float|half)(2|3|4)x(2|3|4)\b`, KeywordType, nil},
41+
{`atomic_u?int\b`, KeywordType, nil},
42+
{`(rg?(8|16)(u|s)norm|rgba(8|16)(u|s)norm|srgba8unorm|rgb10a2|rg11b10f|rgb9e5)\b`, KeywordType, nil},
43+
{`(array|depth(2d|cube)(_array)?|depth2d_ms(_array)?|sampler|texture_buffer|texture(1|2)d(_array)?|texture2d_ms(_array)?|texture3d|texturecube(_array)?|uniform|visible_function_table)\b`, KeywordType, nil},
44+
{`(true|false|NULL)\b`, NameBuiltin, nil},
45+
{Words(``, `\b`, `device`, `constant`, `ray_data`, `thread`, `threadgroup`, `threadgroup_imageblock`), Keyword, nil},
46+
{`([a-zA-Z_]\w*)(\s*)(:)(?!:)`, ByGroups(NameLabel, Text, Punctuation), nil},
47+
{`[a-zA-Z_]\w*`, Name, nil},
48+
},
49+
"root": {
50+
Include("whitespace"),
51+
{`(fragment|kernel|vertex)?((?:[\w*\s])+?(?:\s|[*]))([a-zA-Z_]\w*)(\s*\([^;]*?\))([^;{]*)(\{)`, ByGroups(Keyword, UsingSelf("root"), NameFunction, UsingSelf("root"), UsingSelf("root"), Punctuation), Push("function")},
52+
{`(fragment|kernel|vertex)?((?:[\w*\s])+?(?:\s|[*]))([a-zA-Z_]\w*)(\s*\([^;]*?\))([^;]*)(;)`, ByGroups(Keyword, UsingSelf("root"), NameFunction, UsingSelf("root"), UsingSelf("root"), Punctuation), nil},
53+
Default(Push("statement")),
54+
},
55+
"classname": {
56+
{`(\[\[.+\]\])(\s*)`, ByGroups(NameAttribute, Text), nil},
57+
{`[a-zA-Z_]\w*`, NameClass, Pop(1)},
58+
{`\s*(?=[>{])`, Text, Pop(1)},
59+
},
60+
"whitespace": {
61+
{`^#if\s+0`, CommentPreproc, Push("if0")},
62+
{`^#`, CommentPreproc, Push("macro")},
63+
{`^(\s*(?:/[*].*?[*]/\s*)?)(#if\s+0)`, ByGroups(UsingSelf("root"), CommentPreproc), Push("if0")},
64+
{`^(\s*(?:/[*].*?[*]/\s*)?)(#)`, ByGroups(UsingSelf("root"), CommentPreproc), Push("macro")},
65+
{`\n`, Text, nil},
66+
{`\s+`, Text, nil},
67+
{`\\\n`, Text, nil},
68+
{`//(\n|[\w\W]*?[^\\]\n)`, CommentSingle, nil},
69+
{`/(\\\n)?[*][\w\W]*?[*](\\\n)?/`, CommentMultiline, nil},
70+
{`/(\\\n)?[*][\w\W]*`, CommentMultiline, nil},
71+
},
72+
"statement": {
73+
Include("whitespace"),
74+
Include("statements"),
75+
{`[{]`, Punctuation, Push("root")},
76+
{`[;}]`, Punctuation, Pop(1)},
77+
},
78+
"function": {
79+
Include("whitespace"),
80+
Include("statements"),
81+
{`;`, Punctuation, nil},
82+
{`\{`, Punctuation, Push()},
83+
{`\}`, Punctuation, Pop(1)},
84+
},
85+
"macro": {
86+
{`(include)(\s*(?:/[*].*?[*]/\s*)?)([^\n]+)`, ByGroups(CommentPreproc, Text, CommentPreprocFile), nil},
87+
{`[^/\n]+`, CommentPreproc, nil},
88+
{`/[*](.|\n)*?[*]/`, CommentMultiline, nil},
89+
{`//.*?\n`, CommentSingle, Pop(1)},
90+
{`/`, CommentPreproc, nil},
91+
{`(?<=\\)\n`, CommentPreproc, nil},
92+
{`\n`, CommentPreproc, Pop(1)},
93+
},
94+
"if0": {
95+
{`^\s*#if.*?(?<!\\)\n`, CommentPreproc, Push()},
96+
{`^\s*#el(?:se|if).*\n`, CommentPreproc, Pop(1)},
97+
{`^\s*#endif.*?(?<!\\)\n`, CommentPreproc, Pop(1)},
98+
{`.*?\n`, Comment, nil},
99+
},
100+
}
101+
}

Diff for: lexers/testdata/metal.actual

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#include <metal_stdlib>
2+
3+
using namespace metal;
4+
5+
// Include header shared between C code and .metal files.
6+
#include "AAPLShaderTypes.h"
7+
8+
// Include header shared between all .metal files.
9+
#include "AAPLShaderCommon.h"
10+
11+
struct VertexOutput
12+
{
13+
float4 position [[position]];
14+
};
15+
16+
// A depth pre-pass is necessary in forward plus rendering to produce
17+
// minimum and maximum depth bounds for light culling.
18+
vertex VertexOutput depth_pre_pass_vertex(Vertex in [[ stage_in ]],
19+
constant AAPLFrameData & frameData [[ buffer(AAPLBufferIndexFrameData) ]])
20+
{
21+
// Make the position a float4 to perform 4x4 matrix math on it.
22+
VertexOutput out;
23+
float4 position = float4(in.position, 1.0);
24+
25+
// Calculate the position in clip space.
26+
out.position = frameData.projectionMatrix * frameData.modelViewMatrix * position;
27+
28+
return out;
29+
}
30+
31+
fragment ColorData depth_pre_pass_fragment(VertexOutput in [[ stage_in ]])
32+
{
33+
// Populate on-tile geometry buffer data.
34+
ColorData f;
35+
36+
// Setting color in the depth pre-pass is unnecessary, but may make debugging easier.
37+
// f.lighting = half4(0, 0, 0, 1);
38+
39+
// Set the depth in clip space, which you use in `AAPLCulling` to perform per-tile light culling.
40+
f.depth = in.position.z;
41+
42+
return f;
43+
}

Diff for: lexers/testdata/metal.expected

+175
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
[
2+
{"type":"CommentPreproc","value":"#include"},
3+
{"type":"Text","value":" "},
4+
{"type":"CommentPreprocFile","value":"\u003cmetal_stdlib\u003e"},
5+
{"type":"CommentPreproc","value":"\n"},
6+
{"type":"Text","value":"\n"},
7+
{"type":"Keyword","value":"using"},
8+
{"type":"Text","value":" "},
9+
{"type":"Keyword","value":"namespace"},
10+
{"type":"Text","value":" "},
11+
{"type":"Name","value":"metal"},
12+
{"type":"Punctuation","value":";"},
13+
{"type":"Text","value":"\n\n"},
14+
{"type":"CommentSingle","value":"// Include header shared between C code and .metal files.\n"},
15+
{"type":"CommentPreproc","value":"#include"},
16+
{"type":"Text","value":" "},
17+
{"type":"CommentPreprocFile","value":"\"AAPLShaderTypes.h\""},
18+
{"type":"CommentPreproc","value":"\n"},
19+
{"type":"Text","value":"\n"},
20+
{"type":"CommentSingle","value":"// Include header shared between all .metal files.\n"},
21+
{"type":"CommentPreproc","value":"#include"},
22+
{"type":"Text","value":" "},
23+
{"type":"CommentPreprocFile","value":"\"AAPLShaderCommon.h\""},
24+
{"type":"CommentPreproc","value":"\n"},
25+
{"type":"Text","value":"\n"},
26+
{"type":"Keyword","value":"struct"},
27+
{"type":"Text","value":" "},
28+
{"type":"NameClass","value":"VertexOutput"},
29+
{"type":"Text","value":"\n"},
30+
{"type":"Punctuation","value":"{"},
31+
{"type":"Text","value":"\n "},
32+
{"type":"KeywordType","value":"float4"},
33+
{"type":"Text","value":" "},
34+
{"type":"Name","value":"position"},
35+
{"type":"Text","value":" "},
36+
{"type":"NameAttribute","value":"[[position]]"},
37+
{"type":"Punctuation","value":";"},
38+
{"type":"Text","value":"\n"},
39+
{"type":"Punctuation","value":"};"},
40+
{"type":"Text","value":"\n\n"},
41+
{"type":"CommentSingle","value":"// A depth pre-pass is necessary in forward plus rendering to produce\n// minimum and maximum depth bounds for light culling.\n"},
42+
{"type":"Keyword","value":"vertex"},
43+
{"type":"Text","value":" "},
44+
{"type":"Name","value":"VertexOutput"},
45+
{"type":"Text","value":" "},
46+
{"type":"NameFunction","value":"depth_pre_pass_vertex"},
47+
{"type":"Punctuation","value":"("},
48+
{"type":"Name","value":"Vertex"},
49+
{"type":"Text","value":" "},
50+
{"type":"Name","value":"in"},
51+
{"type":"Text","value":" "},
52+
{"type":"NameAttribute","value":"[[ stage_in ]]"},
53+
{"type":"Punctuation","value":","},
54+
{"type":"Text","value":"\n "},
55+
{"type":"Keyword","value":"constant"},
56+
{"type":"Text","value":" "},
57+
{"type":"Name","value":"AAPLFrameData"},
58+
{"type":"Text","value":" "},
59+
{"type":"Operator","value":"\u0026"},
60+
{"type":"Text","value":" "},
61+
{"type":"Name","value":"frameData"},
62+
{"type":"Text","value":" "},
63+
{"type":"Punctuation","value":"[["},
64+
{"type":"Text","value":" "},
65+
{"type":"Name","value":"buffer"},
66+
{"type":"Punctuation","value":"("},
67+
{"type":"Name","value":"AAPLBufferIndexFrameData"},
68+
{"type":"Punctuation","value":")"},
69+
{"type":"Text","value":" "},
70+
{"type":"Punctuation","value":"]])"},
71+
{"type":"Text","value":"\n"},
72+
{"type":"Punctuation","value":"{"},
73+
{"type":"Text","value":"\n "},
74+
{"type":"CommentSingle","value":"// Make the position a float4 to perform 4x4 matrix math on it.\n"},
75+
{"type":"Text","value":" "},
76+
{"type":"Name","value":"VertexOutput"},
77+
{"type":"Text","value":" "},
78+
{"type":"Name","value":"out"},
79+
{"type":"Punctuation","value":";"},
80+
{"type":"Text","value":"\n "},
81+
{"type":"KeywordType","value":"float4"},
82+
{"type":"Text","value":" "},
83+
{"type":"Name","value":"position"},
84+
{"type":"Text","value":" "},
85+
{"type":"Operator","value":"="},
86+
{"type":"Text","value":" "},
87+
{"type":"KeywordType","value":"float4"},
88+
{"type":"Punctuation","value":"("},
89+
{"type":"Name","value":"in"},
90+
{"type":"Punctuation","value":"."},
91+
{"type":"Name","value":"position"},
92+
{"type":"Punctuation","value":","},
93+
{"type":"Text","value":" "},
94+
{"type":"LiteralNumberFloat","value":"1.0"},
95+
{"type":"Punctuation","value":");"},
96+
{"type":"Text","value":"\n\n "},
97+
{"type":"CommentSingle","value":"// Calculate the position in clip space.\n"},
98+
{"type":"Text","value":" "},
99+
{"type":"Name","value":"out"},
100+
{"type":"Punctuation","value":"."},
101+
{"type":"Name","value":"position"},
102+
{"type":"Text","value":" "},
103+
{"type":"Operator","value":"="},
104+
{"type":"Text","value":" "},
105+
{"type":"Name","value":"frameData"},
106+
{"type":"Punctuation","value":"."},
107+
{"type":"Name","value":"projectionMatrix"},
108+
{"type":"Text","value":" "},
109+
{"type":"Operator","value":"*"},
110+
{"type":"Text","value":" "},
111+
{"type":"Name","value":"frameData"},
112+
{"type":"Punctuation","value":"."},
113+
{"type":"Name","value":"modelViewMatrix"},
114+
{"type":"Text","value":" "},
115+
{"type":"Operator","value":"*"},
116+
{"type":"Text","value":" "},
117+
{"type":"Name","value":"position"},
118+
{"type":"Punctuation","value":";"},
119+
{"type":"Text","value":"\n\n "},
120+
{"type":"Keyword","value":"return"},
121+
{"type":"Text","value":" "},
122+
{"type":"Name","value":"out"},
123+
{"type":"Punctuation","value":";"},
124+
{"type":"Text","value":"\n"},
125+
{"type":"Punctuation","value":"}"},
126+
{"type":"Text","value":"\n\n"},
127+
{"type":"Keyword","value":"fragment"},
128+
{"type":"Text","value":" "},
129+
{"type":"Name","value":"ColorData"},
130+
{"type":"Text","value":" "},
131+
{"type":"NameFunction","value":"depth_pre_pass_fragment"},
132+
{"type":"Punctuation","value":"("},
133+
{"type":"Name","value":"VertexOutput"},
134+
{"type":"Text","value":" "},
135+
{"type":"Name","value":"in"},
136+
{"type":"Text","value":" "},
137+
{"type":"NameAttribute","value":"[[ stage_in ]]"},
138+
{"type":"Punctuation","value":")"},
139+
{"type":"Text","value":"\n"},
140+
{"type":"Punctuation","value":"{"},
141+
{"type":"Text","value":"\n "},
142+
{"type":"CommentSingle","value":"// Populate on-tile geometry buffer data.\n"},
143+
{"type":"Text","value":" "},
144+
{"type":"Name","value":"ColorData"},
145+
{"type":"Text","value":" "},
146+
{"type":"Name","value":"f"},
147+
{"type":"Punctuation","value":";"},
148+
{"type":"Text","value":"\n\n "},
149+
{"type":"CommentSingle","value":"// Setting color in the depth pre-pass is unnecessary, but may make debugging easier.\n"},
150+
{"type":"Text","value":" "},
151+
{"type":"CommentSingle","value":"// f.lighting = half4(0, 0, 0, 1);\n"},
152+
{"type":"Text","value":"\n "},
153+
{"type":"CommentSingle","value":"// Set the depth in clip space, which you use in `AAPLCulling` to perform per-tile light culling.\n"},
154+
{"type":"Text","value":" "},
155+
{"type":"Name","value":"f"},
156+
{"type":"Punctuation","value":"."},
157+
{"type":"Name","value":"depth"},
158+
{"type":"Text","value":" "},
159+
{"type":"Operator","value":"="},
160+
{"type":"Text","value":" "},
161+
{"type":"Name","value":"in"},
162+
{"type":"Punctuation","value":"."},
163+
{"type":"Name","value":"position"},
164+
{"type":"Punctuation","value":"."},
165+
{"type":"Name","value":"z"},
166+
{"type":"Punctuation","value":";"},
167+
{"type":"Text","value":"\n\n "},
168+
{"type":"Keyword","value":"return"},
169+
{"type":"Text","value":" "},
170+
{"type":"Name","value":"f"},
171+
{"type":"Punctuation","value":";"},
172+
{"type":"Text","value":"\n"},
173+
{"type":"Punctuation","value":"}"},
174+
{"type":"Text","value":"\n"}
175+
]

0 commit comments

Comments
 (0)