1"""
2 pygments.lexers.wgsl
3 ~~~~~~~~~~~~~~~~~~~~
4
5 Lexer for the WebGPU Shading Language.
6
7 :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS.
8 :license: BSD, see LICENSE for details.
9"""
10
11from pygments.lexer import RegexLexer, include, words, default
12from pygments.token import Comment, Operator, Keyword, Name, \
13 Number, Punctuation, Whitespace
14from pygments import unistring as uni
15
16__all__ = ['WgslLexer']
17
18LF = '\\u000a'
19VT = '\\u000b'
20FF = '\\u000c'
21CR = '\\u000d'
22NextLine = '\\u0085'
23LineSep = '\\u2028'
24ParaSep = '\\u2029'
25LineEndCodePoints = [LF,VT,FF,CR,NextLine,LineSep,ParaSep]
26NotLineEndRE = '[^' + "".join(LineEndCodePoints) + ']'
27LineEndRE = '[' + "".join(LineEndCodePoints) + ']'
28
29# https://www.w3.org/TR/WGSL/#syntax-ident_pattern_token
30ident_pattern_token = f'([{uni.xid_start}][{uni.xid_continue}]+)|[{uni.xid_start}]'
31
32
33class WgslLexer(RegexLexer):
34 """
35 Lexer for the WebGPU Shading Language.
36 """
37 name = 'WebGPU Shading Language'
38 url = 'https://www.w3.org/TR/WGSL/'
39 aliases = ['wgsl']
40 filenames = ['*.wgsl']
41 mimetypes = ['text/wgsl']
42 version_added = '2.15'
43
44 # https://www.w3.org/TR/WGSL/#var-and-value
45 keyword_decl = (words('var let const override'.split(),suffix=r'\b'), Keyword.Declaration)
46 # https://www.w3.org/TR/WGSL/#keyword-summary
47 keywords = (words("""
48 alias
49 break
50 case
51 const_assert
52 continue
53 continuing
54 default
55 diagnostic
56 discard
57 else
58 enable
59 false
60 fn
61 for
62 if
63 loop
64 requires
65 return
66 struct
67 switch
68 true
69 while
70 """.split(), suffix=r'\b'), Keyword)
71
72 # https://www.w3.org/TR/WGSL/#reserved-words
73 keyword_reserved = (words("""
74 NULL
75 Self
76 abstract
77 active
78 alignas
79 alignof
80 as
81 asm
82 asm_fragment
83 async
84 attribute
85 auto
86 await
87 become
88 binding_array
89 cast
90 catch
91 class
92 co_await
93 co_return
94 co_yield
95 coherent
96 column_major
97 common
98 compile
99 compile_fragment
100 concept
101 const_cast
102 consteval
103 constexpr
104 constinit
105 crate
106 debugger
107 decltype
108 delete
109 demote
110 demote_to_helper
111 do
112 dynamic_cast
113 enum
114 explicit
115 export
116 extends
117 extern
118 external
119 fallthrough
120 filter
121 final
122 finally
123 friend
124 from
125 fxgroup
126 get
127 goto
128 groupshared
129 highp
130 impl
131 implements
132 import
133 inline
134 instanceof
135 interface
136 layout
137 lowp
138 macro
139 macro_rules
140 match
141 mediump
142 meta
143 mod
144 module
145 move
146 mut
147 mutable
148 namespace
149 new
150 nil
151 noexcept
152 noinline
153 nointerpolation
154 noperspective
155 null
156 nullptr
157 of
158 operator
159 package
160 packoffset
161 partition
162 pass
163 patch
164 pixelfragment
165 precise
166 precision
167 premerge
168 priv
169 protected
170 pub
171 public
172 readonly
173 ref
174 regardless
175 register
176 reinterpret_cast
177 require
178 resource
179 restrict
180 self
181 set
182 shared
183 sizeof
184 smooth
185 snorm
186 static
187 static_assert
188 static_cast
189 std
190 subroutine
191 super
192 target
193 template
194 this
195 thread_local
196 throw
197 trait
198 try
199 type
200 typedef
201 typeid
202 typename
203 typeof
204 union
205 unless
206 unorm
207 unsafe
208 unsized
209 use
210 using
211 varying
212 virtual
213 volatile
214 wgsl
215 where
216 with
217 writeonly
218 yield
219 """.split(), suffix=r'\b'), Keyword.Reserved)
220
221 # https://www.w3.org/TR/WGSL/#predeclared-enumerants
222 predeclared_enums = (words("""
223 read write read_write
224 function private workgroup uniform storage
225 perspective linear flat
226 center centroid sample
227 vertex_index instance_index position front_facing frag_depth
228 local_invocation_id local_invocation_index
229 global_invocation_id workgroup_id num_workgroups
230 sample_index sample_mask
231 rgba8unorm
232 rgba8snorm
233 rgba8uint
234 rgba8sint
235 rgba16uint
236 rgba16sint
237 rgba16float
238 r32uint
239 r32sint
240 r32float
241 rg32uint
242 rg32sint
243 rg32float
244 rgba32uint
245 rgba32sint
246 rgba32float
247 bgra8unorm
248 """.split(), suffix=r'\b'), Name.Builtin)
249
250 # https://www.w3.org/TR/WGSL/#predeclared-types
251 predeclared_types = (words("""
252 bool
253 f16
254 f32
255 i32
256 sampler sampler_comparison
257 texture_depth_2d
258 texture_depth_2d_array
259 texture_depth_cube
260 texture_depth_cube_array
261 texture_depth_multisampled_2d
262 texture_external
263 texture_external
264 u32
265 """.split(), suffix=r'\b'), Name.Builtin)
266
267 # https://www.w3.org/TR/WGSL/#predeclared-types
268 predeclared_type_generators = (words("""
269 array
270 atomic
271 mat2x2
272 mat2x3
273 mat2x4
274 mat3x2
275 mat3x3
276 mat3x4
277 mat4x2
278 mat4x3
279 mat4x4
280 ptr
281 texture_1d
282 texture_2d
283 texture_2d_array
284 texture_3d
285 texture_cube
286 texture_cube_array
287 texture_multisampled_2d
288 texture_storage_1d
289 texture_storage_2d
290 texture_storage_2d_array
291 texture_storage_3d
292 vec2
293 vec3
294 vec4
295 """.split(), suffix=r'\b'), Name.Builtin)
296
297 # Predeclared type aliases for vectors
298 # https://www.w3.org/TR/WGSL/#vector-types
299 predeclared_type_alias_vectors = (words("""
300 vec2i vec3i vec4i
301 vec2u vec3u vec4u
302 vec2f vec3f vec4f
303 vec2h vec3h vec4h
304 """.split(), suffix=r'\b'), Name.Builtin)
305
306 # Predeclared type aliases for matrices
307 # https://www.w3.org/TR/WGSL/#matrix-types
308 predeclared_type_alias_matrices = (words("""
309 mat2x2f mat2x3f mat2x4f
310 mat3x2f mat3x3f mat3x4f
311 mat4x2f mat4x3f mat4x4f
312 mat2x2h mat2x3h mat2x4h
313 mat3x2h mat3x3h mat3x4h
314 mat4x2h mat4x3h mat4x4h
315 """.split(), suffix=r'\b'), Name.Builtin)
316
317 tokens = {
318 'blankspace': [
319 # https://www.w3.org/TR/WGSL/#blankspace
320 (r'[\u0020\u0009\u000a\u000b\u000c\u000d\u0085\u200e\u200f\u2028\u2029]+', Whitespace),
321 ],
322 'comments': [
323 # Line ending comments
324 # Match up CR/LF pair first.
325 (rf'//{NotLineEndRE}*{CR}{LF}', Comment.Single),
326 (rf'//{NotLineEndRE}*{LineEndRE}', Comment.Single),
327 (r'/\*', Comment.Multiline, 'block_comment'),
328 ],
329 'attribute': [
330 include('blankspace'),
331 include('comments'),
332 (ident_pattern_token, Name.Decorator,'#pop'),
333 default('#pop'),
334 ],
335 'root': [
336 include('blankspace'),
337 include('comments'),
338
339 # Attributes.
340 # https://www.w3.org/TR/WGSL/#attributes
341 # Mark the '@' and the attribute name as a decorator.
342 (r'@', Name.Decorator, 'attribute'),
343
344 # Keywords
345 (r'(true|false)\b', Keyword.Constant),
346 keyword_decl,
347 keywords,
348 keyword_reserved,
349
350 # Predeclared
351 predeclared_enums,
352 predeclared_types,
353 predeclared_type_generators,
354 predeclared_type_alias_vectors,
355 predeclared_type_alias_matrices,
356
357 # Decimal float literals
358 # https://www.w3.org/TR/WGSL/#syntax-decimal_float_literal
359 # 0, with type-specifying suffix.
360 (r'0[fh]', Number.Float),
361 # Other decimal integer, with type-specifying suffix.
362 (r'[1-9][0-9]*[fh]', Number.Float),
363 # Has decimal point, at least one digit after decimal.
364 (r'[0-9]*\.[0-9]+([eE][+-]?[0-9]+)?[fh]?', Number.Float),
365 # Has decimal point, at least one digit before decimal.
366 (r'[0-9]+\.[0-9]*([eE][+-]?[0-9]+)?[fh]?', Number.Float),
367 # Has at least one digit, and has an exponent.
368 (r'[0-9]+[eE][+-]?[0-9]+[fh]?', Number.Float),
369
370 # Hex float literals
371 # https://www.w3.org/TR/WGSL/#syntax-hex_float_literal
372 (r'0[xX][0-9a-fA-F]*\.[0-9a-fA-F]+([pP][+-]?[0-9]+[fh]?)?', Number.Float),
373 (r'0[xX][0-9a-fA-F]+\.[0-9a-fA-F]*([pP][+-]?[0-9]+[fh]?)?', Number.Float),
374 (r'0[xX][0-9a-fA-F]+[pP][+-]?[0-9]+[fh]?', Number.Float),
375
376 # Hexadecimal integer literals
377 # https://www.w3.org/TR/WGSL/#syntax-hex_int_literal
378 (r'0[xX][0-9a-fA-F]+[iu]?', Number.Hex),
379 # Decimal integer literals
380 # https://www.w3.org/TR/WGSL/#syntax-decimal_int_literal
381 # We need two rules here because 01 is not valid.
382 (r'[1-9][0-9]*[iu]?', Number.Integer),
383 (r'0[iu]?', Number.Integer), # Must match last.
384
385 # Operators and Punctuation
386 (r'[{}()\[\],\.;:]', Punctuation),
387 (r'->', Punctuation), # Return-type arrow
388 (r'[+\-*/%&|<>^!~=]', Operator),
389
390 # TODO: Treat context-depedendent names specially
391 # https://www.w3.org/TR/WGSL/#context-dependent-name
392
393 # Identifiers
394 (ident_pattern_token, Name),
395
396 # TODO: templates start and end tokens.
397 # https://www.w3.org/TR/WGSL/#template-lists-sec
398 ],
399 'block_comment': [
400 # https://www.w3.org/TR/WGSL/#block-comment
401 (r'[^*/]+', Comment.Multiline),
402 (r'/\*', Comment.Multiline, '#push'),
403 (r'\*/', Comment.Multiline, '#pop'),
404 (r'[*/]', Comment.Multiline),
405 ],
406 }