Skip to main content

naga/front/wgsl/parse/
mod.rs

1use alloc::{boxed::Box, vec::Vec};
2use directive::enable_extension::ImplementedEnableExtension;
3
4use crate::diagnostic_filter::{
5    self, DiagnosticFilter, DiagnosticFilterMap, DiagnosticFilterNode, FilterableTriggeringRule,
6    ShouldConflictOnFullDuplicate, StandardFilterableTriggeringRule,
7};
8use crate::front::wgsl::error::{DiagnosticAttributeNotSupportedPosition, Error, ExpectedToken};
9use crate::front::wgsl::parse::directive::enable_extension::{EnableExtension, EnableExtensions};
10use crate::front::wgsl::parse::directive::language_extension::LanguageExtension;
11use crate::front::wgsl::parse::directive::DirectiveKind;
12use crate::front::wgsl::parse::lexer::{Lexer, Token, TokenSpan};
13use crate::front::wgsl::parse::number::Number;
14use crate::front::wgsl::Result;
15use crate::front::SymbolTable;
16use crate::{Arena, FastHashSet, FastIndexSet, Handle, ShaderStage, Span};
17
18pub mod ast;
19pub mod conv;
20pub mod directive;
21pub mod lexer;
22pub mod number;
23
24/// State for constructing an AST expression.
25///
26/// Not to be confused with [`lower::ExpressionContext`], which is for producing
27/// Naga IR from the AST we produce here.
28///
29/// [`lower::ExpressionContext`]: super::lower::ExpressionContext
30struct ExpressionContext<'input, 'temp, 'out> {
31    /// The [`TranslationUnit::expressions`] arena to which we should contribute
32    /// expressions.
33    ///
34    /// [`TranslationUnit::expressions`]: ast::TranslationUnit::expressions
35    expressions: &'out mut Arena<ast::Expression<'input>>,
36
37    /// A map from identifiers in scope to the locals/arguments they represent.
38    ///
39    /// The handles refer to the [`locals`] arena; see that field's
40    /// documentation for details.
41    ///
42    /// [`locals`]: ExpressionContext::locals
43    local_table: &'temp mut SymbolTable<&'input str, Handle<ast::Local>>,
44
45    /// Local variable and function argument arena for the function we're building.
46    ///
47    /// Note that the [`ast::Local`] here is actually a zero-sized type. This
48    /// `Arena`'s only role is to assign a unique `Handle` to each local
49    /// identifier, and track its definition's span for use in diagnostics. All
50    /// the detailed information about locals - names, types, etc. - is kept in
51    /// the [`LocalDecl`] statements we parsed from their declarations. For
52    /// arguments, that information is kept in [`arguments`].
53    ///
54    /// In the AST, when an [`Ident`] expression refers to a local variable or
55    /// argument, its [`IdentExpr`] holds the referent's `Handle<Local>` in this
56    /// arena.
57    ///
58    /// During lowering, [`LocalDecl`] statements add entries to a per-function
59    /// table that maps `Handle<Local>` values to their Naga representations,
60    /// accessed via [`StatementContext::local_table`] and
61    /// [`LocalExpressionContext::local_table`]. This table is then consulted when
62    /// lowering subsequent [`Ident`] expressions.
63    ///
64    /// [`LocalDecl`]: ast::StatementKind::LocalDecl
65    /// [`arguments`]: ast::Function::arguments
66    /// [`Ident`]: ast::Expression::Ident
67    /// [`IdentExpr`]: ast::IdentExpr
68    /// [`StatementContext::local_table`]: super::lower::StatementContext::local_table
69    /// [`LocalExpressionContext::local_table`]: super::lower::LocalExpressionContext::local_table
70    locals: &'out mut Arena<ast::Local>,
71
72    /// Identifiers used by the current global declaration that have no local definition.
73    ///
74    /// This becomes the [`GlobalDecl`]'s [`dependencies`] set.
75    ///
76    /// Note that we don't know at parse time what kind of [`GlobalDecl`] the
77    /// name refers to. We can't look up names until we've seen the entire
78    /// translation unit.
79    ///
80    /// [`GlobalDecl`]: ast::GlobalDecl
81    /// [`dependencies`]: ast::GlobalDecl::dependencies
82    unresolved: &'out mut FastIndexSet<ast::Dependency<'input>>,
83}
84
85impl<'a> ExpressionContext<'a, '_, '_> {
86    fn parse_binary_op(
87        &mut self,
88        lexer: &mut Lexer<'a>,
89        classifier: impl Fn(Token<'a>) -> Option<crate::BinaryOperator>,
90        mut parser: impl FnMut(&mut Lexer<'a>, &mut Self) -> Result<'a, Handle<ast::Expression<'a>>>,
91    ) -> Result<'a, Handle<ast::Expression<'a>>> {
92        let start = lexer.start_byte_offset();
93        let mut accumulator = parser(lexer, self)?;
94        while let Some(op) = classifier(lexer.peek().0) {
95            let _ = lexer.next();
96            let left = accumulator;
97            let right = parser(lexer, self)?;
98            accumulator = self.expressions.append(
99                ast::Expression::Binary { op, left, right },
100                lexer.span_from(start),
101            );
102        }
103        Ok(accumulator)
104    }
105
106    fn declare_local(&mut self, name: ast::Ident<'a>) -> Result<'a, Handle<ast::Local>> {
107        let handle = self.locals.append(ast::Local, name.span);
108        if let Some(old) = self.local_table.add(name.name, handle) {
109            Err(Box::new(Error::Redefinition {
110                previous: self.locals.get_span(old),
111                current: name.span,
112            }))
113        } else {
114            Ok(handle)
115        }
116    }
117}
118
119/// Which grammar rule we are in the midst of parsing.
120///
121/// This is used for error checking. `Parser` maintains a stack of
122/// these and (occasionally) checks that it is being pushed and popped
123/// as expected.
124#[derive(Copy, Clone, Debug, PartialEq)]
125enum Rule {
126    Attribute,
127    VariableDecl,
128    FunctionDecl,
129    Block,
130    Statement,
131    PrimaryExpr,
132    SingularExpr,
133    UnaryExpr,
134    GeneralExpr,
135    Directive,
136    GenericExpr,
137    EnclosedExpr,
138    LhsExpr,
139}
140
141struct ParsedAttribute<T> {
142    value: Option<T>,
143}
144
145impl<T> Default for ParsedAttribute<T> {
146    fn default() -> Self {
147        Self { value: None }
148    }
149}
150
151impl<T> ParsedAttribute<T> {
152    fn set(&mut self, value: T, name_span: Span) -> Result<'static, ()> {
153        if self.value.is_some() {
154            return Err(Box::new(Error::RepeatedAttribute(name_span)));
155        }
156        self.value = Some(value);
157        Ok(())
158    }
159}
160
161#[derive(Default)]
162struct BindingParser<'a> {
163    location: ParsedAttribute<Handle<ast::Expression<'a>>>,
164    built_in: ParsedAttribute<crate::BuiltIn>,
165    interpolation: ParsedAttribute<crate::Interpolation>,
166    sampling: ParsedAttribute<crate::Sampling>,
167    invariant: ParsedAttribute<bool>,
168    blend_src: ParsedAttribute<Handle<ast::Expression<'a>>>,
169    per_primitive: ParsedAttribute<()>,
170}
171
172impl<'a> BindingParser<'a> {
173    fn parse(
174        &mut self,
175        parser: &mut Parser,
176        lexer: &mut Lexer<'a>,
177        name: &'a str,
178        name_span: Span,
179        ctx: &mut ExpressionContext<'a, '_, '_>,
180    ) -> Result<'a, ()> {
181        match name {
182            "location" => {
183                lexer.expect(Token::Paren('('))?;
184                self.location
185                    .set(parser.expression(lexer, ctx)?, name_span)?;
186                lexer.next_if(Token::Separator(','));
187                lexer.expect(Token::Paren(')'))?;
188            }
189            "builtin" => {
190                lexer.expect(Token::Paren('('))?;
191                let (raw, span) = lexer.next_ident_with_span()?;
192                self.built_in.set(
193                    conv::map_built_in(&lexer.enable_extensions, raw, span)?,
194                    name_span,
195                )?;
196                lexer.next_if(Token::Separator(','));
197                lexer.expect(Token::Paren(')'))?;
198            }
199            "interpolate" => {
200                lexer.expect(Token::Paren('('))?;
201                let (raw, span) = lexer.next_ident_with_span()?;
202                self.interpolation.set(
203                    conv::map_interpolation(&lexer.enable_extensions, raw, span)?,
204                    name_span,
205                )?;
206                if lexer.next_if(Token::Separator(','))
207                    && !matches!(lexer.peek().0, Token::Paren(')'))
208                {
209                    let (raw, span) = lexer.next_ident_with_span()?;
210                    self.sampling
211                        .set(conv::map_sampling(raw, span)?, name_span)?;
212                    lexer.next_if(Token::Separator(','));
213                }
214                lexer.expect(Token::Paren(')'))?;
215            }
216
217            "invariant" => {
218                self.invariant.set(true, name_span)?;
219            }
220            "blend_src" => {
221                lexer.require_enable_extension(
222                    ImplementedEnableExtension::DualSourceBlending,
223                    name_span,
224                )?;
225
226                lexer.expect(Token::Paren('('))?;
227                self.blend_src
228                    .set(parser.expression(lexer, ctx)?, name_span)?;
229                lexer.next_if(Token::Separator(','));
230                lexer.expect(Token::Paren(')'))?;
231            }
232            "per_primitive" => {
233                lexer.require_enable_extension(
234                    ImplementedEnableExtension::WgpuMeshShader,
235                    name_span,
236                )?;
237                self.per_primitive.set((), name_span)?;
238            }
239            _ => return Err(Box::new(Error::UnknownAttribute(name_span))),
240        }
241        Ok(())
242    }
243
244    fn finish(self, span: Span) -> Result<'a, Option<ast::Binding<'a>>> {
245        match (
246            self.location.value,
247            self.built_in.value,
248            self.interpolation.value,
249            self.sampling.value,
250            self.invariant.value.unwrap_or_default(),
251            self.blend_src.value,
252            self.per_primitive.value,
253        ) {
254            (None, None, None, None, false, None, None) => Ok(None),
255            (Some(location), None, interpolation, sampling, false, blend_src, per_primitive) => {
256                // Before handing over the completed `Module`, we call
257                // `apply_default_interpolation` to ensure that the interpolation and
258                // sampling have been explicitly specified on all vertex shader output and fragment
259                // shader input user bindings, so leaving them potentially `None` here is fine.
260                Ok(Some(ast::Binding::Location {
261                    location,
262                    interpolation,
263                    sampling,
264                    blend_src,
265                    per_primitive: per_primitive.is_some(),
266                }))
267            }
268            (None, Some(crate::BuiltIn::Position { .. }), None, None, invariant, None, None) => {
269                Ok(Some(ast::Binding::BuiltIn(crate::BuiltIn::Position {
270                    invariant,
271                })))
272            }
273            (None, Some(built_in), None, None, false, None, None) => {
274                Ok(Some(ast::Binding::BuiltIn(built_in)))
275            }
276            (_, _, _, _, _, _, _) => Err(Box::new(Error::InconsistentBinding(span))),
277        }
278    }
279}
280
281/// Configuration for the whole parser run.
282#[derive(Debug)]
283pub struct Options {
284    /// Controls whether the parser should parse doc comments.
285    pub parse_doc_comments: bool,
286    /// Capabilities to enable during parsing.
287    pub capabilities: crate::valid::Capabilities,
288}
289
290impl Options {
291    /// Creates a new default [`Options`].
292    pub const fn new() -> Self {
293        Options {
294            parse_doc_comments: false,
295            capabilities: crate::valid::Capabilities::all(),
296        }
297    }
298}
299
300#[derive(Debug)]
301pub struct Parser {
302    rules: Vec<(Rule, usize)>,
303    recursion_depth: u32,
304}
305
306impl Parser {
307    pub const fn new() -> Self {
308        Parser {
309            rules: Vec::new(),
310            recursion_depth: 0,
311        }
312    }
313
314    fn reset(&mut self) {
315        self.rules.clear();
316        self.recursion_depth = 0;
317    }
318
319    fn push_rule_span(&mut self, rule: Rule, lexer: &mut Lexer<'_>) {
320        self.rules.push((rule, lexer.start_byte_offset()));
321    }
322
323    fn pop_rule_span(&mut self, lexer: &Lexer<'_>) -> Span {
324        let (_, initial) = self.rules.pop().unwrap();
325        lexer.span_from(initial)
326    }
327
328    fn peek_rule_span(&mut self, lexer: &Lexer<'_>) -> Span {
329        let &(_, initial) = self.rules.last().unwrap();
330        lexer.span_from(initial)
331    }
332
333    fn race_rules(&self, rule0: Rule, rule1: Rule) -> Option<Rule> {
334        Some(
335            self.rules
336                .iter()
337                .rev()
338                .find(|&x| x.0 == rule0 || x.0 == rule1)?
339                .0,
340        )
341    }
342
343    fn track_recursion<'a, F, R>(&mut self, f: F) -> Result<'a, R>
344    where
345        F: FnOnce(&mut Self) -> Result<'a, R>,
346    {
347        self.recursion_depth += 1;
348        if self.recursion_depth >= 200 {
349            return Err(Box::new(Error::Internal("Parser recursion limit exceeded")));
350        }
351        let ret = f(self);
352        self.recursion_depth -= 1;
353        ret
354    }
355
356    fn switch_value<'a>(
357        &mut self,
358        lexer: &mut Lexer<'a>,
359        ctx: &mut ExpressionContext<'a, '_, '_>,
360    ) -> Result<'a, ast::SwitchValue<'a>> {
361        if lexer.next_if(Token::Word("default")) {
362            return Ok(ast::SwitchValue::Default);
363        }
364
365        let expr = self.expression(lexer, ctx)?;
366        Ok(ast::SwitchValue::Expr(expr))
367    }
368
369    /// Expects `name` to be consumed (not in lexer).
370    fn arguments<'a>(
371        &mut self,
372        lexer: &mut Lexer<'a>,
373        ctx: &mut ExpressionContext<'a, '_, '_>,
374    ) -> Result<'a, Vec<Handle<ast::Expression<'a>>>> {
375        self.push_rule_span(Rule::EnclosedExpr, lexer);
376        lexer.open_arguments()?;
377        let mut arguments = Vec::new();
378        loop {
379            if !arguments.is_empty() {
380                if !lexer.next_argument()? {
381                    break;
382                }
383            } else if lexer.next_if(Token::Paren(')')) {
384                break;
385            }
386            let arg = self.expression(lexer, ctx)?;
387            arguments.push(arg);
388        }
389
390        self.pop_rule_span(lexer);
391        Ok(arguments)
392    }
393
394    fn enclosed_expression<'a>(
395        &mut self,
396        lexer: &mut Lexer<'a>,
397        ctx: &mut ExpressionContext<'a, '_, '_>,
398    ) -> Result<'a, Handle<ast::Expression<'a>>> {
399        self.push_rule_span(Rule::EnclosedExpr, lexer);
400        let expr = self.expression(lexer, ctx)?;
401        self.pop_rule_span(lexer);
402        Ok(expr)
403    }
404
405    fn ident_expr<'a>(
406        &mut self,
407        name: &'a str,
408        name_span: Span,
409        ctx: &mut ExpressionContext<'a, '_, '_>,
410    ) -> ast::IdentExpr<'a> {
411        match ctx.local_table.lookup(name) {
412            Some(&local) => ast::IdentExpr::Local(local),
413            None => {
414                ctx.unresolved.insert(ast::Dependency {
415                    ident: name,
416                    usage: name_span,
417                });
418                ast::IdentExpr::Unresolved(name)
419            }
420        }
421    }
422
423    fn primary_expression<'a>(
424        &mut self,
425        lexer: &mut Lexer<'a>,
426        ctx: &mut ExpressionContext<'a, '_, '_>,
427        token: TokenSpan<'a>,
428    ) -> Result<'a, Handle<ast::Expression<'a>>> {
429        self.push_rule_span(Rule::PrimaryExpr, lexer);
430
431        const fn literal_ray_flag<'b>(flag: crate::RayFlag) -> ast::Expression<'b> {
432            ast::Expression::Literal(ast::Literal::Number(Number::U32(flag.bits())))
433        }
434        const fn literal_ray_intersection<'b>(
435            intersection: crate::RayQueryIntersection,
436        ) -> ast::Expression<'b> {
437            ast::Expression::Literal(ast::Literal::Number(Number::U32(intersection as u32)))
438        }
439
440        let expr = match token {
441            (Token::Paren('('), _) => {
442                let expr = self.enclosed_expression(lexer, ctx)?;
443                lexer.expect(Token::Paren(')'))?;
444                self.pop_rule_span(lexer);
445                return Ok(expr);
446            }
447            (Token::Word("true"), _) => ast::Expression::Literal(ast::Literal::Bool(true)),
448            (Token::Word("false"), _) => ast::Expression::Literal(ast::Literal::Bool(false)),
449            (Token::Number(res), span) => {
450                let num = res.map_err(|err| Error::BadNumber(span, err))?;
451
452                if let Some(enable_extension) = num.requires_enable_extension() {
453                    lexer.require_enable_extension(enable_extension, span)?;
454                }
455
456                ast::Expression::Literal(ast::Literal::Number(num))
457            }
458            (Token::Word("RAY_FLAG_NONE"), _) => literal_ray_flag(crate::RayFlag::empty()),
459            (Token::Word("RAY_FLAG_FORCE_OPAQUE"), _) => {
460                literal_ray_flag(crate::RayFlag::FORCE_OPAQUE)
461            }
462            (Token::Word("RAY_FLAG_FORCE_NO_OPAQUE"), _) => {
463                literal_ray_flag(crate::RayFlag::FORCE_NO_OPAQUE)
464            }
465            (Token::Word("RAY_FLAG_TERMINATE_ON_FIRST_HIT"), _) => {
466                literal_ray_flag(crate::RayFlag::TERMINATE_ON_FIRST_HIT)
467            }
468            (Token::Word("RAY_FLAG_SKIP_CLOSEST_HIT_SHADER"), _) => {
469                literal_ray_flag(crate::RayFlag::SKIP_CLOSEST_HIT_SHADER)
470            }
471            (Token::Word("RAY_FLAG_CULL_BACK_FACING"), _) => {
472                literal_ray_flag(crate::RayFlag::CULL_BACK_FACING)
473            }
474            (Token::Word("RAY_FLAG_CULL_FRONT_FACING"), _) => {
475                literal_ray_flag(crate::RayFlag::CULL_FRONT_FACING)
476            }
477            (Token::Word("RAY_FLAG_CULL_OPAQUE"), _) => {
478                literal_ray_flag(crate::RayFlag::CULL_OPAQUE)
479            }
480            (Token::Word("RAY_FLAG_CULL_NO_OPAQUE"), _) => {
481                literal_ray_flag(crate::RayFlag::CULL_NO_OPAQUE)
482            }
483            (Token::Word("RAY_FLAG_SKIP_TRIANGLES"), _) => {
484                literal_ray_flag(crate::RayFlag::SKIP_TRIANGLES)
485            }
486            (Token::Word("RAY_FLAG_SKIP_AABBS"), _) => literal_ray_flag(crate::RayFlag::SKIP_AABBS),
487            (Token::Word("RAY_QUERY_INTERSECTION_NONE"), _) => {
488                literal_ray_intersection(crate::RayQueryIntersection::None)
489            }
490            (Token::Word("RAY_QUERY_INTERSECTION_TRIANGLE"), _) => {
491                literal_ray_intersection(crate::RayQueryIntersection::Triangle)
492            }
493            (Token::Word("RAY_QUERY_INTERSECTION_GENERATED"), _) => {
494                literal_ray_intersection(crate::RayQueryIntersection::Generated)
495            }
496            (Token::Word("RAY_QUERY_INTERSECTION_AABB"), _) => {
497                literal_ray_intersection(crate::RayQueryIntersection::Aabb)
498            }
499            (Token::String(s), _) => ast::Expression::String(s),
500            (Token::Word(word), span) => {
501                let ident = self.template_elaborated_ident(word, span, lexer, ctx)?;
502
503                if let Token::Paren('(') = lexer.peek().0 {
504                    let arguments = self.arguments(lexer, ctx)?;
505                    ast::Expression::Call(ast::CallPhrase {
506                        function: ident,
507                        arguments,
508                    })
509                } else {
510                    ast::Expression::Ident(ident)
511                }
512            }
513            other => {
514                return Err(Box::new(Error::Unexpected(
515                    other.1,
516                    ExpectedToken::PrimaryExpression,
517                )))
518            }
519        };
520
521        self.pop_rule_span(lexer);
522        let span = lexer.span_with_start(token.1);
523        let expr = ctx.expressions.append(expr, span);
524        Ok(expr)
525    }
526
527    fn component_or_swizzle_specifier<'a>(
528        &mut self,
529        expr_start: Span,
530        lexer: &mut Lexer<'a>,
531        ctx: &mut ExpressionContext<'a, '_, '_>,
532        expr: Handle<ast::Expression<'a>>,
533    ) -> Result<'a, Handle<ast::Expression<'a>>> {
534        let mut expr = expr;
535
536        loop {
537            let expression = match lexer.peek().0 {
538                Token::Separator('.') => {
539                    let _ = lexer.next();
540                    let field = lexer.next_ident()?;
541
542                    ast::Expression::Member { base: expr, field }
543                }
544                Token::Paren('[') => {
545                    let _ = lexer.next();
546                    let index = self.enclosed_expression(lexer, ctx)?;
547                    lexer.expect(Token::Paren(']'))?;
548
549                    ast::Expression::Index { base: expr, index }
550                }
551                _ => break,
552            };
553
554            let span = lexer.span_with_start(expr_start);
555            expr = ctx.expressions.append(expression, span);
556        }
557
558        Ok(expr)
559    }
560
561    /// Parse a `unary_expression`.
562    fn unary_expression<'a>(
563        &mut self,
564        lexer: &mut Lexer<'a>,
565        ctx: &mut ExpressionContext<'a, '_, '_>,
566    ) -> Result<'a, Handle<ast::Expression<'a>>> {
567        self.push_rule_span(Rule::UnaryExpr, lexer);
568
569        enum UnaryOp {
570            Negate,
571            LogicalNot,
572            BitwiseNot,
573            Deref,
574            AddrOf,
575        }
576
577        let mut ops = Vec::new();
578        let mut expr;
579
580        loop {
581            match lexer.next() {
582                (Token::Operation('-'), span) => {
583                    ops.push((UnaryOp::Negate, span));
584                }
585                (Token::Operation('!'), span) => {
586                    ops.push((UnaryOp::LogicalNot, span));
587                }
588                (Token::Operation('~'), span) => {
589                    ops.push((UnaryOp::BitwiseNot, span));
590                }
591                (Token::Operation('*'), span) => {
592                    ops.push((UnaryOp::Deref, span));
593                }
594                (Token::Operation('&'), span) => {
595                    ops.push((UnaryOp::AddrOf, span));
596                }
597                token => {
598                    expr = self.singular_expression(lexer, ctx, token)?;
599                    break;
600                }
601            };
602        }
603
604        for (op, span) in ops.into_iter().rev() {
605            let e = match op {
606                UnaryOp::Negate => ast::Expression::Unary {
607                    op: crate::UnaryOperator::Negate,
608                    expr,
609                },
610                UnaryOp::LogicalNot => ast::Expression::Unary {
611                    op: crate::UnaryOperator::LogicalNot,
612                    expr,
613                },
614                UnaryOp::BitwiseNot => ast::Expression::Unary {
615                    op: crate::UnaryOperator::BitwiseNot,
616                    expr,
617                },
618                UnaryOp::Deref => ast::Expression::Deref(expr),
619                UnaryOp::AddrOf => ast::Expression::AddrOf(expr),
620            };
621            let span = lexer.span_with_start(span);
622            expr = ctx.expressions.append(e, span);
623        }
624
625        self.pop_rule_span(lexer);
626        Ok(expr)
627    }
628
629    /// Parse a `lhs_expression`.
630    ///
631    /// LHS expressions only support the `&` and `*` operators and
632    /// the `[]` and `.` postfix selectors.
633    fn lhs_expression<'a>(
634        &mut self,
635        lexer: &mut Lexer<'a>,
636        ctx: &mut ExpressionContext<'a, '_, '_>,
637        token: Option<TokenSpan<'a>>,
638        expected_token: ExpectedToken<'a>,
639    ) -> Result<'a, Handle<ast::Expression<'a>>> {
640        self.track_recursion(|this| {
641            this.push_rule_span(Rule::LhsExpr, lexer);
642            let token = token.unwrap_or_else(|| lexer.next());
643            let expr = match token {
644                (Token::Operation('*'), _) => {
645                    let expr =
646                        this.lhs_expression(lexer, ctx, None, ExpectedToken::LhsExpression)?;
647                    let expr = ast::Expression::Deref(expr);
648                    let span = this.peek_rule_span(lexer);
649                    ctx.expressions.append(expr, span)
650                }
651                (Token::Operation('&'), _) => {
652                    let expr =
653                        this.lhs_expression(lexer, ctx, None, ExpectedToken::LhsExpression)?;
654                    let expr = ast::Expression::AddrOf(expr);
655                    let span = this.peek_rule_span(lexer);
656                    ctx.expressions.append(expr, span)
657                }
658                (Token::Paren('('), span) => {
659                    let expr =
660                        this.lhs_expression(lexer, ctx, None, ExpectedToken::LhsExpression)?;
661                    lexer.expect(Token::Paren(')'))?;
662                    this.component_or_swizzle_specifier(span, lexer, ctx, expr)?
663                }
664                (Token::Word(word), span) => {
665                    let ident = this.ident_expr(word, span, ctx);
666                    let ident = ast::TemplateElaboratedIdent {
667                        ident,
668                        ident_span: span,
669                        template_list: Vec::new(),
670                        template_list_span: Span::UNDEFINED,
671                    };
672                    let ident = ctx.expressions.append(ast::Expression::Ident(ident), span);
673                    this.component_or_swizzle_specifier(span, lexer, ctx, ident)?
674                }
675                (_, span) => {
676                    return Err(Box::new(Error::Unexpected(span, expected_token)));
677                }
678            };
679
680            this.pop_rule_span(lexer);
681            Ok(expr)
682        })
683    }
684
685    /// Parse a `singular_expression`.
686    fn singular_expression<'a>(
687        &mut self,
688        lexer: &mut Lexer<'a>,
689        ctx: &mut ExpressionContext<'a, '_, '_>,
690        token: TokenSpan<'a>,
691    ) -> Result<'a, Handle<ast::Expression<'a>>> {
692        self.push_rule_span(Rule::SingularExpr, lexer);
693        let primary_expr = self.primary_expression(lexer, ctx, token)?;
694        let singular_expr =
695            self.component_or_swizzle_specifier(token.1, lexer, ctx, primary_expr)?;
696        self.pop_rule_span(lexer);
697
698        Ok(singular_expr)
699    }
700
701    fn equality_expression<'a>(
702        &mut self,
703        lexer: &mut Lexer<'a>,
704        context: &mut ExpressionContext<'a, '_, '_>,
705    ) -> Result<'a, Handle<ast::Expression<'a>>> {
706        // equality_expression
707        context.parse_binary_op(
708            lexer,
709            |token| match token {
710                Token::LogicalOperation('=') => Some(crate::BinaryOperator::Equal),
711                Token::LogicalOperation('!') => Some(crate::BinaryOperator::NotEqual),
712                _ => None,
713            },
714            // relational_expression
715            |lexer, context| {
716                let enclosing = self.race_rules(Rule::GenericExpr, Rule::EnclosedExpr);
717                context.parse_binary_op(
718                    lexer,
719                    match enclosing {
720                        Some(Rule::GenericExpr) => |token| match token {
721                            Token::LogicalOperation('<') => Some(crate::BinaryOperator::LessEqual),
722                            _ => None,
723                        },
724                        _ => |token| match token {
725                            Token::Paren('<') => Some(crate::BinaryOperator::Less),
726                            Token::Paren('>') => Some(crate::BinaryOperator::Greater),
727                            Token::LogicalOperation('<') => Some(crate::BinaryOperator::LessEqual),
728                            Token::LogicalOperation('>') => {
729                                Some(crate::BinaryOperator::GreaterEqual)
730                            }
731                            _ => None,
732                        },
733                    },
734                    // shift_expression
735                    |lexer, context| {
736                        context.parse_binary_op(
737                            lexer,
738                            match enclosing {
739                                Some(Rule::GenericExpr) => |token| match token {
740                                    Token::ShiftOperation('<') => {
741                                        Some(crate::BinaryOperator::ShiftLeft)
742                                    }
743                                    _ => None,
744                                },
745                                _ => |token| match token {
746                                    Token::ShiftOperation('<') => {
747                                        Some(crate::BinaryOperator::ShiftLeft)
748                                    }
749                                    Token::ShiftOperation('>') => {
750                                        Some(crate::BinaryOperator::ShiftRight)
751                                    }
752                                    _ => None,
753                                },
754                            },
755                            // additive_expression
756                            |lexer, context| {
757                                context.parse_binary_op(
758                                    lexer,
759                                    |token| match token {
760                                        Token::Operation('+') => Some(crate::BinaryOperator::Add),
761                                        Token::Operation('-') => {
762                                            Some(crate::BinaryOperator::Subtract)
763                                        }
764                                        _ => None,
765                                    },
766                                    // multiplicative_expression
767                                    |lexer, context| {
768                                        context.parse_binary_op(
769                                            lexer,
770                                            |token| match token {
771                                                Token::Operation('*') => {
772                                                    Some(crate::BinaryOperator::Multiply)
773                                                }
774                                                Token::Operation('/') => {
775                                                    Some(crate::BinaryOperator::Divide)
776                                                }
777                                                Token::Operation('%') => {
778                                                    Some(crate::BinaryOperator::Modulo)
779                                                }
780                                                _ => None,
781                                            },
782                                            |lexer, context| self.unary_expression(lexer, context),
783                                        )
784                                    },
785                                )
786                            },
787                        )
788                    },
789                )
790            },
791        )
792    }
793
794    fn expression<'a>(
795        &mut self,
796        lexer: &mut Lexer<'a>,
797        context: &mut ExpressionContext<'a, '_, '_>,
798    ) -> Result<'a, Handle<ast::Expression<'a>>> {
799        self.track_recursion(|this| {
800            this.push_rule_span(Rule::GeneralExpr, lexer);
801            // logical_or_expression
802            let handle = context.parse_binary_op(
803                lexer,
804                |token| match token {
805                    Token::LogicalOperation('|') => Some(crate::BinaryOperator::LogicalOr),
806                    _ => None,
807                },
808                // logical_and_expression
809                |lexer, context| {
810                    context.parse_binary_op(
811                        lexer,
812                        |token| match token {
813                            Token::LogicalOperation('&') => Some(crate::BinaryOperator::LogicalAnd),
814                            _ => None,
815                        },
816                        // inclusive_or_expression
817                        |lexer, context| {
818                            context.parse_binary_op(
819                                lexer,
820                                |token| match token {
821                                    Token::Operation('|') => {
822                                        Some(crate::BinaryOperator::InclusiveOr)
823                                    }
824                                    _ => None,
825                                },
826                                // exclusive_or_expression
827                                |lexer, context| {
828                                    context.parse_binary_op(
829                                        lexer,
830                                        |token| match token {
831                                            Token::Operation('^') => {
832                                                Some(crate::BinaryOperator::ExclusiveOr)
833                                            }
834                                            _ => None,
835                                        },
836                                        // and_expression
837                                        |lexer, context| {
838                                            context.parse_binary_op(
839                                                lexer,
840                                                |token| match token {
841                                                    Token::Operation('&') => {
842                                                        Some(crate::BinaryOperator::And)
843                                                    }
844                                                    _ => None,
845                                                },
846                                                |lexer, context| {
847                                                    this.equality_expression(lexer, context)
848                                                },
849                                            )
850                                        },
851                                    )
852                                },
853                            )
854                        },
855                    )
856                },
857            )?;
858            this.pop_rule_span(lexer);
859            Ok(handle)
860        })
861    }
862
863    fn optionally_typed_ident<'a>(
864        &mut self,
865        lexer: &mut Lexer<'a>,
866        ctx: &mut ExpressionContext<'a, '_, '_>,
867    ) -> Result<'a, (ast::Ident<'a>, Option<ast::TemplateElaboratedIdent<'a>>)> {
868        let name = lexer.next_ident()?;
869
870        let ty = if lexer.next_if(Token::Separator(':')) {
871            Some(self.type_specifier(lexer, ctx)?)
872        } else {
873            None
874        };
875
876        Ok((name, ty))
877    }
878
879    /// 'var' _disambiguate_template template_list? optionally_typed_ident
880    fn variable_decl<'a>(
881        &mut self,
882        lexer: &mut Lexer<'a>,
883        ctx: &mut ExpressionContext<'a, '_, '_>,
884    ) -> Result<'a, ast::GlobalVariable<'a>> {
885        self.push_rule_span(Rule::VariableDecl, lexer);
886        let (template_list, _) = self.maybe_template_list(lexer, ctx)?;
887        let (name, ty) = self.optionally_typed_ident(lexer, ctx)?;
888
889        let init = if lexer.next_if(Token::Operation('=')) {
890            let handle = self.expression(lexer, ctx)?;
891            Some(handle)
892        } else {
893            None
894        };
895        lexer.expect(Token::Separator(';'))?;
896        self.pop_rule_span(lexer);
897
898        Ok(ast::GlobalVariable {
899            name,
900            template_list,
901            binding: None,
902            ty,
903            init,
904            doc_comments: Vec::new(),
905            memory_decorations: crate::MemoryDecorations::empty(),
906        })
907    }
908
909    fn struct_body<'a>(
910        &mut self,
911        lexer: &mut Lexer<'a>,
912        ctx: &mut ExpressionContext<'a, '_, '_>,
913    ) -> Result<'a, Vec<ast::StructMember<'a>>> {
914        let mut members = Vec::new();
915        let mut member_names = FastHashSet::default();
916
917        lexer.expect(Token::Paren('{'))?;
918        let mut ready = true;
919        while !lexer.next_if(Token::Paren('}')) {
920            if !ready {
921                return Err(Box::new(Error::Unexpected(
922                    lexer.next().1,
923                    ExpectedToken::Token(Token::Separator(',')),
924                )));
925            }
926
927            let doc_comments = lexer.accumulate_doc_comments();
928
929            let (mut size, mut align) = (ParsedAttribute::default(), ParsedAttribute::default());
930            self.push_rule_span(Rule::Attribute, lexer);
931            let mut bind_parser = BindingParser::default();
932            while lexer.next_if(Token::Attribute) {
933                match lexer.next_ident_with_span()? {
934                    ("size", name_span) => {
935                        lexer.expect(Token::Paren('('))?;
936                        let expr = self.expression(lexer, ctx)?;
937                        lexer.next_if(Token::Separator(','));
938                        lexer.expect(Token::Paren(')'))?;
939                        size.set(expr, name_span)?;
940                    }
941                    ("align", name_span) => {
942                        lexer.expect(Token::Paren('('))?;
943                        let expr = self.expression(lexer, ctx)?;
944                        lexer.next_if(Token::Separator(','));
945                        lexer.expect(Token::Paren(')'))?;
946                        align.set(expr, name_span)?;
947                    }
948                    (word, word_span) => bind_parser.parse(self, lexer, word, word_span, ctx)?,
949                }
950            }
951
952            let bind_span = self.pop_rule_span(lexer);
953            let binding = bind_parser.finish(bind_span)?;
954
955            let name = lexer.next_ident()?;
956            lexer.expect(Token::Separator(':'))?;
957            let ty = self.type_specifier(lexer, ctx)?;
958            ready = lexer.next_if(Token::Separator(','));
959
960            members.push(ast::StructMember {
961                name,
962                ty,
963                binding,
964                size: size.value,
965                align: align.value,
966                doc_comments,
967            });
968
969            if !member_names.insert(name.name) {
970                return Err(Box::new(Error::Redefinition {
971                    previous: members
972                        .iter()
973                        .find(|x| x.name.name == name.name)
974                        .map(|x| x.name.span)
975                        .unwrap(),
976                    current: name.span,
977                }));
978            }
979        }
980
981        Ok(members)
982    }
983
984    fn maybe_template_list<'a>(
985        &mut self,
986        lexer: &mut Lexer<'a>,
987        ctx: &mut ExpressionContext<'a, '_, '_>,
988    ) -> Result<'a, (Vec<Handle<ast::Expression<'a>>>, Span)> {
989        let start = lexer.start_byte_offset();
990        if lexer.next_if(Token::TemplateArgsStart) {
991            let mut args = Vec::new();
992            args.push(self.expression(lexer, ctx)?);
993            while lexer.next_if(Token::Separator(',')) && lexer.peek().0 != Token::TemplateArgsEnd {
994                args.push(self.expression(lexer, ctx)?);
995            }
996            lexer.expect(Token::TemplateArgsEnd)?;
997            let span = lexer.span_from(start);
998            Ok((args, span))
999        } else {
1000            Ok((Vec::new(), Span::UNDEFINED))
1001        }
1002    }
1003
1004    fn template_elaborated_ident<'a>(
1005        &mut self,
1006        word: &'a str,
1007        span: Span,
1008        lexer: &mut Lexer<'a>,
1009        ctx: &mut ExpressionContext<'a, '_, '_>,
1010    ) -> Result<'a, ast::TemplateElaboratedIdent<'a>> {
1011        let ident = self.ident_expr(word, span, ctx);
1012        let (template_list, template_list_span) = self.maybe_template_list(lexer, ctx)?;
1013        Ok(ast::TemplateElaboratedIdent {
1014            ident,
1015            ident_span: span,
1016            template_list,
1017            template_list_span,
1018        })
1019    }
1020
1021    fn type_specifier<'a>(
1022        &mut self,
1023        lexer: &mut Lexer<'a>,
1024        ctx: &mut ExpressionContext<'a, '_, '_>,
1025    ) -> Result<'a, ast::TemplateElaboratedIdent<'a>> {
1026        let (name, span) = lexer.next_ident_with_span()?;
1027        self.template_elaborated_ident(name, span, lexer, ctx)
1028    }
1029
1030    /// Parses assignment, increment and decrement statements
1031    ///
1032    /// This does not consume or require a final `;` token. In the update
1033    /// expression of a C-style `for` loop header, there is no terminating `;`.
1034    fn variable_updating_statement<'a>(
1035        &mut self,
1036        lexer: &mut Lexer<'a>,
1037        ctx: &mut ExpressionContext<'a, '_, '_>,
1038        block: &mut ast::Block<'a>,
1039        token: TokenSpan<'a>,
1040        expected_token: ExpectedToken<'a>,
1041    ) -> Result<'a, ()> {
1042        match token {
1043            (Token::Word("_"), span) => {
1044                lexer.expect(Token::Operation('='))?;
1045                let expr = self.expression(lexer, ctx)?;
1046                let span = lexer.span_with_start(span);
1047                block.stmts.push(ast::Statement {
1048                    kind: ast::StatementKind::Phony(expr),
1049                    span,
1050                });
1051                return Ok(());
1052            }
1053            _ => {}
1054        }
1055        let target = self.lhs_expression(lexer, ctx, Some(token), expected_token)?;
1056
1057        let (op, value) = match lexer.next() {
1058            (Token::Operation('='), _) => {
1059                let value = self.expression(lexer, ctx)?;
1060                (None, value)
1061            }
1062            (Token::AssignmentOperation(c), _) => {
1063                use crate::BinaryOperator as Bo;
1064                let op = match c {
1065                    '<' => Bo::ShiftLeft,
1066                    '>' => Bo::ShiftRight,
1067                    '+' => Bo::Add,
1068                    '-' => Bo::Subtract,
1069                    '*' => Bo::Multiply,
1070                    '/' => Bo::Divide,
1071                    '%' => Bo::Modulo,
1072                    '&' => Bo::And,
1073                    '|' => Bo::InclusiveOr,
1074                    '^' => Bo::ExclusiveOr,
1075                    // Note: `consume_token` shouldn't produce any other assignment ops
1076                    _ => unreachable!(),
1077                };
1078
1079                let value = self.expression(lexer, ctx)?;
1080                (Some(op), value)
1081            }
1082            op_token @ (Token::IncrementOperation | Token::DecrementOperation, _) => {
1083                let op = match op_token.0 {
1084                    Token::IncrementOperation => ast::StatementKind::Increment,
1085                    Token::DecrementOperation => ast::StatementKind::Decrement,
1086                    _ => unreachable!(),
1087                };
1088
1089                let span = lexer.span_with_start(token.1);
1090                block.stmts.push(ast::Statement {
1091                    kind: op(target),
1092                    span,
1093                });
1094                return Ok(());
1095            }
1096            (_, span) => return Err(Box::new(Error::Unexpected(span, ExpectedToken::Assignment))),
1097        };
1098
1099        let span = lexer.span_with_start(token.1);
1100        block.stmts.push(ast::Statement {
1101            kind: ast::StatementKind::Assign { target, op, value },
1102            span,
1103        });
1104        Ok(())
1105    }
1106
1107    /// Parse a function call statement.
1108    ///
1109    /// This assumes that `token` has been consumed from the lexer.
1110    ///
1111    /// This does not consume or require a final `;` token. In the update
1112    /// expression of a C-style `for` loop header, there is no terminating `;`.
1113    fn maybe_func_call_statement<'a>(
1114        &mut self,
1115        lexer: &mut Lexer<'a>,
1116        context: &mut ExpressionContext<'a, '_, '_>,
1117        block: &mut ast::Block<'a>,
1118        token: TokenSpan<'a>,
1119    ) -> Result<'a, bool> {
1120        let (name, name_span) = match token {
1121            (Token::Word(name), span) => (name, span),
1122            _ => return Ok(false),
1123        };
1124        let ident = self.template_elaborated_ident(name, name_span, lexer, context)?;
1125        if ident.template_list.is_empty() && !matches!(lexer.peek(), (Token::Paren('('), _)) {
1126            return Ok(false);
1127        }
1128
1129        self.push_rule_span(Rule::SingularExpr, lexer);
1130
1131        let arguments = self.arguments(lexer, context)?;
1132        let span = lexer.span_with_start(name_span);
1133
1134        block.stmts.push(ast::Statement {
1135            kind: ast::StatementKind::Call(ast::CallPhrase {
1136                function: ident,
1137                arguments,
1138            }),
1139            span,
1140        });
1141
1142        self.pop_rule_span(lexer);
1143
1144        Ok(true)
1145    }
1146
1147    /// Parses func_call_statement and variable_updating_statement
1148    ///
1149    /// This does not consume or require a final `;` token. In the update
1150    /// expression of a C-style `for` loop header, there is no terminating `;`.
1151    fn func_call_or_variable_updating_statement<'a>(
1152        &mut self,
1153        lexer: &mut Lexer<'a>,
1154        context: &mut ExpressionContext<'a, '_, '_>,
1155        block: &mut ast::Block<'a>,
1156        token: TokenSpan<'a>,
1157        expected_token: ExpectedToken<'a>,
1158    ) -> Result<'a, ()> {
1159        if !self.maybe_func_call_statement(lexer, context, block, token)? {
1160            self.variable_updating_statement(lexer, context, block, token, expected_token)?;
1161        }
1162        Ok(())
1163    }
1164
1165    /// Parses variable_or_value_statement, func_call_statement and variable_updating_statement.
1166    ///
1167    /// This is equivalent to the `for_init` production in the WGSL spec,
1168    /// but it's also used for parsing these forms when they appear within a block,
1169    /// hence the longer name.
1170    ///
1171    /// This does not consume the following `;` token.
1172    fn variable_or_value_or_func_call_or_variable_updating_statement<'a>(
1173        &mut self,
1174        lexer: &mut Lexer<'a>,
1175        ctx: &mut ExpressionContext<'a, '_, '_>,
1176        block: &mut ast::Block<'a>,
1177        token: TokenSpan<'a>,
1178        expected_token: ExpectedToken<'a>,
1179    ) -> Result<'a, ()> {
1180        let local_decl = match token {
1181            (Token::Word("let"), _) => {
1182                let (name, given_ty) = self.optionally_typed_ident(lexer, ctx)?;
1183
1184                lexer.expect(Token::Operation('='))?;
1185                let expr_id = self.expression(lexer, ctx)?;
1186
1187                let handle = ctx.declare_local(name)?;
1188                ast::LocalDecl::Let(ast::Let {
1189                    name,
1190                    ty: given_ty,
1191                    init: expr_id,
1192                    handle,
1193                })
1194            }
1195            (Token::Word("const"), _) => {
1196                let (name, given_ty) = self.optionally_typed_ident(lexer, ctx)?;
1197
1198                lexer.expect(Token::Operation('='))?;
1199                let expr_id = self.expression(lexer, ctx)?;
1200
1201                let handle = ctx.declare_local(name)?;
1202                ast::LocalDecl::Const(ast::LocalConst {
1203                    name,
1204                    ty: given_ty,
1205                    init: expr_id,
1206                    handle,
1207                })
1208            }
1209            (Token::Word("var"), _) => {
1210                if lexer.next_if(Token::TemplateArgsStart) {
1211                    let (class_str, span) = lexer.next_ident_with_span()?;
1212                    if class_str != "function" {
1213                        return Err(Box::new(Error::InvalidLocalVariableAddressSpace(span)));
1214                    }
1215                    lexer.expect(Token::TemplateArgsEnd)?;
1216                }
1217
1218                let (name, ty) = self.optionally_typed_ident(lexer, ctx)?;
1219
1220                let init = if lexer.next_if(Token::Operation('=')) {
1221                    let init = self.expression(lexer, ctx)?;
1222                    Some(init)
1223                } else {
1224                    None
1225                };
1226
1227                let handle = ctx.declare_local(name)?;
1228                ast::LocalDecl::Var(ast::LocalVariable {
1229                    name,
1230                    ty,
1231                    init,
1232                    handle,
1233                })
1234            }
1235            token => {
1236                return self.func_call_or_variable_updating_statement(
1237                    lexer,
1238                    ctx,
1239                    block,
1240                    token,
1241                    expected_token,
1242                );
1243            }
1244        };
1245
1246        let span = lexer.span_with_start(token.1);
1247        block.stmts.push(ast::Statement {
1248            kind: ast::StatementKind::LocalDecl(local_decl),
1249            span,
1250        });
1251
1252        Ok(())
1253    }
1254
1255    fn statement<'a>(
1256        &mut self,
1257        lexer: &mut Lexer<'a>,
1258        ctx: &mut ExpressionContext<'a, '_, '_>,
1259        block: &mut ast::Block<'a>,
1260        brace_nesting_level: u8,
1261    ) -> Result<'a, ()> {
1262        self.track_recursion(|this| {
1263            this.push_rule_span(Rule::Statement, lexer);
1264
1265            // We peek here instead of eagerly getting the next token since
1266            // `Parser::block` expects its first token to be `{`.
1267            //
1268            // Most callers have a single path leading to the start of the block;
1269            // `statement` is the only exception where there are multiple choices.
1270            match lexer.peek() {
1271                (token, _) if is_start_of_compound_statement(token) => {
1272                    let (inner, span) = this.block(lexer, ctx, brace_nesting_level)?;
1273                    block.stmts.push(ast::Statement {
1274                        kind: ast::StatementKind::Block(inner),
1275                        span,
1276                    });
1277                    this.pop_rule_span(lexer);
1278                    return Ok(());
1279                }
1280                _ => {}
1281            }
1282
1283            let kind = match lexer.next() {
1284                (Token::Separator(';'), _) => {
1285                    this.pop_rule_span(lexer);
1286                    return Ok(());
1287                }
1288                (Token::Word("return"), _) => {
1289                    let value = if lexer.peek().0 != Token::Separator(';') {
1290                        let handle = this.expression(lexer, ctx)?;
1291                        Some(handle)
1292                    } else {
1293                        None
1294                    };
1295                    lexer.expect(Token::Separator(';'))?;
1296                    ast::StatementKind::Return { value }
1297                }
1298                (Token::Word("if"), _) => {
1299                    let condition = this.expression(lexer, ctx)?;
1300
1301                    let accept = this.block(lexer, ctx, brace_nesting_level)?.0;
1302
1303                    let mut elsif_stack = Vec::new();
1304                    let mut elseif_span_start = lexer.start_byte_offset();
1305                    let mut reject = loop {
1306                        if !lexer.next_if(Token::Word("else")) {
1307                            break ast::Block::default();
1308                        }
1309
1310                        if !lexer.next_if(Token::Word("if")) {
1311                            // ... else { ... }
1312                            break this.block(lexer, ctx, brace_nesting_level)?.0;
1313                        }
1314
1315                        // ... else if (...) { ... }
1316                        let other_condition = this.expression(lexer, ctx)?;
1317                        let other_block = this.block(lexer, ctx, brace_nesting_level)?;
1318                        elsif_stack.push((elseif_span_start, other_condition, other_block));
1319                        elseif_span_start = lexer.start_byte_offset();
1320                    };
1321
1322                    // reverse-fold the else-if blocks
1323                    //Note: we may consider uplifting this to the IR
1324                    for (other_span_start, other_cond, other_block) in elsif_stack.into_iter().rev()
1325                    {
1326                        let sub_stmt = ast::StatementKind::If {
1327                            condition: other_cond,
1328                            accept: other_block.0,
1329                            reject,
1330                        };
1331                        reject = ast::Block::default();
1332                        let span = lexer.span_from(other_span_start);
1333                        reject.stmts.push(ast::Statement {
1334                            kind: sub_stmt,
1335                            span,
1336                        })
1337                    }
1338
1339                    ast::StatementKind::If {
1340                        condition,
1341                        accept,
1342                        reject,
1343                    }
1344                }
1345                (Token::Word("switch"), _) => {
1346                    let selector = this.expression(lexer, ctx)?;
1347                    let brace_span = lexer.expect_span(Token::Paren('{'))?;
1348                    let brace_nesting_level =
1349                        Self::increase_brace_nesting(brace_nesting_level, brace_span)?;
1350                    let mut cases = Vec::new();
1351
1352                    loop {
1353                        // cases + default
1354                        match lexer.next() {
1355                            (Token::Word("case"), _) => {
1356                                // parse a list of values
1357                                let value = loop {
1358                                    let value = this.switch_value(lexer, ctx)?;
1359                                    if lexer.next_if(Token::Separator(',')) {
1360                                        // list of values ends with ':' or a compound statement
1361                                        let next_token = lexer.peek().0;
1362                                        if next_token == Token::Separator(':')
1363                                            || is_start_of_compound_statement(next_token)
1364                                        {
1365                                            break value;
1366                                        }
1367                                    } else {
1368                                        break value;
1369                                    }
1370                                    cases.push(ast::SwitchCase {
1371                                        value,
1372                                        body: ast::Block::default(),
1373                                        fall_through: true,
1374                                    });
1375                                };
1376
1377                                lexer.next_if(Token::Separator(':'));
1378
1379                                let body = this.block(lexer, ctx, brace_nesting_level)?.0;
1380
1381                                cases.push(ast::SwitchCase {
1382                                    value,
1383                                    body,
1384                                    fall_through: false,
1385                                });
1386                            }
1387                            (Token::Word("default"), _) => {
1388                                lexer.next_if(Token::Separator(':'));
1389                                let body = this.block(lexer, ctx, brace_nesting_level)?.0;
1390                                cases.push(ast::SwitchCase {
1391                                    value: ast::SwitchValue::Default,
1392                                    body,
1393                                    fall_through: false,
1394                                });
1395                            }
1396                            (Token::Paren('}'), _) => break,
1397                            (_, span) => {
1398                                return Err(Box::new(Error::Unexpected(
1399                                    span,
1400                                    ExpectedToken::SwitchItem,
1401                                )))
1402                            }
1403                        }
1404                    }
1405
1406                    ast::StatementKind::Switch { selector, cases }
1407                }
1408                (Token::Word("loop"), _) => this.r#loop(lexer, ctx, brace_nesting_level)?,
1409                (Token::Word("while"), _) => {
1410                    let mut body = ast::Block::default();
1411
1412                    let (condition, span) =
1413                        lexer.capture_span(|lexer| this.expression(lexer, ctx))?;
1414                    let mut reject = ast::Block::default();
1415                    reject.stmts.push(ast::Statement {
1416                        kind: ast::StatementKind::Break,
1417                        span,
1418                    });
1419
1420                    body.stmts.push(ast::Statement {
1421                        kind: ast::StatementKind::If {
1422                            condition,
1423                            accept: ast::Block::default(),
1424                            reject,
1425                        },
1426                        span,
1427                    });
1428
1429                    let (block, span) = this.block(lexer, ctx, brace_nesting_level)?;
1430                    body.stmts.push(ast::Statement {
1431                        kind: ast::StatementKind::Block(block),
1432                        span,
1433                    });
1434
1435                    ast::StatementKind::Loop {
1436                        body,
1437                        continuing: ast::Block::default(),
1438                        break_if: None,
1439                    }
1440                }
1441                (Token::Word("for"), _) => {
1442                    lexer.expect(Token::Paren('('))?;
1443
1444                    ctx.local_table.push_scope();
1445
1446                    if !lexer.next_if(Token::Separator(';')) {
1447                        let token = lexer.next();
1448                        this.variable_or_value_or_func_call_or_variable_updating_statement(
1449                            lexer,
1450                            ctx,
1451                            block,
1452                            token,
1453                            ExpectedToken::ForInit,
1454                        )?;
1455                        lexer.expect(Token::Separator(';'))?;
1456                    };
1457
1458                    let mut body = ast::Block::default();
1459                    if !lexer.next_if(Token::Separator(';')) {
1460                        let (condition, span) = lexer.capture_span(|lexer| -> Result<'_, _> {
1461                            let condition = this.expression(lexer, ctx)?;
1462                            lexer.expect(Token::Separator(';'))?;
1463                            Ok(condition)
1464                        })?;
1465                        let mut reject = ast::Block::default();
1466                        reject.stmts.push(ast::Statement {
1467                            kind: ast::StatementKind::Break,
1468                            span,
1469                        });
1470                        body.stmts.push(ast::Statement {
1471                            kind: ast::StatementKind::If {
1472                                condition,
1473                                accept: ast::Block::default(),
1474                                reject,
1475                            },
1476                            span,
1477                        });
1478                    };
1479
1480                    let mut continuing = ast::Block::default();
1481                    if !lexer.next_if(Token::Paren(')')) {
1482                        let token = lexer.next();
1483                        this.func_call_or_variable_updating_statement(
1484                            lexer,
1485                            ctx,
1486                            &mut continuing,
1487                            token,
1488                            ExpectedToken::ForUpdate,
1489                        )?;
1490                        lexer.expect(Token::Paren(')'))?;
1491                    }
1492
1493                    let (block, span) = this.block(lexer, ctx, brace_nesting_level)?;
1494                    body.stmts.push(ast::Statement {
1495                        kind: ast::StatementKind::Block(block),
1496                        span,
1497                    });
1498
1499                    ctx.local_table.pop_scope();
1500
1501                    ast::StatementKind::Loop {
1502                        body,
1503                        continuing,
1504                        break_if: None,
1505                    }
1506                }
1507                (Token::Word("break"), span) => {
1508                    // Check if the next token is an `if`, this indicates
1509                    // that the user tried to type out a `break if` which
1510                    // is illegal in this position.
1511                    let (peeked_token, peeked_span) = lexer.peek();
1512                    if let Token::Word("if") = peeked_token {
1513                        let span = span.until(&peeked_span);
1514                        return Err(Box::new(Error::InvalidBreakIf(span)));
1515                    }
1516                    lexer.expect(Token::Separator(';'))?;
1517                    ast::StatementKind::Break
1518                }
1519                (Token::Word("continue"), _) => {
1520                    lexer.expect(Token::Separator(';'))?;
1521                    ast::StatementKind::Continue
1522                }
1523                (Token::Word("discard"), _) => {
1524                    lexer.expect(Token::Separator(';'))?;
1525                    ast::StatementKind::Kill
1526                }
1527                // https://www.w3.org/TR/WGSL/#const-assert-statement
1528                (Token::Word("const_assert"), _) => {
1529                    // parentheses are optional
1530                    let paren = lexer.next_if(Token::Paren('('));
1531
1532                    let condition = this.expression(lexer, ctx)?;
1533
1534                    if paren {
1535                        lexer.expect(Token::Paren(')'))?;
1536                    }
1537                    lexer.expect(Token::Separator(';'))?;
1538                    ast::StatementKind::ConstAssert(condition)
1539                }
1540                token => {
1541                    this.variable_or_value_or_func_call_or_variable_updating_statement(
1542                        lexer,
1543                        ctx,
1544                        block,
1545                        token,
1546                        ExpectedToken::Statement,
1547                    )?;
1548                    lexer.expect(Token::Separator(';'))?;
1549                    this.pop_rule_span(lexer);
1550                    return Ok(());
1551                }
1552            };
1553
1554            let span = this.pop_rule_span(lexer);
1555            block.stmts.push(ast::Statement { kind, span });
1556
1557            Ok(())
1558        })
1559    }
1560
1561    fn r#loop<'a>(
1562        &mut self,
1563        lexer: &mut Lexer<'a>,
1564        ctx: &mut ExpressionContext<'a, '_, '_>,
1565        brace_nesting_level: u8,
1566    ) -> Result<'a, ast::StatementKind<'a>> {
1567        let mut body = ast::Block::default();
1568        let mut continuing = ast::Block::default();
1569        let mut break_if = None;
1570
1571        let brace_span = lexer.expect_span(Token::Paren('{'))?;
1572        let brace_nesting_level = Self::increase_brace_nesting(brace_nesting_level, brace_span)?;
1573
1574        ctx.local_table.push_scope();
1575
1576        loop {
1577            if lexer.next_if(Token::Word("continuing")) {
1578                // Branch for the `continuing` block, this must be
1579                // the last thing in the loop body
1580
1581                // Expect a opening brace to start the continuing block
1582                let brace_span = lexer.expect_span(Token::Paren('{'))?;
1583                let brace_nesting_level =
1584                    Self::increase_brace_nesting(brace_nesting_level, brace_span)?;
1585                loop {
1586                    if lexer.next_if(Token::Word("break")) {
1587                        // Branch for the `break if` statement, this statement
1588                        // has the form `break if <expr>;` and must be the last
1589                        // statement in a continuing block
1590
1591                        // The break must be followed by an `if` to form
1592                        // the break if
1593                        lexer.expect(Token::Word("if"))?;
1594
1595                        let condition = self.expression(lexer, ctx)?;
1596                        // Set the condition of the break if to the newly parsed
1597                        // expression
1598                        break_if = Some(condition);
1599
1600                        // Expect a semicolon to close the statement
1601                        lexer.expect(Token::Separator(';'))?;
1602                        // Expect a closing brace to close the continuing block,
1603                        // since the break if must be the last statement
1604                        lexer.expect(Token::Paren('}'))?;
1605                        // Stop parsing the continuing block
1606                        break;
1607                    } else if lexer.next_if(Token::Paren('}')) {
1608                        // If we encounter a closing brace it means we have reached
1609                        // the end of the continuing block and should stop processing
1610                        break;
1611                    } else {
1612                        // Otherwise try to parse a statement
1613                        self.statement(lexer, ctx, &mut continuing, brace_nesting_level)?;
1614                    }
1615                }
1616                // Since the continuing block must be the last part of the loop body,
1617                // we expect to see a closing brace to end the loop body
1618                lexer.expect(Token::Paren('}'))?;
1619                break;
1620            }
1621            if lexer.next_if(Token::Paren('}')) {
1622                // If we encounter a closing brace it means we have reached
1623                // the end of the loop body and should stop processing
1624                break;
1625            }
1626            // Otherwise try to parse a statement
1627            self.statement(lexer, ctx, &mut body, brace_nesting_level)?;
1628        }
1629
1630        ctx.local_table.pop_scope();
1631
1632        Ok(ast::StatementKind::Loop {
1633            body,
1634            continuing,
1635            break_if,
1636        })
1637    }
1638
1639    /// compound_statement
1640    fn block<'a>(
1641        &mut self,
1642        lexer: &mut Lexer<'a>,
1643        ctx: &mut ExpressionContext<'a, '_, '_>,
1644        brace_nesting_level: u8,
1645    ) -> Result<'a, (ast::Block<'a>, Span)> {
1646        self.push_rule_span(Rule::Block, lexer);
1647
1648        ctx.local_table.push_scope();
1649
1650        let mut diagnostic_filters = DiagnosticFilterMap::new();
1651
1652        self.push_rule_span(Rule::Attribute, lexer);
1653        while lexer.next_if(Token::Attribute) {
1654            let (name, name_span) = lexer.next_ident_with_span()?;
1655            if let Some(DirectiveKind::Diagnostic) = DirectiveKind::from_ident(name) {
1656                let filter = self.diagnostic_filter(lexer)?;
1657                let span = self.peek_rule_span(lexer);
1658                diagnostic_filters
1659                    .add(filter, span, ShouldConflictOnFullDuplicate::Yes)
1660                    .map_err(|e| Box::new(e.into()))?;
1661            } else {
1662                return Err(Box::new(Error::Unexpected(
1663                    name_span,
1664                    ExpectedToken::DiagnosticAttribute,
1665                )));
1666            }
1667        }
1668        self.pop_rule_span(lexer);
1669
1670        if !diagnostic_filters.is_empty() {
1671            return Err(Box::new(
1672                Error::DiagnosticAttributeNotYetImplementedAtParseSite {
1673                    site_name_plural: "compound statements",
1674                    spans: diagnostic_filters.spans().collect(),
1675                },
1676            ));
1677        }
1678
1679        let brace_span = lexer.expect_span(Token::Paren('{'))?;
1680        let brace_nesting_level = Self::increase_brace_nesting(brace_nesting_level, brace_span)?;
1681        let mut block = ast::Block::default();
1682        while !lexer.next_if(Token::Paren('}')) {
1683            self.statement(lexer, ctx, &mut block, brace_nesting_level)?;
1684        }
1685
1686        ctx.local_table.pop_scope();
1687
1688        let span = self.pop_rule_span(lexer);
1689        Ok((block, span))
1690    }
1691
1692    fn varying_binding<'a>(
1693        &mut self,
1694        lexer: &mut Lexer<'a>,
1695        ctx: &mut ExpressionContext<'a, '_, '_>,
1696    ) -> Result<'a, Option<ast::Binding<'a>>> {
1697        let mut bind_parser = BindingParser::default();
1698        self.push_rule_span(Rule::Attribute, lexer);
1699
1700        while lexer.next_if(Token::Attribute) {
1701            let (word, span) = lexer.next_ident_with_span()?;
1702            bind_parser.parse(self, lexer, word, span, ctx)?;
1703        }
1704
1705        let span = self.pop_rule_span(lexer);
1706        bind_parser.finish(span)
1707    }
1708
1709    fn function_decl<'a>(
1710        &mut self,
1711        lexer: &mut Lexer<'a>,
1712        diagnostic_filter_leaf: Option<Handle<DiagnosticFilterNode>>,
1713        must_use: Option<Span>,
1714        out: &mut ast::TranslationUnit<'a>,
1715        dependencies: &mut FastIndexSet<ast::Dependency<'a>>,
1716    ) -> Result<'a, ast::Function<'a>> {
1717        self.push_rule_span(Rule::FunctionDecl, lexer);
1718        // read function name
1719        let fun_name = lexer.next_ident()?;
1720
1721        let mut locals = Arena::new();
1722
1723        let mut ctx = ExpressionContext {
1724            expressions: &mut out.expressions,
1725            local_table: &mut SymbolTable::default(),
1726            locals: &mut locals,
1727            unresolved: dependencies,
1728        };
1729
1730        // start a scope that contains arguments as well as the function body
1731        ctx.local_table.push_scope();
1732        // Reduce lookup scope to parse the parameter list and return type
1733        // avoiding identifier lookup to match newly declared param names.
1734        ctx.local_table.reduce_lookup_scope();
1735
1736        // read parameter list
1737        let mut arguments = Vec::new();
1738        lexer.expect(Token::Paren('('))?;
1739        let mut ready = true;
1740        while !lexer.next_if(Token::Paren(')')) {
1741            if !ready {
1742                return Err(Box::new(Error::Unexpected(
1743                    lexer.next().1,
1744                    ExpectedToken::Token(Token::Separator(',')),
1745                )));
1746            }
1747            let binding = self.varying_binding(lexer, &mut ctx)?;
1748
1749            let param_name = lexer.next_ident()?;
1750
1751            lexer.expect(Token::Separator(':'))?;
1752            let param_type = self.type_specifier(lexer, &mut ctx)?;
1753
1754            let handle = ctx.declare_local(param_name)?;
1755            arguments.push(ast::FunctionArgument {
1756                name: param_name,
1757                ty: param_type,
1758                binding,
1759                handle,
1760            });
1761            ready = lexer.next_if(Token::Separator(','));
1762        }
1763        // read return type
1764        let result = if lexer.next_if(Token::Arrow) {
1765            let binding = self.varying_binding(lexer, &mut ctx)?;
1766            let ty = self.type_specifier(lexer, &mut ctx)?;
1767            let must_use = must_use.is_some();
1768            Some(ast::FunctionResult {
1769                ty,
1770                binding,
1771                must_use,
1772            })
1773        } else if let Some(must_use) = must_use {
1774            return Err(Box::new(Error::FunctionMustUseReturnsVoid(
1775                must_use,
1776                self.peek_rule_span(lexer),
1777            )));
1778        } else {
1779            None
1780        };
1781
1782        ctx.local_table.reset_lookup_scope();
1783
1784        // do not use `self.block` here, since we must not push a new scope
1785        lexer.expect(Token::Paren('{'))?;
1786        let brace_nesting_level = 1;
1787        let mut body = ast::Block::default();
1788        while !lexer.next_if(Token::Paren('}')) {
1789            self.statement(lexer, &mut ctx, &mut body, brace_nesting_level)?;
1790        }
1791
1792        ctx.local_table.pop_scope();
1793
1794        let fun = ast::Function {
1795            entry_point: None,
1796            name: fun_name,
1797            arguments,
1798            result,
1799            body,
1800            diagnostic_filter_leaf,
1801            doc_comments: Vec::new(),
1802        };
1803
1804        // done
1805        self.pop_rule_span(lexer);
1806
1807        Ok(fun)
1808    }
1809
1810    fn directive_ident_list<'a>(
1811        &self,
1812        lexer: &mut Lexer<'a>,
1813        handler: impl FnMut(&'a str, Span) -> Result<'a, ()>,
1814    ) -> Result<'a, ()> {
1815        let mut handler = handler;
1816        'next_arg: loop {
1817            let (ident, span) = lexer.next_ident_with_span()?;
1818            handler(ident, span)?;
1819
1820            let expected_token = match lexer.peek().0 {
1821                Token::Separator(',') => {
1822                    let _ = lexer.next();
1823                    if matches!(lexer.peek().0, Token::Word(..)) {
1824                        continue 'next_arg;
1825                    }
1826                    ExpectedToken::AfterIdentListComma
1827                }
1828                _ => ExpectedToken::AfterIdentListArg,
1829            };
1830
1831            if !matches!(lexer.next().0, Token::Separator(';')) {
1832                return Err(Box::new(Error::Unexpected(span, expected_token)));
1833            }
1834
1835            break Ok(());
1836        }
1837    }
1838
1839    fn global_decl<'a>(
1840        &mut self,
1841        lexer: &mut Lexer<'a>,
1842        out: &mut ast::TranslationUnit<'a>,
1843    ) -> Result<'a, ()> {
1844        let doc_comments = lexer.accumulate_doc_comments();
1845
1846        // read attributes
1847        let mut binding = None;
1848        let mut stage = ParsedAttribute::default();
1849        // Span in case we need to report an error for a shader stage missing something (e.g. its workgroup size).
1850        // Doesn't need to be set in the vertex and fragment stages because they don't have errors like that.
1851        let mut shader_stage_error_span = Span::new(0, 0);
1852        let mut workgroup_size = ParsedAttribute::default();
1853        let mut early_depth_test = ParsedAttribute::default();
1854        let (mut bind_index, mut bind_group) =
1855            (ParsedAttribute::default(), ParsedAttribute::default());
1856        let mut id = ParsedAttribute::default();
1857        // the payload variable for a mesh shader
1858        let mut payload = ParsedAttribute::default();
1859        // the incoming payload from a traceRay call
1860        let mut incoming_payload = ParsedAttribute::default();
1861        let mut mesh_output = ParsedAttribute::default();
1862
1863        let mut must_use: ParsedAttribute<Span> = ParsedAttribute::default();
1864        let mut memory_decorations = crate::MemoryDecorations::empty();
1865
1866        let mut dependencies = FastIndexSet::default();
1867        let mut ctx = ExpressionContext {
1868            expressions: &mut out.expressions,
1869            local_table: &mut SymbolTable::default(),
1870            locals: &mut Arena::new(),
1871            unresolved: &mut dependencies,
1872        };
1873        let mut diagnostic_filters = DiagnosticFilterMap::new();
1874        let ensure_no_diag_attrs = |on_what, filters: DiagnosticFilterMap| -> Result<()> {
1875            if filters.is_empty() {
1876                Ok(())
1877            } else {
1878                Err(Box::new(Error::DiagnosticAttributeNotSupported {
1879                    on_what,
1880                    spans: filters.spans().collect(),
1881                }))
1882            }
1883        };
1884
1885        self.push_rule_span(Rule::Attribute, lexer);
1886        while lexer.next_if(Token::Attribute) {
1887            let (name, name_span) = lexer.next_ident_with_span()?;
1888            if let Some(DirectiveKind::Diagnostic) = DirectiveKind::from_ident(name) {
1889                let filter = self.diagnostic_filter(lexer)?;
1890                let span = self.peek_rule_span(lexer);
1891                diagnostic_filters
1892                    .add(filter, span, ShouldConflictOnFullDuplicate::Yes)
1893                    .map_err(|e| Box::new(e.into()))?;
1894                continue;
1895            }
1896            match name {
1897                "binding" => {
1898                    lexer.expect(Token::Paren('('))?;
1899                    bind_index.set(self.expression(lexer, &mut ctx)?, name_span)?;
1900                    lexer.next_if(Token::Separator(','));
1901                    lexer.expect(Token::Paren(')'))?;
1902                }
1903                "group" => {
1904                    lexer.expect(Token::Paren('('))?;
1905                    bind_group.set(self.expression(lexer, &mut ctx)?, name_span)?;
1906                    lexer.next_if(Token::Separator(','));
1907                    lexer.expect(Token::Paren(')'))?;
1908                }
1909                "id" => {
1910                    lexer.expect(Token::Paren('('))?;
1911                    id.set(self.expression(lexer, &mut ctx)?, name_span)?;
1912                    lexer.next_if(Token::Separator(','));
1913                    lexer.expect(Token::Paren(')'))?;
1914                }
1915                "vertex" => {
1916                    stage.set(ShaderStage::Vertex, name_span)?;
1917                }
1918                "fragment" => {
1919                    stage.set(ShaderStage::Fragment, name_span)?;
1920                }
1921                "compute" => {
1922                    stage.set(ShaderStage::Compute, name_span)?;
1923                    shader_stage_error_span = name_span;
1924                }
1925                "task" => {
1926                    lexer.require_enable_extension(
1927                        ImplementedEnableExtension::WgpuMeshShader,
1928                        name_span,
1929                    )?;
1930                    stage.set(ShaderStage::Task, name_span)?;
1931                    shader_stage_error_span = name_span;
1932                }
1933                "mesh" => {
1934                    lexer.require_enable_extension(
1935                        ImplementedEnableExtension::WgpuMeshShader,
1936                        name_span,
1937                    )?;
1938                    stage.set(ShaderStage::Mesh, name_span)?;
1939                    shader_stage_error_span = name_span;
1940
1941                    lexer.expect(Token::Paren('('))?;
1942                    mesh_output.set(lexer.next_ident_with_span()?, name_span)?;
1943                    lexer.expect(Token::Paren(')'))?;
1944                }
1945                "ray_generation" => {
1946                    lexer.require_enable_extension(
1947                        ImplementedEnableExtension::WgpuRayTracingPipeline,
1948                        name_span,
1949                    )?;
1950                    stage.set(ShaderStage::RayGeneration, name_span)?;
1951                    shader_stage_error_span = name_span;
1952                }
1953                "any_hit" => {
1954                    lexer.require_enable_extension(
1955                        ImplementedEnableExtension::WgpuRayTracingPipeline,
1956                        name_span,
1957                    )?;
1958                    stage.set(ShaderStage::AnyHit, name_span)?;
1959                    shader_stage_error_span = name_span;
1960                }
1961                "closest_hit" => {
1962                    lexer.require_enable_extension(
1963                        ImplementedEnableExtension::WgpuRayTracingPipeline,
1964                        name_span,
1965                    )?;
1966                    stage.set(ShaderStage::ClosestHit, name_span)?;
1967                    shader_stage_error_span = name_span;
1968                }
1969                "miss" => {
1970                    lexer.require_enable_extension(
1971                        ImplementedEnableExtension::WgpuRayTracingPipeline,
1972                        name_span,
1973                    )?;
1974                    stage.set(ShaderStage::Miss, name_span)?;
1975                    shader_stage_error_span = name_span;
1976                }
1977                "payload" => {
1978                    lexer.require_enable_extension(
1979                        ImplementedEnableExtension::WgpuMeshShader,
1980                        name_span,
1981                    )?;
1982                    lexer.expect(Token::Paren('('))?;
1983                    payload.set(lexer.next_ident_with_span()?, name_span)?;
1984                    lexer.expect(Token::Paren(')'))?;
1985                }
1986                "incoming_payload" => {
1987                    lexer.require_enable_extension(
1988                        ImplementedEnableExtension::WgpuRayTracingPipeline,
1989                        name_span,
1990                    )?;
1991                    lexer.expect(Token::Paren('('))?;
1992                    incoming_payload.set(lexer.next_ident_with_span()?, name_span)?;
1993                    lexer.expect(Token::Paren(')'))?;
1994                }
1995                "workgroup_size" => {
1996                    lexer.expect(Token::Paren('('))?;
1997                    let mut new_workgroup_size = [None; 3];
1998                    for size in new_workgroup_size.iter_mut() {
1999                        *size = Some(self.expression(lexer, &mut ctx)?);
2000                        match lexer.next() {
2001                            (Token::Paren(')'), _) => break,
2002                            (Token::Separator(','), _) => {
2003                                if lexer.next_if(Token::Paren(')')) {
2004                                    break;
2005                                }
2006                            }
2007                            other => {
2008                                return Err(Box::new(Error::Unexpected(
2009                                    other.1,
2010                                    ExpectedToken::WorkgroupSizeSeparator,
2011                                )))
2012                            }
2013                        }
2014                    }
2015                    workgroup_size.set(new_workgroup_size, name_span)?;
2016                }
2017                "early_depth_test" => {
2018                    lexer.expect(Token::Paren('('))?;
2019                    let (ident, ident_span) = lexer.next_ident_with_span()?;
2020                    let value = if ident == "force" {
2021                        crate::EarlyDepthTest::Force
2022                    } else {
2023                        crate::EarlyDepthTest::Allow {
2024                            conservative: conv::map_conservative_depth(ident, ident_span)?,
2025                        }
2026                    };
2027                    lexer.expect(Token::Paren(')'))?;
2028                    early_depth_test.set(value, name_span)?;
2029                }
2030                "must_use" => {
2031                    must_use.set(name_span, name_span)?;
2032                }
2033                "coherent" => {
2034                    memory_decorations |= crate::MemoryDecorations::COHERENT;
2035                }
2036                "volatile" => {
2037                    memory_decorations |= crate::MemoryDecorations::VOLATILE;
2038                }
2039                _ => return Err(Box::new(Error::UnknownAttribute(name_span))),
2040            }
2041        }
2042
2043        let attrib_span = self.pop_rule_span(lexer);
2044        match (bind_group.value, bind_index.value) {
2045            (Some(group), Some(index)) => {
2046                binding = Some(ast::ResourceBinding {
2047                    group,
2048                    binding: index,
2049                });
2050            }
2051            (Some(_), None) => {
2052                return Err(Box::new(Error::MissingAttribute("binding", attrib_span)))
2053            }
2054            (None, Some(_)) => return Err(Box::new(Error::MissingAttribute("group", attrib_span))),
2055            (None, None) => {}
2056        }
2057
2058        // read item
2059        let start = lexer.start_byte_offset();
2060        let kind = match lexer.next() {
2061            (Token::Separator(';'), _) => {
2062                ensure_no_diag_attrs(
2063                    DiagnosticAttributeNotSupportedPosition::SemicolonInModulePosition,
2064                    diagnostic_filters,
2065                )?;
2066                None
2067            }
2068            (Token::Word(word), directive_span) if DirectiveKind::from_ident(word).is_some() => {
2069                return Err(Box::new(Error::DirectiveAfterFirstGlobalDecl {
2070                    directive_span,
2071                }));
2072            }
2073            (Token::Word("struct"), _) => {
2074                ensure_no_diag_attrs("`struct`s".into(), diagnostic_filters)?;
2075
2076                let name = lexer.next_ident()?;
2077
2078                let members = self.struct_body(lexer, &mut ctx)?;
2079
2080                Some(ast::GlobalDeclKind::Struct(ast::Struct {
2081                    name,
2082                    members,
2083                    doc_comments,
2084                }))
2085            }
2086            (Token::Word("alias"), _) => {
2087                ensure_no_diag_attrs("`alias`es".into(), diagnostic_filters)?;
2088
2089                let name = lexer.next_ident()?;
2090
2091                lexer.expect(Token::Operation('='))?;
2092                let ty = self.type_specifier(lexer, &mut ctx)?;
2093                lexer.expect(Token::Separator(';'))?;
2094                Some(ast::GlobalDeclKind::Type(ast::TypeAlias { name, ty }))
2095            }
2096            (Token::Word("const"), _) => {
2097                ensure_no_diag_attrs("`const`s".into(), diagnostic_filters)?;
2098
2099                let (name, ty) = self.optionally_typed_ident(lexer, &mut ctx)?;
2100
2101                lexer.expect(Token::Operation('='))?;
2102                let init = self.expression(lexer, &mut ctx)?;
2103                lexer.expect(Token::Separator(';'))?;
2104
2105                Some(ast::GlobalDeclKind::Const(ast::Const {
2106                    name,
2107                    ty,
2108                    init,
2109                    doc_comments,
2110                }))
2111            }
2112            (Token::Word("override"), _) => {
2113                ensure_no_diag_attrs("`override`s".into(), diagnostic_filters)?;
2114
2115                let (name, ty) = self.optionally_typed_ident(lexer, &mut ctx)?;
2116
2117                let init = if lexer.next_if(Token::Operation('=')) {
2118                    Some(self.expression(lexer, &mut ctx)?)
2119                } else {
2120                    None
2121                };
2122
2123                lexer.expect(Token::Separator(';'))?;
2124
2125                Some(ast::GlobalDeclKind::Override(ast::Override {
2126                    name,
2127                    id: id.value,
2128                    ty,
2129                    init,
2130                }))
2131            }
2132            (Token::Word("var"), _) => {
2133                ensure_no_diag_attrs("`var`s".into(), diagnostic_filters)?;
2134
2135                let mut var = self.variable_decl(lexer, &mut ctx)?;
2136                var.binding = binding.take();
2137                var.doc_comments = doc_comments;
2138                var.memory_decorations = memory_decorations;
2139                Some(ast::GlobalDeclKind::Var(var))
2140            }
2141            (Token::Word("fn"), _) => {
2142                let diagnostic_filter_leaf = Self::write_diagnostic_filters(
2143                    &mut out.diagnostic_filters,
2144                    diagnostic_filters,
2145                    out.diagnostic_filter_leaf,
2146                );
2147
2148                let function = self.function_decl(
2149                    lexer,
2150                    diagnostic_filter_leaf,
2151                    must_use.value,
2152                    out,
2153                    &mut dependencies,
2154                )?;
2155                Some(ast::GlobalDeclKind::Fn(ast::Function {
2156                    entry_point: if let Some(stage) = stage.value {
2157                        if stage.compute_like() && workgroup_size.value.is_none() {
2158                            return Err(Box::new(Error::MissingWorkgroupSize(
2159                                shader_stage_error_span,
2160                            )));
2161                        }
2162
2163                        match stage {
2164                            ShaderStage::AnyHit | ShaderStage::ClosestHit | ShaderStage::Miss
2165                                if incoming_payload.value.is_none() =>
2166                            {
2167                                return Err(Box::new(Error::MissingIncomingPayload(
2168                                    shader_stage_error_span,
2169                                )));
2170                            }
2171                            _ => {}
2172                        }
2173
2174                        Some(ast::EntryPoint {
2175                            stage,
2176                            early_depth_test: early_depth_test.value,
2177                            workgroup_size: workgroup_size.value,
2178                            mesh_output_variable: mesh_output.value,
2179                            task_payload: payload.value,
2180                            ray_incoming_payload: incoming_payload.value,
2181                        })
2182                    } else {
2183                        None
2184                    },
2185                    doc_comments,
2186                    ..function
2187                }))
2188            }
2189            (Token::Word("const_assert"), _) => {
2190                ensure_no_diag_attrs("`const_assert`s".into(), diagnostic_filters)?;
2191
2192                // parentheses are optional
2193                let paren = lexer.next_if(Token::Paren('('));
2194
2195                let condition = self.expression(lexer, &mut ctx)?;
2196
2197                if paren {
2198                    lexer.expect(Token::Paren(')'))?;
2199                }
2200                lexer.expect(Token::Separator(';'))?;
2201                Some(ast::GlobalDeclKind::ConstAssert(condition))
2202            }
2203            (Token::End, _) => return Ok(()),
2204            (Token::UnterminatedBlockComment(_), span) => {
2205                return Err(Box::new(Error::UnterminatedBlockComment(span)))
2206            }
2207            other => {
2208                return Err(Box::new(Error::Unexpected(
2209                    other.1,
2210                    ExpectedToken::GlobalItem,
2211                )))
2212            }
2213        };
2214
2215        if let Some(must_use_span) = must_use.value {
2216            if !matches!(kind.as_ref(), Some(ast::GlobalDeclKind::Fn(_))) {
2217                return Err(Box::new(Error::FunctionMustUseOnNonFunction(must_use_span)));
2218            }
2219        }
2220
2221        if let Some(kind) = kind {
2222            out.decls.append(
2223                ast::GlobalDecl { kind, dependencies },
2224                lexer.span_from(start),
2225            );
2226        }
2227
2228        if !self.rules.is_empty() {
2229            log::error!("Reached the end of global decl, but rule stack is not empty");
2230            log::error!("Rules: {:?}", self.rules);
2231            return Err(Box::new(Error::Internal("rule stack is not empty")));
2232        };
2233
2234        match binding {
2235            None => Ok(()),
2236            Some(_) => Err(Box::new(Error::Internal(
2237                "we had the attribute but no var?",
2238            ))),
2239        }
2240    }
2241
2242    pub fn parse<'a>(
2243        &mut self,
2244        source: &'a str,
2245        options: &Options,
2246    ) -> Result<'a, ast::TranslationUnit<'a>> {
2247        self.reset();
2248
2249        let mut lexer = Lexer::new(source, !options.parse_doc_comments);
2250        let mut tu = ast::TranslationUnit::default();
2251        let mut enable_extensions = EnableExtensions::empty();
2252        let mut diagnostic_filters = DiagnosticFilterMap::new();
2253
2254        // Parse module doc comments.
2255        tu.doc_comments = lexer.accumulate_module_doc_comments();
2256
2257        // Parse directives.
2258        while let (Token::Word(word), _) = lexer.peek() {
2259            if let Some(kind) = DirectiveKind::from_ident(word) {
2260                self.push_rule_span(Rule::Directive, &mut lexer);
2261                let _ = lexer.next_ident_with_span().unwrap();
2262                match kind {
2263                    DirectiveKind::Diagnostic => {
2264                        let diagnostic_filter = self.diagnostic_filter(&mut lexer)?;
2265                        let span = self.peek_rule_span(&lexer);
2266                        diagnostic_filters
2267                            .add(diagnostic_filter, span, ShouldConflictOnFullDuplicate::No)
2268                            .map_err(|e| Box::new(e.into()))?;
2269                        lexer.expect(Token::Separator(';'))?;
2270                    }
2271                    DirectiveKind::Enable => {
2272                        self.directive_ident_list(&mut lexer, |ident, span| {
2273                            let kind = EnableExtension::from_ident(ident, span)?;
2274                            let extension = match kind {
2275                                EnableExtension::Implemented(kind) => kind,
2276                                EnableExtension::Unimplemented(kind) => {
2277                                    return Err(Box::new(Error::EnableExtensionNotYetImplemented {
2278                                        kind,
2279                                        span,
2280                                    }))
2281                                }
2282                            };
2283                            // Check if the required capability is supported
2284                            let required_capability = extension.capability();
2285                            if !options.capabilities.intersects(required_capability) {
2286                                return Err(Box::new(Error::EnableExtensionNotSupported {
2287                                    kind,
2288                                    span,
2289                                }));
2290                            }
2291                            enable_extensions.add(extension);
2292                            Ok(())
2293                        })?;
2294                    }
2295                    DirectiveKind::Requires => {
2296                        self.directive_ident_list(&mut lexer, |ident, span| {
2297                            match LanguageExtension::from_ident(ident) {
2298                                Some(LanguageExtension::Implemented(_kind)) => {
2299                                    // NOTE: No further validation is needed for an extension, so
2300                                    // just throw parsed information away. If we ever want to apply
2301                                    // what we've parsed to diagnostics, maybe we'll want to refer
2302                                    // to enabled extensions later?
2303                                    Ok(())
2304                                }
2305                                Some(LanguageExtension::Unimplemented(kind)) => {
2306                                    Err(Box::new(Error::LanguageExtensionNotYetImplemented {
2307                                        kind,
2308                                        span,
2309                                    }))
2310                                }
2311                                None => Err(Box::new(Error::UnknownLanguageExtension(span, ident))),
2312                            }
2313                        })?;
2314                    }
2315                }
2316                self.pop_rule_span(&lexer);
2317            } else {
2318                break;
2319            }
2320        }
2321
2322        lexer.enable_extensions = enable_extensions;
2323        tu.enable_extensions = enable_extensions;
2324        tu.diagnostic_filter_leaf =
2325            Self::write_diagnostic_filters(&mut tu.diagnostic_filters, diagnostic_filters, None);
2326
2327        loop {
2328            match self.global_decl(&mut lexer, &mut tu) {
2329                Err(error) => return Err(error),
2330                Ok(()) => {
2331                    if lexer.peek().0 == Token::End {
2332                        break;
2333                    }
2334                }
2335            }
2336        }
2337
2338        Ok(tu)
2339    }
2340
2341    fn increase_brace_nesting(brace_nesting_level: u8, brace_span: Span) -> Result<'static, u8> {
2342        // From [spec.](https://gpuweb.github.io/gpuweb/wgsl/#limits):
2343        //
2344        // > § 2.4. Limits
2345        // >
2346        // > …
2347        // >
2348        // > Maximum nesting depth of brace-enclosed statements in a function[:] 127
2349        const BRACE_NESTING_MAXIMUM: u8 = 127;
2350        if brace_nesting_level + 1 > BRACE_NESTING_MAXIMUM {
2351            return Err(Box::new(Error::ExceededLimitForNestedBraces {
2352                span: brace_span,
2353                limit: BRACE_NESTING_MAXIMUM,
2354            }));
2355        }
2356        Ok(brace_nesting_level + 1)
2357    }
2358
2359    fn diagnostic_filter<'a>(&self, lexer: &mut Lexer<'a>) -> Result<'a, DiagnosticFilter> {
2360        lexer.expect(Token::Paren('('))?;
2361
2362        let (severity_control_name, severity_control_name_span) = lexer.next_ident_with_span()?;
2363        let new_severity = diagnostic_filter::Severity::from_wgsl_ident(severity_control_name)
2364            .ok_or(Error::DiagnosticInvalidSeverity {
2365                severity_control_name_span,
2366            })?;
2367
2368        lexer.expect(Token::Separator(','))?;
2369
2370        let (diagnostic_name_token, diagnostic_name_token_span) = lexer.next_ident_with_span()?;
2371        let triggering_rule = if lexer.next_if(Token::Separator('.')) {
2372            let (ident, _span) = lexer.next_ident_with_span()?;
2373            FilterableTriggeringRule::User(Box::new([diagnostic_name_token.into(), ident.into()]))
2374        } else {
2375            let diagnostic_rule_name = diagnostic_name_token;
2376            let diagnostic_rule_name_span = diagnostic_name_token_span;
2377            if let Some(triggering_rule) =
2378                StandardFilterableTriggeringRule::from_wgsl_ident(diagnostic_rule_name)
2379            {
2380                FilterableTriggeringRule::Standard(triggering_rule)
2381            } else {
2382                diagnostic_filter::Severity::Warning.report_wgsl_parse_diag(
2383                    Box::new(Error::UnknownDiagnosticRuleName(diagnostic_rule_name_span)),
2384                    lexer.source,
2385                )?;
2386                FilterableTriggeringRule::Unknown(diagnostic_rule_name.into())
2387            }
2388        };
2389        let filter = DiagnosticFilter {
2390            triggering_rule,
2391            new_severity,
2392        };
2393        lexer.next_if(Token::Separator(','));
2394        lexer.expect(Token::Paren(')'))?;
2395
2396        Ok(filter)
2397    }
2398
2399    pub(crate) fn write_diagnostic_filters(
2400        arena: &mut Arena<DiagnosticFilterNode>,
2401        filters: DiagnosticFilterMap,
2402        parent: Option<Handle<DiagnosticFilterNode>>,
2403    ) -> Option<Handle<DiagnosticFilterNode>> {
2404        filters
2405            .into_iter()
2406            .fold(parent, |parent, (triggering_rule, (new_severity, span))| {
2407                Some(arena.append(
2408                    DiagnosticFilterNode {
2409                        inner: DiagnosticFilter {
2410                            new_severity,
2411                            triggering_rule,
2412                        },
2413                        parent,
2414                    },
2415                    span,
2416                ))
2417            })
2418    }
2419}
2420
2421const fn is_start_of_compound_statement<'a>(token: Token<'a>) -> bool {
2422    matches!(token, Token::Attribute | Token::Paren('{'))
2423}