1use alloc::{vec, vec::Vec};
2use core::num::NonZeroU32;
3
4use crate::{
5 front::glsl::{
6 ast::{QualifierKey, QualifierValue, StorageQualifier, StructLayout, TypeQualifiers},
7 context::Context,
8 error::ExpectedToken,
9 parser::ParsingContext,
10 token::{Token, TokenValue},
11 Error, ErrorKind, Frontend, Result,
12 },
13 AddressSpace, ArraySize, Handle, Span, Type, TypeInner,
14};
15
16impl ParsingContext<'_> {
17 pub fn parse_array_specifier(
20 &mut self,
21 frontend: &mut Frontend,
22 ctx: &mut Context,
23 span: &mut Span,
24 ty: &mut Handle<Type>,
25 ) -> Result<()> {
26 while self.parse_array_specifier_single(frontend, ctx, span, ty)? {}
27 Ok(())
28 }
29
30 fn parse_array_specifier_single(
32 &mut self,
33 frontend: &mut Frontend,
34 ctx: &mut Context,
35 span: &mut Span,
36 ty: &mut Handle<Type>,
37 ) -> Result<bool> {
38 if self.bump_if(frontend, TokenValue::LeftBracket).is_some() {
39 let size = if let Some(Token { meta, .. }) =
40 self.bump_if(frontend, TokenValue::RightBracket)
41 {
42 span.subsume(meta);
43 ArraySize::Dynamic
44 } else {
45 let (value, constant_span) = self.parse_uint_constant(frontend, ctx)?;
46 let size = NonZeroU32::new(value).ok_or(Error {
47 kind: ErrorKind::SemanticError("Array size must be greater than zero".into()),
48 meta: constant_span,
49 })?;
50 let end_span = self.expect(frontend, TokenValue::RightBracket)?.meta;
51 span.subsume(end_span);
52 ArraySize::Constant(size)
53 };
54
55 frontend.layouter.update(ctx.module.to_ctx()).unwrap();
56 let stride = frontend.layouter[*ty].to_stride();
57 *ty = ctx.module.types.insert(
58 Type {
59 name: None,
60 inner: TypeInner::Array {
61 base: *ty,
62 size,
63 stride,
64 },
65 },
66 *span,
67 );
68
69 Ok(true)
70 } else {
71 Ok(false)
72 }
73 }
74
75 pub fn parse_type(
76 &mut self,
77 frontend: &mut Frontend,
78 ctx: &mut Context,
79 ) -> Result<(Option<Handle<Type>>, Span)> {
80 let token = self.bump(frontend)?;
81 let mut handle = match token.value {
82 TokenValue::Void => return Ok((None, token.meta)),
83 TokenValue::TypeName(ty) => ctx.module.types.insert(ty, token.meta),
84 TokenValue::Struct => {
85 let mut meta = token.meta;
86 let ty_name = self.expect_ident(frontend)?.0;
87 self.expect(frontend, TokenValue::LeftBrace)?;
88 let mut members = Vec::new();
89 let span = self.parse_struct_declaration_list(
90 frontend,
91 ctx,
92 &mut members,
93 StructLayout::Std140,
94 )?;
95 let end_meta = self.expect(frontend, TokenValue::RightBrace)?.meta;
96 meta.subsume(end_meta);
97 let ty = ctx.module.types.insert(
98 Type {
99 name: Some(ty_name.clone()),
100 inner: TypeInner::Struct { members, span },
101 },
102 meta,
103 );
104 frontend.lookup_type.insert(ty_name, ty);
105 ty
106 }
107 TokenValue::Identifier(ident) => match frontend.lookup_type.get(&ident) {
108 Some(ty) => *ty,
109 None => {
110 return Err(Error {
111 kind: ErrorKind::UnknownType(ident),
112 meta: token.meta,
113 })
114 }
115 },
116 _ => {
117 return Err(Error {
118 kind: ErrorKind::InvalidToken(
119 token.value,
120 vec![
121 TokenValue::Void.into(),
122 TokenValue::Struct.into(),
123 ExpectedToken::TypeName,
124 ],
125 ),
126 meta: token.meta,
127 });
128 }
129 };
130
131 let mut span = token.meta;
132 self.parse_array_specifier(frontend, ctx, &mut span, &mut handle)?;
133 Ok((Some(handle), span))
134 }
135
136 pub fn parse_type_non_void(
137 &mut self,
138 frontend: &mut Frontend,
139 ctx: &mut Context,
140 ) -> Result<(Handle<Type>, Span)> {
141 let (maybe_ty, meta) = self.parse_type(frontend, ctx)?;
142 let ty = maybe_ty.ok_or_else(|| Error {
143 kind: ErrorKind::SemanticError("Type can't be void".into()),
144 meta,
145 })?;
146
147 Ok((ty, meta))
148 }
149
150 pub fn peek_type_qualifier(&mut self, frontend: &mut Frontend) -> bool {
151 self.peek(frontend).is_some_and(|t| match t.value {
152 TokenValue::Invariant
153 | TokenValue::Interpolation(_)
154 | TokenValue::Sampling(_)
155 | TokenValue::PrecisionQualifier(_)
156 | TokenValue::Const
157 | TokenValue::In
158 | TokenValue::Out
159 | TokenValue::Uniform
160 | TokenValue::Shared
161 | TokenValue::Buffer
162 | TokenValue::Restrict
163 | TokenValue::MemoryQualifier(_)
164 | TokenValue::Layout => true,
165 _ => false,
166 })
167 }
168
169 pub fn parse_type_qualifiers<'a>(
170 &mut self,
171 frontend: &mut Frontend,
172 ctx: &mut Context,
173 ) -> Result<TypeQualifiers<'a>> {
174 let mut qualifiers = TypeQualifiers::default();
175
176 while self.peek_type_qualifier(frontend) {
177 let token = self.bump(frontend)?;
178
179 if token.value == TokenValue::Layout {
181 self.parse_layout_qualifier_id_list(frontend, ctx, &mut qualifiers)?;
182 continue;
183 }
184
185 qualifiers.span.subsume(token.meta);
186
187 match token.value {
188 TokenValue::Invariant => {
189 if qualifiers.invariant.is_some() {
190 frontend.errors.push(Error {
191 kind: ErrorKind::SemanticError(
192 "Cannot use more than one invariant qualifier per declaration"
193 .into(),
194 ),
195 meta: token.meta,
196 })
197 }
198
199 qualifiers.invariant = Some(token.meta);
200 }
201 TokenValue::Interpolation(i) => {
202 if qualifiers.interpolation.is_some() {
203 frontend.errors.push(Error {
204 kind: ErrorKind::SemanticError(
205 "Cannot use more than one interpolation qualifier per declaration"
206 .into(),
207 ),
208 meta: token.meta,
209 })
210 }
211
212 qualifiers.interpolation = Some((i, token.meta));
213 }
214 TokenValue::Const
215 | TokenValue::In
216 | TokenValue::Out
217 | TokenValue::Uniform
218 | TokenValue::Shared
219 | TokenValue::Buffer => {
220 let storage = match token.value {
221 TokenValue::Const => StorageQualifier::Const,
222 TokenValue::In => StorageQualifier::Input,
223 TokenValue::Out => StorageQualifier::Output,
224 TokenValue::Uniform => {
225 StorageQualifier::AddressSpace(AddressSpace::Uniform)
226 }
227 TokenValue::Shared => {
228 StorageQualifier::AddressSpace(AddressSpace::WorkGroup)
229 }
230 TokenValue::Buffer => {
231 StorageQualifier::AddressSpace(AddressSpace::Storage {
232 access: crate::StorageAccess::LOAD | crate::StorageAccess::STORE,
233 })
234 }
235 _ => unreachable!(),
236 };
237
238 if StorageQualifier::AddressSpace(AddressSpace::Function)
239 != qualifiers.storage.0
240 {
241 frontend.errors.push(Error {
242 kind: ErrorKind::SemanticError(
243 "Cannot use more than one storage qualifier per declaration".into(),
244 ),
245 meta: token.meta,
246 });
247 }
248
249 qualifiers.storage = (storage, token.meta);
250 }
251 TokenValue::Sampling(s) => {
252 if qualifiers.sampling.is_some() {
253 frontend.errors.push(Error {
254 kind: ErrorKind::SemanticError(
255 "Cannot use more than one sampling qualifier per declaration"
256 .into(),
257 ),
258 meta: token.meta,
259 })
260 }
261
262 qualifiers.sampling = Some((s, token.meta));
263 }
264 TokenValue::PrecisionQualifier(p) => {
265 if qualifiers.precision.is_some() {
266 frontend.errors.push(Error {
267 kind: ErrorKind::SemanticError(
268 "Cannot use more than one precision qualifier per declaration"
269 .into(),
270 ),
271 meta: token.meta,
272 })
273 }
274
275 qualifiers.precision = Some((p, token.meta));
276 }
277 TokenValue::MemoryQualifier(access) => {
278 let load_store = crate::StorageAccess::LOAD | crate::StorageAccess::STORE;
279 let storage_access = qualifiers
280 .storage_access
281 .get_or_insert((load_store, Span::default()));
282
283 if !storage_access.0.contains(!access & load_store) {
284 frontend.errors.push(Error {
285 kind: ErrorKind::SemanticError(
286 "The same memory qualifier can only be used once".into(),
287 ),
288 meta: token.meta,
289 })
290 }
291
292 storage_access.0 &= access;
293 storage_access.1.subsume(token.meta);
294 }
295 TokenValue::Restrict => continue,
296 _ => unreachable!(),
297 };
298 }
299
300 Ok(qualifiers)
301 }
302
303 pub fn parse_layout_qualifier_id_list(
304 &mut self,
305 frontend: &mut Frontend,
306 ctx: &mut Context,
307 qualifiers: &mut TypeQualifiers,
308 ) -> Result<()> {
309 self.expect(frontend, TokenValue::LeftParen)?;
310 loop {
311 self.parse_layout_qualifier_id(frontend, ctx, &mut qualifiers.layout_qualifiers)?;
312
313 if self.bump_if(frontend, TokenValue::Comma).is_some() {
314 continue;
315 }
316
317 break;
318 }
319 let token = self.expect(frontend, TokenValue::RightParen)?;
320 qualifiers.span.subsume(token.meta);
321
322 Ok(())
323 }
324
325 pub fn parse_layout_qualifier_id(
326 &mut self,
327 frontend: &mut Frontend,
328 ctx: &mut Context,
329 qualifiers: &mut crate::FastHashMap<QualifierKey, (QualifierValue, Span)>,
330 ) -> Result<()> {
331 let mut token = self.bump(frontend)?;
336 match token.value {
337 TokenValue::Identifier(name) => {
338 let (key, value) = match name.as_str() {
339 "std140" => (
340 QualifierKey::Layout,
341 QualifierValue::Layout(StructLayout::Std140),
342 ),
343 "std430" => (
344 QualifierKey::Layout,
345 QualifierValue::Layout(StructLayout::Std430),
346 ),
347 "index" => {
348 self.expect(frontend, TokenValue::Assign)?;
349 let (value, end_meta) = self.parse_uint_constant(frontend, ctx)?;
350 token.meta.subsume(end_meta);
351
352 (QualifierKey::Index, QualifierValue::Uint(value))
353 }
354 word => {
355 if let Some(format) = map_image_format(word) {
356 (QualifierKey::Format, QualifierValue::Format(format))
357 } else {
358 let key = QualifierKey::String(name.into());
359 let value = if self.bump_if(frontend, TokenValue::Assign).is_some() {
360 let (value, end_meta) =
361 match self.parse_uint_constant(frontend, ctx) {
362 Ok(v) => v,
363 Err(e) => {
364 frontend.errors.push(e);
365 (0, Span::default())
366 }
367 };
368 token.meta.subsume(end_meta);
369
370 QualifierValue::Uint(value)
371 } else {
372 QualifierValue::None
373 };
374
375 (key, value)
376 }
377 }
378 };
379
380 qualifiers.insert(key, (value, token.meta));
381 }
382 _ => frontend.errors.push(Error {
383 kind: ErrorKind::InvalidToken(token.value, vec![ExpectedToken::Identifier]),
384 meta: token.meta,
385 }),
386 }
387
388 Ok(())
389 }
390
391 pub fn peek_type_name(&mut self, frontend: &mut Frontend) -> bool {
392 self.peek(frontend).is_some_and(|t| match t.value {
393 TokenValue::TypeName(_) | TokenValue::Void => true,
394 TokenValue::Struct => true,
395 TokenValue::Identifier(ref ident) => frontend.lookup_type.contains_key(ident),
396 _ => false,
397 })
398 }
399}
400
401fn map_image_format(word: &str) -> Option<crate::StorageFormat> {
402 use crate::StorageFormat as Sf;
403
404 let format = match word {
405 "rgba32f" => Sf::Rgba32Float,
407 "rgba16f" => Sf::Rgba16Float,
408 "rg32f" => Sf::Rg32Float,
409 "rg16f" => Sf::Rg16Float,
410 "r11f_g11f_b10f" => Sf::Rg11b10Ufloat,
411 "r32f" => Sf::R32Float,
412 "r16f" => Sf::R16Float,
413 "rgba16" => Sf::Rgba16Unorm,
414 "rgb10_a2ui" => Sf::Rgb10a2Uint,
415 "rgb10_a2" => Sf::Rgb10a2Unorm,
416 "rgba8" => Sf::Rgba8Unorm,
417 "rg16" => Sf::Rg16Unorm,
418 "rg8" => Sf::Rg8Unorm,
419 "r16" => Sf::R16Unorm,
420 "r8" => Sf::R8Unorm,
421 "rgba16_snorm" => Sf::Rgba16Snorm,
422 "rgba8_snorm" => Sf::Rgba8Snorm,
423 "rg16_snorm" => Sf::Rg16Snorm,
424 "rg8_snorm" => Sf::Rg8Snorm,
425 "r16_snorm" => Sf::R16Snorm,
426 "r8_snorm" => Sf::R8Snorm,
427 "rgba32i" => Sf::Rgba32Sint,
429 "rgba16i" => Sf::Rgba16Sint,
430 "rgba8i" => Sf::Rgba8Sint,
431 "rg32i" => Sf::Rg32Sint,
432 "rg16i" => Sf::Rg16Sint,
433 "rg8i" => Sf::Rg8Sint,
434 "r32i" => Sf::R32Sint,
435 "r16i" => Sf::R16Sint,
436 "r8i" => Sf::R8Sint,
437 "rgba32ui" => Sf::Rgba32Uint,
439 "rgba16ui" => Sf::Rgba16Uint,
440 "rgba8ui" => Sf::Rgba8Uint,
441 "r64ui" => Sf::R64Uint,
442 "rg32ui" => Sf::Rg32Uint,
443 "rg16ui" => Sf::Rg16Uint,
444 "rg8ui" => Sf::Rg8Uint,
445 "r32ui" => Sf::R32Uint,
446 "r16ui" => Sf::R16Uint,
447 "r8ui" => Sf::R8Uint,
448 _ => return None,
451 };
452
453 Some(format)
454}