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::Word(word), span) => {
500                let ident = self.template_elaborated_ident(word, span, lexer, ctx)?;
501
502                if let Token::Paren('(') = lexer.peek().0 {
503                    let arguments = self.arguments(lexer, ctx)?;
504                    ast::Expression::Call(ast::CallPhrase {
505                        function: ident,
506                        arguments,
507                    })
508                } else {
509                    ast::Expression::Ident(ident)
510                }
511            }
512            other => {
513                return Err(Box::new(Error::Unexpected(
514                    other.1,
515                    ExpectedToken::PrimaryExpression,
516                )))
517            }
518        };
519
520        self.pop_rule_span(lexer);
521        let span = lexer.span_with_start(token.1);
522        let expr = ctx.expressions.append(expr, span);
523        Ok(expr)
524    }
525
526    fn component_or_swizzle_specifier<'a>(
527        &mut self,
528        expr_start: Span,
529        lexer: &mut Lexer<'a>,
530        ctx: &mut ExpressionContext<'a, '_, '_>,
531        expr: Handle<ast::Expression<'a>>,
532    ) -> Result<'a, Handle<ast::Expression<'a>>> {
533        let mut expr = expr;
534
535        loop {
536            let expression = match lexer.peek().0 {
537                Token::Separator('.') => {
538                    let _ = lexer.next();
539                    let field = lexer.next_ident()?;
540
541                    ast::Expression::Member { base: expr, field }
542                }
543                Token::Paren('[') => {
544                    let _ = lexer.next();
545                    let index = self.enclosed_expression(lexer, ctx)?;
546                    lexer.expect(Token::Paren(']'))?;
547
548                    ast::Expression::Index { base: expr, index }
549                }
550                _ => break,
551            };
552
553            let span = lexer.span_with_start(expr_start);
554            expr = ctx.expressions.append(expression, span);
555        }
556
557        Ok(expr)
558    }
559
560    /// Parse a `unary_expression`.
561    fn unary_expression<'a>(
562        &mut self,
563        lexer: &mut Lexer<'a>,
564        ctx: &mut ExpressionContext<'a, '_, '_>,
565    ) -> Result<'a, Handle<ast::Expression<'a>>> {
566        self.push_rule_span(Rule::UnaryExpr, lexer);
567
568        enum UnaryOp {
569            Negate,
570            LogicalNot,
571            BitwiseNot,
572            Deref,
573            AddrOf,
574        }
575
576        let mut ops = Vec::new();
577        let mut expr;
578
579        loop {
580            match lexer.next() {
581                (Token::Operation('-'), span) => {
582                    ops.push((UnaryOp::Negate, span));
583                }
584                (Token::Operation('!'), span) => {
585                    ops.push((UnaryOp::LogicalNot, span));
586                }
587                (Token::Operation('~'), span) => {
588                    ops.push((UnaryOp::BitwiseNot, span));
589                }
590                (Token::Operation('*'), span) => {
591                    ops.push((UnaryOp::Deref, span));
592                }
593                (Token::Operation('&'), span) => {
594                    ops.push((UnaryOp::AddrOf, span));
595                }
596                token => {
597                    expr = self.singular_expression(lexer, ctx, token)?;
598                    break;
599                }
600            };
601        }
602
603        for (op, span) in ops.into_iter().rev() {
604            let e = match op {
605                UnaryOp::Negate => ast::Expression::Unary {
606                    op: crate::UnaryOperator::Negate,
607                    expr,
608                },
609                UnaryOp::LogicalNot => ast::Expression::Unary {
610                    op: crate::UnaryOperator::LogicalNot,
611                    expr,
612                },
613                UnaryOp::BitwiseNot => ast::Expression::Unary {
614                    op: crate::UnaryOperator::BitwiseNot,
615                    expr,
616                },
617                UnaryOp::Deref => ast::Expression::Deref(expr),
618                UnaryOp::AddrOf => ast::Expression::AddrOf(expr),
619            };
620            let span = lexer.span_with_start(span);
621            expr = ctx.expressions.append(e, span);
622        }
623
624        self.pop_rule_span(lexer);
625        Ok(expr)
626    }
627
628    /// Parse a `lhs_expression`.
629    ///
630    /// LHS expressions only support the `&` and `*` operators and
631    /// the `[]` and `.` postfix selectors.
632    fn lhs_expression<'a>(
633        &mut self,
634        lexer: &mut Lexer<'a>,
635        ctx: &mut ExpressionContext<'a, '_, '_>,
636        token: Option<TokenSpan<'a>>,
637        expected_token: ExpectedToken<'a>,
638    ) -> Result<'a, Handle<ast::Expression<'a>>> {
639        self.track_recursion(|this| {
640            this.push_rule_span(Rule::LhsExpr, lexer);
641            let token = token.unwrap_or_else(|| lexer.next());
642            let expr = match token {
643                (Token::Operation('*'), _) => {
644                    let expr =
645                        this.lhs_expression(lexer, ctx, None, ExpectedToken::LhsExpression)?;
646                    let expr = ast::Expression::Deref(expr);
647                    let span = this.peek_rule_span(lexer);
648                    ctx.expressions.append(expr, span)
649                }
650                (Token::Operation('&'), _) => {
651                    let expr =
652                        this.lhs_expression(lexer, ctx, None, ExpectedToken::LhsExpression)?;
653                    let expr = ast::Expression::AddrOf(expr);
654                    let span = this.peek_rule_span(lexer);
655                    ctx.expressions.append(expr, span)
656                }
657                (Token::Paren('('), span) => {
658                    let expr =
659                        this.lhs_expression(lexer, ctx, None, ExpectedToken::LhsExpression)?;
660                    lexer.expect(Token::Paren(')'))?;
661                    this.component_or_swizzle_specifier(span, lexer, ctx, expr)?
662                }
663                (Token::Word(word), span) => {
664                    let ident = this.ident_expr(word, span, ctx);
665                    let ident = ast::TemplateElaboratedIdent {
666                        ident,
667                        ident_span: span,
668                        template_list: Vec::new(),
669                        template_list_span: Span::UNDEFINED,
670                    };
671                    let ident = ctx.expressions.append(ast::Expression::Ident(ident), span);
672                    this.component_or_swizzle_specifier(span, lexer, ctx, ident)?
673                }
674                (_, span) => {
675                    return Err(Box::new(Error::Unexpected(span, expected_token)));
676                }
677            };
678
679            this.pop_rule_span(lexer);
680            Ok(expr)
681        })
682    }
683
684    /// Parse a `singular_expression`.
685    fn singular_expression<'a>(
686        &mut self,
687        lexer: &mut Lexer<'a>,
688        ctx: &mut ExpressionContext<'a, '_, '_>,
689        token: TokenSpan<'a>,
690    ) -> Result<'a, Handle<ast::Expression<'a>>> {
691        self.push_rule_span(Rule::SingularExpr, lexer);
692        let primary_expr = self.primary_expression(lexer, ctx, token)?;
693        let singular_expr =
694            self.component_or_swizzle_specifier(token.1, lexer, ctx, primary_expr)?;
695        self.pop_rule_span(lexer);
696
697        Ok(singular_expr)
698    }
699
700    fn equality_expression<'a>(
701        &mut self,
702        lexer: &mut Lexer<'a>,
703        context: &mut ExpressionContext<'a, '_, '_>,
704    ) -> Result<'a, Handle<ast::Expression<'a>>> {
705        // equality_expression
706        context.parse_binary_op(
707            lexer,
708            |token| match token {
709                Token::LogicalOperation('=') => Some(crate::BinaryOperator::Equal),
710                Token::LogicalOperation('!') => Some(crate::BinaryOperator::NotEqual),
711                _ => None,
712            },
713            // relational_expression
714            |lexer, context| {
715                let enclosing = self.race_rules(Rule::GenericExpr, Rule::EnclosedExpr);
716                context.parse_binary_op(
717                    lexer,
718                    match enclosing {
719                        Some(Rule::GenericExpr) => |token| match token {
720                            Token::LogicalOperation('<') => Some(crate::BinaryOperator::LessEqual),
721                            _ => None,
722                        },
723                        _ => |token| match token {
724                            Token::Paren('<') => Some(crate::BinaryOperator::Less),
725                            Token::Paren('>') => Some(crate::BinaryOperator::Greater),
726                            Token::LogicalOperation('<') => Some(crate::BinaryOperator::LessEqual),
727                            Token::LogicalOperation('>') => {
728                                Some(crate::BinaryOperator::GreaterEqual)
729                            }
730                            _ => None,
731                        },
732                    },
733                    // shift_expression
734                    |lexer, context| {
735                        context.parse_binary_op(
736                            lexer,
737                            match enclosing {
738                                Some(Rule::GenericExpr) => |token| match token {
739                                    Token::ShiftOperation('<') => {
740                                        Some(crate::BinaryOperator::ShiftLeft)
741                                    }
742                                    _ => None,
743                                },
744                                _ => |token| match token {
745                                    Token::ShiftOperation('<') => {
746                                        Some(crate::BinaryOperator::ShiftLeft)
747                                    }
748                                    Token::ShiftOperation('>') => {
749                                        Some(crate::BinaryOperator::ShiftRight)
750                                    }
751                                    _ => None,
752                                },
753                            },
754                            // additive_expression
755                            |lexer, context| {
756                                context.parse_binary_op(
757                                    lexer,
758                                    |token| match token {
759                                        Token::Operation('+') => Some(crate::BinaryOperator::Add),
760                                        Token::Operation('-') => {
761                                            Some(crate::BinaryOperator::Subtract)
762                                        }
763                                        _ => None,
764                                    },
765                                    // multiplicative_expression
766                                    |lexer, context| {
767                                        context.parse_binary_op(
768                                            lexer,
769                                            |token| match token {
770                                                Token::Operation('*') => {
771                                                    Some(crate::BinaryOperator::Multiply)
772                                                }
773                                                Token::Operation('/') => {
774                                                    Some(crate::BinaryOperator::Divide)
775                                                }
776                                                Token::Operation('%') => {
777                                                    Some(crate::BinaryOperator::Modulo)
778                                                }
779                                                _ => None,
780                                            },
781                                            |lexer, context| self.unary_expression(lexer, context),
782                                        )
783                                    },
784                                )
785                            },
786                        )
787                    },
788                )
789            },
790        )
791    }
792
793    fn expression<'a>(
794        &mut self,
795        lexer: &mut Lexer<'a>,
796        context: &mut ExpressionContext<'a, '_, '_>,
797    ) -> Result<'a, Handle<ast::Expression<'a>>> {
798        self.track_recursion(|this| {
799            this.push_rule_span(Rule::GeneralExpr, lexer);
800            // logical_or_expression
801            let handle = context.parse_binary_op(
802                lexer,
803                |token| match token {
804                    Token::LogicalOperation('|') => Some(crate::BinaryOperator::LogicalOr),
805                    _ => None,
806                },
807                // logical_and_expression
808                |lexer, context| {
809                    context.parse_binary_op(
810                        lexer,
811                        |token| match token {
812                            Token::LogicalOperation('&') => Some(crate::BinaryOperator::LogicalAnd),
813                            _ => None,
814                        },
815                        // inclusive_or_expression
816                        |lexer, context| {
817                            context.parse_binary_op(
818                                lexer,
819                                |token| match token {
820                                    Token::Operation('|') => {
821                                        Some(crate::BinaryOperator::InclusiveOr)
822                                    }
823                                    _ => None,
824                                },
825                                // exclusive_or_expression
826                                |lexer, context| {
827                                    context.parse_binary_op(
828                                        lexer,
829                                        |token| match token {
830                                            Token::Operation('^') => {
831                                                Some(crate::BinaryOperator::ExclusiveOr)
832                                            }
833                                            _ => None,
834                                        },
835                                        // and_expression
836                                        |lexer, context| {
837                                            context.parse_binary_op(
838                                                lexer,
839                                                |token| match token {
840                                                    Token::Operation('&') => {
841                                                        Some(crate::BinaryOperator::And)
842                                                    }
843                                                    _ => None,
844                                                },
845                                                |lexer, context| {
846                                                    this.equality_expression(lexer, context)
847                                                },
848                                            )
849                                        },
850                                    )
851                                },
852                            )
853                        },
854                    )
855                },
856            )?;
857            this.pop_rule_span(lexer);
858            Ok(handle)
859        })
860    }
861
862    fn optionally_typed_ident<'a>(
863        &mut self,
864        lexer: &mut Lexer<'a>,
865        ctx: &mut ExpressionContext<'a, '_, '_>,
866    ) -> Result<'a, (ast::Ident<'a>, Option<ast::TemplateElaboratedIdent<'a>>)> {
867        let name = lexer.next_ident()?;
868
869        let ty = if lexer.next_if(Token::Separator(':')) {
870            Some(self.type_specifier(lexer, ctx)?)
871        } else {
872            None
873        };
874
875        Ok((name, ty))
876    }
877
878    /// 'var' _disambiguate_template template_list? optionally_typed_ident
879    fn variable_decl<'a>(
880        &mut self,
881        lexer: &mut Lexer<'a>,
882        ctx: &mut ExpressionContext<'a, '_, '_>,
883    ) -> Result<'a, ast::GlobalVariable<'a>> {
884        self.push_rule_span(Rule::VariableDecl, lexer);
885        let (template_list, _) = self.maybe_template_list(lexer, ctx)?;
886        let (name, ty) = self.optionally_typed_ident(lexer, ctx)?;
887
888        let init = if lexer.next_if(Token::Operation('=')) {
889            let handle = self.expression(lexer, ctx)?;
890            Some(handle)
891        } else {
892            None
893        };
894        lexer.expect(Token::Separator(';'))?;
895        self.pop_rule_span(lexer);
896
897        Ok(ast::GlobalVariable {
898            name,
899            template_list,
900            binding: None,
901            ty,
902            init,
903            doc_comments: Vec::new(),
904            memory_decorations: crate::MemoryDecorations::empty(),
905        })
906    }
907
908    fn struct_body<'a>(
909        &mut self,
910        lexer: &mut Lexer<'a>,
911        ctx: &mut ExpressionContext<'a, '_, '_>,
912    ) -> Result<'a, Vec<ast::StructMember<'a>>> {
913        let mut members = Vec::new();
914        let mut member_names = FastHashSet::default();
915
916        lexer.expect(Token::Paren('{'))?;
917        let mut ready = true;
918        while !lexer.next_if(Token::Paren('}')) {
919            if !ready {
920                return Err(Box::new(Error::Unexpected(
921                    lexer.next().1,
922                    ExpectedToken::Token(Token::Separator(',')),
923                )));
924            }
925
926            let doc_comments = lexer.accumulate_doc_comments();
927
928            let (mut size, mut align) = (ParsedAttribute::default(), ParsedAttribute::default());
929            self.push_rule_span(Rule::Attribute, lexer);
930            let mut bind_parser = BindingParser::default();
931            while lexer.next_if(Token::Attribute) {
932                match lexer.next_ident_with_span()? {
933                    ("size", name_span) => {
934                        lexer.expect(Token::Paren('('))?;
935                        let expr = self.expression(lexer, ctx)?;
936                        lexer.next_if(Token::Separator(','));
937                        lexer.expect(Token::Paren(')'))?;
938                        size.set(expr, name_span)?;
939                    }
940                    ("align", name_span) => {
941                        lexer.expect(Token::Paren('('))?;
942                        let expr = self.expression(lexer, ctx)?;
943                        lexer.next_if(Token::Separator(','));
944                        lexer.expect(Token::Paren(')'))?;
945                        align.set(expr, name_span)?;
946                    }
947                    (word, word_span) => bind_parser.parse(self, lexer, word, word_span, ctx)?,
948                }
949            }
950
951            let bind_span = self.pop_rule_span(lexer);
952            let binding = bind_parser.finish(bind_span)?;
953
954            let name = lexer.next_ident()?;
955            lexer.expect(Token::Separator(':'))?;
956            let ty = self.type_specifier(lexer, ctx)?;
957            ready = lexer.next_if(Token::Separator(','));
958
959            members.push(ast::StructMember {
960                name,
961                ty,
962                binding,
963                size: size.value,
964                align: align.value,
965                doc_comments,
966            });
967
968            if !member_names.insert(name.name) {
969                return Err(Box::new(Error::Redefinition {
970                    previous: members
971                        .iter()
972                        .find(|x| x.name.name == name.name)
973                        .map(|x| x.name.span)
974                        .unwrap(),
975                    current: name.span,
976                }));
977            }
978        }
979
980        Ok(members)
981    }
982
983    fn maybe_template_list<'a>(
984        &mut self,
985        lexer: &mut Lexer<'a>,
986        ctx: &mut ExpressionContext<'a, '_, '_>,
987    ) -> Result<'a, (Vec<Handle<ast::Expression<'a>>>, Span)> {
988        let start = lexer.start_byte_offset();
989        if lexer.next_if(Token::TemplateArgsStart) {
990            let mut args = Vec::new();
991            args.push(self.expression(lexer, ctx)?);
992            while lexer.next_if(Token::Separator(',')) && lexer.peek().0 != Token::TemplateArgsEnd {
993                args.push(self.expression(lexer, ctx)?);
994            }
995            lexer.expect(Token::TemplateArgsEnd)?;
996            let span = lexer.span_from(start);
997            Ok((args, span))
998        } else {
999            Ok((Vec::new(), Span::UNDEFINED))
1000        }
1001    }
1002
1003    fn template_elaborated_ident<'a>(
1004        &mut self,
1005        word: &'a str,
1006        span: Span,
1007        lexer: &mut Lexer<'a>,
1008        ctx: &mut ExpressionContext<'a, '_, '_>,
1009    ) -> Result<'a, ast::TemplateElaboratedIdent<'a>> {
1010        let ident = self.ident_expr(word, span, ctx);
1011        let (template_list, template_list_span) = self.maybe_template_list(lexer, ctx)?;
1012        Ok(ast::TemplateElaboratedIdent {
1013            ident,
1014            ident_span: span,
1015            template_list,
1016            template_list_span,
1017        })
1018    }
1019
1020    fn type_specifier<'a>(
1021        &mut self,
1022        lexer: &mut Lexer<'a>,
1023        ctx: &mut ExpressionContext<'a, '_, '_>,
1024    ) -> Result<'a, ast::TemplateElaboratedIdent<'a>> {
1025        let (name, span) = lexer.next_ident_with_span()?;
1026        self.template_elaborated_ident(name, span, lexer, ctx)
1027    }
1028
1029    /// Parses assignment, increment and decrement statements
1030    ///
1031    /// This does not consume or require a final `;` token. In the update
1032    /// expression of a C-style `for` loop header, there is no terminating `;`.
1033    fn variable_updating_statement<'a>(
1034        &mut self,
1035        lexer: &mut Lexer<'a>,
1036        ctx: &mut ExpressionContext<'a, '_, '_>,
1037        block: &mut ast::Block<'a>,
1038        token: TokenSpan<'a>,
1039        expected_token: ExpectedToken<'a>,
1040    ) -> Result<'a, ()> {
1041        match token {
1042            (Token::Word("_"), span) => {
1043                lexer.expect(Token::Operation('='))?;
1044                let expr = self.expression(lexer, ctx)?;
1045                let span = lexer.span_with_start(span);
1046                block.stmts.push(ast::Statement {
1047                    kind: ast::StatementKind::Phony(expr),
1048                    span,
1049                });
1050                return Ok(());
1051            }
1052            _ => {}
1053        }
1054        let target = self.lhs_expression(lexer, ctx, Some(token), expected_token)?;
1055
1056        let (op, value) = match lexer.next() {
1057            (Token::Operation('='), _) => {
1058                let value = self.expression(lexer, ctx)?;
1059                (None, value)
1060            }
1061            (Token::AssignmentOperation(c), _) => {
1062                use crate::BinaryOperator as Bo;
1063                let op = match c {
1064                    '<' => Bo::ShiftLeft,
1065                    '>' => Bo::ShiftRight,
1066                    '+' => Bo::Add,
1067                    '-' => Bo::Subtract,
1068                    '*' => Bo::Multiply,
1069                    '/' => Bo::Divide,
1070                    '%' => Bo::Modulo,
1071                    '&' => Bo::And,
1072                    '|' => Bo::InclusiveOr,
1073                    '^' => Bo::ExclusiveOr,
1074                    // Note: `consume_token` shouldn't produce any other assignment ops
1075                    _ => unreachable!(),
1076                };
1077
1078                let value = self.expression(lexer, ctx)?;
1079                (Some(op), value)
1080            }
1081            op_token @ (Token::IncrementOperation | Token::DecrementOperation, _) => {
1082                let op = match op_token.0 {
1083                    Token::IncrementOperation => ast::StatementKind::Increment,
1084                    Token::DecrementOperation => ast::StatementKind::Decrement,
1085                    _ => unreachable!(),
1086                };
1087
1088                let span = lexer.span_with_start(token.1);
1089                block.stmts.push(ast::Statement {
1090                    kind: op(target),
1091                    span,
1092                });
1093                return Ok(());
1094            }
1095            (_, span) => return Err(Box::new(Error::Unexpected(span, ExpectedToken::Assignment))),
1096        };
1097
1098        let span = lexer.span_with_start(token.1);
1099        block.stmts.push(ast::Statement {
1100            kind: ast::StatementKind::Assign { target, op, value },
1101            span,
1102        });
1103        Ok(())
1104    }
1105
1106    /// Parse a function call statement.
1107    ///
1108    /// This assumes that `token` has been consumed from the lexer.
1109    ///
1110    /// This does not consume or require a final `;` token. In the update
1111    /// expression of a C-style `for` loop header, there is no terminating `;`.
1112    fn maybe_func_call_statement<'a>(
1113        &mut self,
1114        lexer: &mut Lexer<'a>,
1115        context: &mut ExpressionContext<'a, '_, '_>,
1116        block: &mut ast::Block<'a>,
1117        token: TokenSpan<'a>,
1118    ) -> Result<'a, bool> {
1119        let (name, name_span) = match token {
1120            (Token::Word(name), span) => (name, span),
1121            _ => return Ok(false),
1122        };
1123        let ident = self.template_elaborated_ident(name, name_span, lexer, context)?;
1124        if ident.template_list.is_empty() && !matches!(lexer.peek(), (Token::Paren('('), _)) {
1125            return Ok(false);
1126        }
1127
1128        self.push_rule_span(Rule::SingularExpr, lexer);
1129
1130        let arguments = self.arguments(lexer, context)?;
1131        let span = lexer.span_with_start(name_span);
1132
1133        block.stmts.push(ast::Statement {
1134            kind: ast::StatementKind::Call(ast::CallPhrase {
1135                function: ident,
1136                arguments,
1137            }),
1138            span,
1139        });
1140
1141        self.pop_rule_span(lexer);
1142
1143        Ok(true)
1144    }
1145
1146    /// Parses func_call_statement and variable_updating_statement
1147    ///
1148    /// This does not consume or require a final `;` token. In the update
1149    /// expression of a C-style `for` loop header, there is no terminating `;`.
1150    fn func_call_or_variable_updating_statement<'a>(
1151        &mut self,
1152        lexer: &mut Lexer<'a>,
1153        context: &mut ExpressionContext<'a, '_, '_>,
1154        block: &mut ast::Block<'a>,
1155        token: TokenSpan<'a>,
1156        expected_token: ExpectedToken<'a>,
1157    ) -> Result<'a, ()> {
1158        if !self.maybe_func_call_statement(lexer, context, block, token)? {
1159            self.variable_updating_statement(lexer, context, block, token, expected_token)?;
1160        }
1161        Ok(())
1162    }
1163
1164    /// Parses variable_or_value_statement, func_call_statement and variable_updating_statement.
1165    ///
1166    /// This is equivalent to the `for_init` production in the WGSL spec,
1167    /// but it's also used for parsing these forms when they appear within a block,
1168    /// hence the longer name.
1169    ///
1170    /// This does not consume the following `;` token.
1171    fn variable_or_value_or_func_call_or_variable_updating_statement<'a>(
1172        &mut self,
1173        lexer: &mut Lexer<'a>,
1174        ctx: &mut ExpressionContext<'a, '_, '_>,
1175        block: &mut ast::Block<'a>,
1176        token: TokenSpan<'a>,
1177        expected_token: ExpectedToken<'a>,
1178    ) -> Result<'a, ()> {
1179        let local_decl = match token {
1180            (Token::Word("let"), _) => {
1181                let (name, given_ty) = self.optionally_typed_ident(lexer, ctx)?;
1182
1183                lexer.expect(Token::Operation('='))?;
1184                let expr_id = self.expression(lexer, ctx)?;
1185
1186                let handle = ctx.declare_local(name)?;
1187                ast::LocalDecl::Let(ast::Let {
1188                    name,
1189                    ty: given_ty,
1190                    init: expr_id,
1191                    handle,
1192                })
1193            }
1194            (Token::Word("const"), _) => {
1195                let (name, given_ty) = self.optionally_typed_ident(lexer, ctx)?;
1196
1197                lexer.expect(Token::Operation('='))?;
1198                let expr_id = self.expression(lexer, ctx)?;
1199
1200                let handle = ctx.declare_local(name)?;
1201                ast::LocalDecl::Const(ast::LocalConst {
1202                    name,
1203                    ty: given_ty,
1204                    init: expr_id,
1205                    handle,
1206                })
1207            }
1208            (Token::Word("var"), _) => {
1209                if lexer.next_if(Token::TemplateArgsStart) {
1210                    let (class_str, span) = lexer.next_ident_with_span()?;
1211                    if class_str != "function" {
1212                        return Err(Box::new(Error::InvalidLocalVariableAddressSpace(span)));
1213                    }
1214                    lexer.expect(Token::TemplateArgsEnd)?;
1215                }
1216
1217                let (name, ty) = self.optionally_typed_ident(lexer, ctx)?;
1218
1219                let init = if lexer.next_if(Token::Operation('=')) {
1220                    let init = self.expression(lexer, ctx)?;
1221                    Some(init)
1222                } else {
1223                    None
1224                };
1225
1226                let handle = ctx.declare_local(name)?;
1227                ast::LocalDecl::Var(ast::LocalVariable {
1228                    name,
1229                    ty,
1230                    init,
1231                    handle,
1232                })
1233            }
1234            token => {
1235                return self.func_call_or_variable_updating_statement(
1236                    lexer,
1237                    ctx,
1238                    block,
1239                    token,
1240                    expected_token,
1241                );
1242            }
1243        };
1244
1245        let span = lexer.span_with_start(token.1);
1246        block.stmts.push(ast::Statement {
1247            kind: ast::StatementKind::LocalDecl(local_decl),
1248            span,
1249        });
1250
1251        Ok(())
1252    }
1253
1254    fn statement<'a>(
1255        &mut self,
1256        lexer: &mut Lexer<'a>,
1257        ctx: &mut ExpressionContext<'a, '_, '_>,
1258        block: &mut ast::Block<'a>,
1259        brace_nesting_level: u8,
1260    ) -> Result<'a, ()> {
1261        self.track_recursion(|this| {
1262            this.push_rule_span(Rule::Statement, lexer);
1263
1264            // We peek here instead of eagerly getting the next token since
1265            // `Parser::block` expects its first token to be `{`.
1266            //
1267            // Most callers have a single path leading to the start of the block;
1268            // `statement` is the only exception where there are multiple choices.
1269            match lexer.peek() {
1270                (token, _) if is_start_of_compound_statement(token) => {
1271                    let (inner, span) = this.block(lexer, ctx, brace_nesting_level)?;
1272                    block.stmts.push(ast::Statement {
1273                        kind: ast::StatementKind::Block(inner),
1274                        span,
1275                    });
1276                    this.pop_rule_span(lexer);
1277                    return Ok(());
1278                }
1279                _ => {}
1280            }
1281
1282            let kind = match lexer.next() {
1283                (Token::Separator(';'), _) => {
1284                    this.pop_rule_span(lexer);
1285                    return Ok(());
1286                }
1287                (Token::Word("return"), _) => {
1288                    let value = if lexer.peek().0 != Token::Separator(';') {
1289                        let handle = this.expression(lexer, ctx)?;
1290                        Some(handle)
1291                    } else {
1292                        None
1293                    };
1294                    lexer.expect(Token::Separator(';'))?;
1295                    ast::StatementKind::Return { value }
1296                }
1297                (Token::Word("if"), _) => {
1298                    let condition = this.expression(lexer, ctx)?;
1299
1300                    let accept = this.block(lexer, ctx, brace_nesting_level)?.0;
1301
1302                    let mut elsif_stack = Vec::new();
1303                    let mut elseif_span_start = lexer.start_byte_offset();
1304                    let mut reject = loop {
1305                        if !lexer.next_if(Token::Word("else")) {
1306                            break ast::Block::default();
1307                        }
1308
1309                        if !lexer.next_if(Token::Word("if")) {
1310                            // ... else { ... }
1311                            break this.block(lexer, ctx, brace_nesting_level)?.0;
1312                        }
1313
1314                        // ... else if (...) { ... }
1315                        let other_condition = this.expression(lexer, ctx)?;
1316                        let other_block = this.block(lexer, ctx, brace_nesting_level)?;
1317                        elsif_stack.push((elseif_span_start, other_condition, other_block));
1318                        elseif_span_start = lexer.start_byte_offset();
1319                    };
1320
1321                    // reverse-fold the else-if blocks
1322                    //Note: we may consider uplifting this to the IR
1323                    for (other_span_start, other_cond, other_block) in elsif_stack.into_iter().rev()
1324                    {
1325                        let sub_stmt = ast::StatementKind::If {
1326                            condition: other_cond,
1327                            accept: other_block.0,
1328                            reject,
1329                        };
1330                        reject = ast::Block::default();
1331                        let span = lexer.span_from(other_span_start);
1332                        reject.stmts.push(ast::Statement {
1333                            kind: sub_stmt,
1334                            span,
1335                        })
1336                    }
1337
1338                    ast::StatementKind::If {
1339                        condition,
1340                        accept,
1341                        reject,
1342                    }
1343                }
1344                (Token::Word("switch"), _) => {
1345                    let selector = this.expression(lexer, ctx)?;
1346                    let brace_span = lexer.expect_span(Token::Paren('{'))?;
1347                    let brace_nesting_level =
1348                        Self::increase_brace_nesting(brace_nesting_level, brace_span)?;
1349                    let mut cases = Vec::new();
1350
1351                    loop {
1352                        // cases + default
1353                        match lexer.next() {
1354                            (Token::Word("case"), _) => {
1355                                // parse a list of values
1356                                let value = loop {
1357                                    let value = this.switch_value(lexer, ctx)?;
1358                                    if lexer.next_if(Token::Separator(',')) {
1359                                        // list of values ends with ':' or a compound statement
1360                                        let next_token = lexer.peek().0;
1361                                        if next_token == Token::Separator(':')
1362                                            || is_start_of_compound_statement(next_token)
1363                                        {
1364                                            break value;
1365                                        }
1366                                    } else {
1367                                        break value;
1368                                    }
1369                                    cases.push(ast::SwitchCase {
1370                                        value,
1371                                        body: ast::Block::default(),
1372                                        fall_through: true,
1373                                    });
1374                                };
1375
1376                                lexer.next_if(Token::Separator(':'));
1377
1378                                let body = this.block(lexer, ctx, brace_nesting_level)?.0;
1379
1380                                cases.push(ast::SwitchCase {
1381                                    value,
1382                                    body,
1383                                    fall_through: false,
1384                                });
1385                            }
1386                            (Token::Word("default"), _) => {
1387                                lexer.next_if(Token::Separator(':'));
1388                                let body = this.block(lexer, ctx, brace_nesting_level)?.0;
1389                                cases.push(ast::SwitchCase {
1390                                    value: ast::SwitchValue::Default,
1391                                    body,
1392                                    fall_through: false,
1393                                });
1394                            }
1395                            (Token::Paren('}'), _) => break,
1396                            (_, span) => {
1397                                return Err(Box::new(Error::Unexpected(
1398                                    span,
1399                                    ExpectedToken::SwitchItem,
1400                                )))
1401                            }
1402                        }
1403                    }
1404
1405                    ast::StatementKind::Switch { selector, cases }
1406                }
1407                (Token::Word("loop"), _) => this.r#loop(lexer, ctx, brace_nesting_level)?,
1408                (Token::Word("while"), _) => {
1409                    let mut body = ast::Block::default();
1410
1411                    let (condition, span) =
1412                        lexer.capture_span(|lexer| this.expression(lexer, ctx))?;
1413                    let mut reject = ast::Block::default();
1414                    reject.stmts.push(ast::Statement {
1415                        kind: ast::StatementKind::Break,
1416                        span,
1417                    });
1418
1419                    body.stmts.push(ast::Statement {
1420                        kind: ast::StatementKind::If {
1421                            condition,
1422                            accept: ast::Block::default(),
1423                            reject,
1424                        },
1425                        span,
1426                    });
1427
1428                    let (block, span) = this.block(lexer, ctx, brace_nesting_level)?;
1429                    body.stmts.push(ast::Statement {
1430                        kind: ast::StatementKind::Block(block),
1431                        span,
1432                    });
1433
1434                    ast::StatementKind::Loop {
1435                        body,
1436                        continuing: ast::Block::default(),
1437                        break_if: None,
1438                    }
1439                }
1440                (Token::Word("for"), _) => {
1441                    lexer.expect(Token::Paren('('))?;
1442
1443                    ctx.local_table.push_scope();
1444
1445                    if !lexer.next_if(Token::Separator(';')) {
1446                        let token = lexer.next();
1447                        this.variable_or_value_or_func_call_or_variable_updating_statement(
1448                            lexer,
1449                            ctx,
1450                            block,
1451                            token,
1452                            ExpectedToken::ForInit,
1453                        )?;
1454                        lexer.expect(Token::Separator(';'))?;
1455                    };
1456
1457                    let mut body = ast::Block::default();
1458                    if !lexer.next_if(Token::Separator(';')) {
1459                        let (condition, span) = lexer.capture_span(|lexer| -> Result<'_, _> {
1460                            let condition = this.expression(lexer, ctx)?;
1461                            lexer.expect(Token::Separator(';'))?;
1462                            Ok(condition)
1463                        })?;
1464                        let mut reject = ast::Block::default();
1465                        reject.stmts.push(ast::Statement {
1466                            kind: ast::StatementKind::Break,
1467                            span,
1468                        });
1469                        body.stmts.push(ast::Statement {
1470                            kind: ast::StatementKind::If {
1471                                condition,
1472                                accept: ast::Block::default(),
1473                                reject,
1474                            },
1475                            span,
1476                        });
1477                    };
1478
1479                    let mut continuing = ast::Block::default();
1480                    if !lexer.next_if(Token::Paren(')')) {
1481                        let token = lexer.next();
1482                        this.func_call_or_variable_updating_statement(
1483                            lexer,
1484                            ctx,
1485                            &mut continuing,
1486                            token,
1487                            ExpectedToken::ForUpdate,
1488                        )?;
1489                        lexer.expect(Token::Paren(')'))?;
1490                    }
1491
1492                    let (block, span) = this.block(lexer, ctx, brace_nesting_level)?;
1493                    body.stmts.push(ast::Statement {
1494                        kind: ast::StatementKind::Block(block),
1495                        span,
1496                    });
1497
1498                    ctx.local_table.pop_scope();
1499
1500                    ast::StatementKind::Loop {
1501                        body,
1502                        continuing,
1503                        break_if: None,
1504                    }
1505                }
1506                (Token::Word("break"), span) => {
1507                    // Check if the next token is an `if`, this indicates
1508                    // that the user tried to type out a `break if` which
1509                    // is illegal in this position.
1510                    let (peeked_token, peeked_span) = lexer.peek();
1511                    if let Token::Word("if") = peeked_token {
1512                        let span = span.until(&peeked_span);
1513                        return Err(Box::new(Error::InvalidBreakIf(span)));
1514                    }
1515                    lexer.expect(Token::Separator(';'))?;
1516                    ast::StatementKind::Break
1517                }
1518                (Token::Word("continue"), _) => {
1519                    lexer.expect(Token::Separator(';'))?;
1520                    ast::StatementKind::Continue
1521                }
1522                (Token::Word("discard"), _) => {
1523                    lexer.expect(Token::Separator(';'))?;
1524                    ast::StatementKind::Kill
1525                }
1526                // https://www.w3.org/TR/WGSL/#const-assert-statement
1527                (Token::Word("const_assert"), _) => {
1528                    // parentheses are optional
1529                    let paren = lexer.next_if(Token::Paren('('));
1530
1531                    let condition = this.expression(lexer, ctx)?;
1532
1533                    if paren {
1534                        lexer.expect(Token::Paren(')'))?;
1535                    }
1536                    lexer.expect(Token::Separator(';'))?;
1537                    ast::StatementKind::ConstAssert(condition)
1538                }
1539                token => {
1540                    this.variable_or_value_or_func_call_or_variable_updating_statement(
1541                        lexer,
1542                        ctx,
1543                        block,
1544                        token,
1545                        ExpectedToken::Statement,
1546                    )?;
1547                    lexer.expect(Token::Separator(';'))?;
1548                    this.pop_rule_span(lexer);
1549                    return Ok(());
1550                }
1551            };
1552
1553            let span = this.pop_rule_span(lexer);
1554            block.stmts.push(ast::Statement { kind, span });
1555
1556            Ok(())
1557        })
1558    }
1559
1560    fn r#loop<'a>(
1561        &mut self,
1562        lexer: &mut Lexer<'a>,
1563        ctx: &mut ExpressionContext<'a, '_, '_>,
1564        brace_nesting_level: u8,
1565    ) -> Result<'a, ast::StatementKind<'a>> {
1566        let mut body = ast::Block::default();
1567        let mut continuing = ast::Block::default();
1568        let mut break_if = None;
1569
1570        let brace_span = lexer.expect_span(Token::Paren('{'))?;
1571        let brace_nesting_level = Self::increase_brace_nesting(brace_nesting_level, brace_span)?;
1572
1573        ctx.local_table.push_scope();
1574
1575        loop {
1576            if lexer.next_if(Token::Word("continuing")) {
1577                // Branch for the `continuing` block, this must be
1578                // the last thing in the loop body
1579
1580                // Expect a opening brace to start the continuing block
1581                let brace_span = lexer.expect_span(Token::Paren('{'))?;
1582                let brace_nesting_level =
1583                    Self::increase_brace_nesting(brace_nesting_level, brace_span)?;
1584                loop {
1585                    if lexer.next_if(Token::Word("break")) {
1586                        // Branch for the `break if` statement, this statement
1587                        // has the form `break if <expr>;` and must be the last
1588                        // statement in a continuing block
1589
1590                        // The break must be followed by an `if` to form
1591                        // the break if
1592                        lexer.expect(Token::Word("if"))?;
1593
1594                        let condition = self.expression(lexer, ctx)?;
1595                        // Set the condition of the break if to the newly parsed
1596                        // expression
1597                        break_if = Some(condition);
1598
1599                        // Expect a semicolon to close the statement
1600                        lexer.expect(Token::Separator(';'))?;
1601                        // Expect a closing brace to close the continuing block,
1602                        // since the break if must be the last statement
1603                        lexer.expect(Token::Paren('}'))?;
1604                        // Stop parsing the continuing block
1605                        break;
1606                    } else if lexer.next_if(Token::Paren('}')) {
1607                        // If we encounter a closing brace it means we have reached
1608                        // the end of the continuing block and should stop processing
1609                        break;
1610                    } else {
1611                        // Otherwise try to parse a statement
1612                        self.statement(lexer, ctx, &mut continuing, brace_nesting_level)?;
1613                    }
1614                }
1615                // Since the continuing block must be the last part of the loop body,
1616                // we expect to see a closing brace to end the loop body
1617                lexer.expect(Token::Paren('}'))?;
1618                break;
1619            }
1620            if lexer.next_if(Token::Paren('}')) {
1621                // If we encounter a closing brace it means we have reached
1622                // the end of the loop body and should stop processing
1623                break;
1624            }
1625            // Otherwise try to parse a statement
1626            self.statement(lexer, ctx, &mut body, brace_nesting_level)?;
1627        }
1628
1629        ctx.local_table.pop_scope();
1630
1631        Ok(ast::StatementKind::Loop {
1632            body,
1633            continuing,
1634            break_if,
1635        })
1636    }
1637
1638    /// compound_statement
1639    fn block<'a>(
1640        &mut self,
1641        lexer: &mut Lexer<'a>,
1642        ctx: &mut ExpressionContext<'a, '_, '_>,
1643        brace_nesting_level: u8,
1644    ) -> Result<'a, (ast::Block<'a>, Span)> {
1645        self.push_rule_span(Rule::Block, lexer);
1646
1647        ctx.local_table.push_scope();
1648
1649        let mut diagnostic_filters = DiagnosticFilterMap::new();
1650
1651        self.push_rule_span(Rule::Attribute, lexer);
1652        while lexer.next_if(Token::Attribute) {
1653            let (name, name_span) = lexer.next_ident_with_span()?;
1654            if let Some(DirectiveKind::Diagnostic) = DirectiveKind::from_ident(name) {
1655                let filter = self.diagnostic_filter(lexer)?;
1656                let span = self.peek_rule_span(lexer);
1657                diagnostic_filters
1658                    .add(filter, span, ShouldConflictOnFullDuplicate::Yes)
1659                    .map_err(|e| Box::new(e.into()))?;
1660            } else {
1661                return Err(Box::new(Error::Unexpected(
1662                    name_span,
1663                    ExpectedToken::DiagnosticAttribute,
1664                )));
1665            }
1666        }
1667        self.pop_rule_span(lexer);
1668
1669        if !diagnostic_filters.is_empty() {
1670            return Err(Box::new(
1671                Error::DiagnosticAttributeNotYetImplementedAtParseSite {
1672                    site_name_plural: "compound statements",
1673                    spans: diagnostic_filters.spans().collect(),
1674                },
1675            ));
1676        }
1677
1678        let brace_span = lexer.expect_span(Token::Paren('{'))?;
1679        let brace_nesting_level = Self::increase_brace_nesting(brace_nesting_level, brace_span)?;
1680        let mut block = ast::Block::default();
1681        while !lexer.next_if(Token::Paren('}')) {
1682            self.statement(lexer, ctx, &mut block, brace_nesting_level)?;
1683        }
1684
1685        ctx.local_table.pop_scope();
1686
1687        let span = self.pop_rule_span(lexer);
1688        Ok((block, span))
1689    }
1690
1691    fn varying_binding<'a>(
1692        &mut self,
1693        lexer: &mut Lexer<'a>,
1694        ctx: &mut ExpressionContext<'a, '_, '_>,
1695    ) -> Result<'a, Option<ast::Binding<'a>>> {
1696        let mut bind_parser = BindingParser::default();
1697        self.push_rule_span(Rule::Attribute, lexer);
1698
1699        while lexer.next_if(Token::Attribute) {
1700            let (word, span) = lexer.next_ident_with_span()?;
1701            bind_parser.parse(self, lexer, word, span, ctx)?;
1702        }
1703
1704        let span = self.pop_rule_span(lexer);
1705        bind_parser.finish(span)
1706    }
1707
1708    fn function_decl<'a>(
1709        &mut self,
1710        lexer: &mut Lexer<'a>,
1711        diagnostic_filter_leaf: Option<Handle<DiagnosticFilterNode>>,
1712        must_use: Option<Span>,
1713        out: &mut ast::TranslationUnit<'a>,
1714        dependencies: &mut FastIndexSet<ast::Dependency<'a>>,
1715    ) -> Result<'a, ast::Function<'a>> {
1716        self.push_rule_span(Rule::FunctionDecl, lexer);
1717        // read function name
1718        let fun_name = lexer.next_ident()?;
1719
1720        let mut locals = Arena::new();
1721
1722        let mut ctx = ExpressionContext {
1723            expressions: &mut out.expressions,
1724            local_table: &mut SymbolTable::default(),
1725            locals: &mut locals,
1726            unresolved: dependencies,
1727        };
1728
1729        // start a scope that contains arguments as well as the function body
1730        ctx.local_table.push_scope();
1731        // Reduce lookup scope to parse the parameter list and return type
1732        // avoiding identifier lookup to match newly declared param names.
1733        ctx.local_table.reduce_lookup_scope();
1734
1735        // read parameter list
1736        let mut arguments = Vec::new();
1737        lexer.expect(Token::Paren('('))?;
1738        let mut ready = true;
1739        while !lexer.next_if(Token::Paren(')')) {
1740            if !ready {
1741                return Err(Box::new(Error::Unexpected(
1742                    lexer.next().1,
1743                    ExpectedToken::Token(Token::Separator(',')),
1744                )));
1745            }
1746            let binding = self.varying_binding(lexer, &mut ctx)?;
1747
1748            let param_name = lexer.next_ident()?;
1749
1750            lexer.expect(Token::Separator(':'))?;
1751            let param_type = self.type_specifier(lexer, &mut ctx)?;
1752
1753            let handle = ctx.declare_local(param_name)?;
1754            arguments.push(ast::FunctionArgument {
1755                name: param_name,
1756                ty: param_type,
1757                binding,
1758                handle,
1759            });
1760            ready = lexer.next_if(Token::Separator(','));
1761        }
1762        // read return type
1763        let result = if lexer.next_if(Token::Arrow) {
1764            let binding = self.varying_binding(lexer, &mut ctx)?;
1765            let ty = self.type_specifier(lexer, &mut ctx)?;
1766            let must_use = must_use.is_some();
1767            Some(ast::FunctionResult {
1768                ty,
1769                binding,
1770                must_use,
1771            })
1772        } else if let Some(must_use) = must_use {
1773            return Err(Box::new(Error::FunctionMustUseReturnsVoid(
1774                must_use,
1775                self.peek_rule_span(lexer),
1776            )));
1777        } else {
1778            None
1779        };
1780
1781        ctx.local_table.reset_lookup_scope();
1782
1783        // do not use `self.block` here, since we must not push a new scope
1784        lexer.expect(Token::Paren('{'))?;
1785        let brace_nesting_level = 1;
1786        let mut body = ast::Block::default();
1787        while !lexer.next_if(Token::Paren('}')) {
1788            self.statement(lexer, &mut ctx, &mut body, brace_nesting_level)?;
1789        }
1790
1791        ctx.local_table.pop_scope();
1792
1793        let fun = ast::Function {
1794            entry_point: None,
1795            name: fun_name,
1796            arguments,
1797            result,
1798            body,
1799            diagnostic_filter_leaf,
1800            doc_comments: Vec::new(),
1801        };
1802
1803        // done
1804        self.pop_rule_span(lexer);
1805
1806        Ok(fun)
1807    }
1808
1809    fn directive_ident_list<'a>(
1810        &self,
1811        lexer: &mut Lexer<'a>,
1812        handler: impl FnMut(&'a str, Span) -> Result<'a, ()>,
1813    ) -> Result<'a, ()> {
1814        let mut handler = handler;
1815        'next_arg: loop {
1816            let (ident, span) = lexer.next_ident_with_span()?;
1817            handler(ident, span)?;
1818
1819            let expected_token = match lexer.peek().0 {
1820                Token::Separator(',') => {
1821                    let _ = lexer.next();
1822                    if matches!(lexer.peek().0, Token::Word(..)) {
1823                        continue 'next_arg;
1824                    }
1825                    ExpectedToken::AfterIdentListComma
1826                }
1827                _ => ExpectedToken::AfterIdentListArg,
1828            };
1829
1830            if !matches!(lexer.next().0, Token::Separator(';')) {
1831                return Err(Box::new(Error::Unexpected(span, expected_token)));
1832            }
1833
1834            break Ok(());
1835        }
1836    }
1837
1838    fn global_decl<'a>(
1839        &mut self,
1840        lexer: &mut Lexer<'a>,
1841        out: &mut ast::TranslationUnit<'a>,
1842    ) -> Result<'a, ()> {
1843        let doc_comments = lexer.accumulate_doc_comments();
1844
1845        // read attributes
1846        let mut binding = None;
1847        let mut stage = ParsedAttribute::default();
1848        // Span in case we need to report an error for a shader stage missing something (e.g. its workgroup size).
1849        // Doesn't need to be set in the vertex and fragment stages because they don't have errors like that.
1850        let mut shader_stage_error_span = Span::new(0, 0);
1851        let mut workgroup_size = ParsedAttribute::default();
1852        let mut early_depth_test = ParsedAttribute::default();
1853        let (mut bind_index, mut bind_group) =
1854            (ParsedAttribute::default(), ParsedAttribute::default());
1855        let mut id = ParsedAttribute::default();
1856        // the payload variable for a mesh shader
1857        let mut payload = ParsedAttribute::default();
1858        // the incoming payload from a traceRay call
1859        let mut incoming_payload = ParsedAttribute::default();
1860        let mut mesh_output = ParsedAttribute::default();
1861
1862        let mut must_use: ParsedAttribute<Span> = ParsedAttribute::default();
1863        let mut memory_decorations = crate::MemoryDecorations::empty();
1864
1865        let mut dependencies = FastIndexSet::default();
1866        let mut ctx = ExpressionContext {
1867            expressions: &mut out.expressions,
1868            local_table: &mut SymbolTable::default(),
1869            locals: &mut Arena::new(),
1870            unresolved: &mut dependencies,
1871        };
1872        let mut diagnostic_filters = DiagnosticFilterMap::new();
1873        let ensure_no_diag_attrs = |on_what, filters: DiagnosticFilterMap| -> Result<()> {
1874            if filters.is_empty() {
1875                Ok(())
1876            } else {
1877                Err(Box::new(Error::DiagnosticAttributeNotSupported {
1878                    on_what,
1879                    spans: filters.spans().collect(),
1880                }))
1881            }
1882        };
1883
1884        self.push_rule_span(Rule::Attribute, lexer);
1885        while lexer.next_if(Token::Attribute) {
1886            let (name, name_span) = lexer.next_ident_with_span()?;
1887            if let Some(DirectiveKind::Diagnostic) = DirectiveKind::from_ident(name) {
1888                let filter = self.diagnostic_filter(lexer)?;
1889                let span = self.peek_rule_span(lexer);
1890                diagnostic_filters
1891                    .add(filter, span, ShouldConflictOnFullDuplicate::Yes)
1892                    .map_err(|e| Box::new(e.into()))?;
1893                continue;
1894            }
1895            match name {
1896                "binding" => {
1897                    lexer.expect(Token::Paren('('))?;
1898                    bind_index.set(self.expression(lexer, &mut ctx)?, name_span)?;
1899                    lexer.next_if(Token::Separator(','));
1900                    lexer.expect(Token::Paren(')'))?;
1901                }
1902                "group" => {
1903                    lexer.expect(Token::Paren('('))?;
1904                    bind_group.set(self.expression(lexer, &mut ctx)?, name_span)?;
1905                    lexer.next_if(Token::Separator(','));
1906                    lexer.expect(Token::Paren(')'))?;
1907                }
1908                "id" => {
1909                    lexer.expect(Token::Paren('('))?;
1910                    id.set(self.expression(lexer, &mut ctx)?, name_span)?;
1911                    lexer.next_if(Token::Separator(','));
1912                    lexer.expect(Token::Paren(')'))?;
1913                }
1914                "vertex" => {
1915                    stage.set(ShaderStage::Vertex, name_span)?;
1916                }
1917                "fragment" => {
1918                    stage.set(ShaderStage::Fragment, name_span)?;
1919                }
1920                "compute" => {
1921                    stage.set(ShaderStage::Compute, name_span)?;
1922                    shader_stage_error_span = name_span;
1923                }
1924                "task" => {
1925                    lexer.require_enable_extension(
1926                        ImplementedEnableExtension::WgpuMeshShader,
1927                        name_span,
1928                    )?;
1929                    stage.set(ShaderStage::Task, name_span)?;
1930                    shader_stage_error_span = name_span;
1931                }
1932                "mesh" => {
1933                    lexer.require_enable_extension(
1934                        ImplementedEnableExtension::WgpuMeshShader,
1935                        name_span,
1936                    )?;
1937                    stage.set(ShaderStage::Mesh, name_span)?;
1938                    shader_stage_error_span = name_span;
1939
1940                    lexer.expect(Token::Paren('('))?;
1941                    mesh_output.set(lexer.next_ident_with_span()?, name_span)?;
1942                    lexer.expect(Token::Paren(')'))?;
1943                }
1944                "ray_generation" => {
1945                    lexer.require_enable_extension(
1946                        ImplementedEnableExtension::WgpuRayTracingPipeline,
1947                        name_span,
1948                    )?;
1949                    stage.set(ShaderStage::RayGeneration, name_span)?;
1950                    shader_stage_error_span = name_span;
1951                }
1952                "any_hit" => {
1953                    lexer.require_enable_extension(
1954                        ImplementedEnableExtension::WgpuRayTracingPipeline,
1955                        name_span,
1956                    )?;
1957                    stage.set(ShaderStage::AnyHit, name_span)?;
1958                    shader_stage_error_span = name_span;
1959                }
1960                "closest_hit" => {
1961                    lexer.require_enable_extension(
1962                        ImplementedEnableExtension::WgpuRayTracingPipeline,
1963                        name_span,
1964                    )?;
1965                    stage.set(ShaderStage::ClosestHit, name_span)?;
1966                    shader_stage_error_span = name_span;
1967                }
1968                "miss" => {
1969                    lexer.require_enable_extension(
1970                        ImplementedEnableExtension::WgpuRayTracingPipeline,
1971                        name_span,
1972                    )?;
1973                    stage.set(ShaderStage::Miss, name_span)?;
1974                    shader_stage_error_span = name_span;
1975                }
1976                "payload" => {
1977                    lexer.require_enable_extension(
1978                        ImplementedEnableExtension::WgpuMeshShader,
1979                        name_span,
1980                    )?;
1981                    lexer.expect(Token::Paren('('))?;
1982                    payload.set(lexer.next_ident_with_span()?, name_span)?;
1983                    lexer.expect(Token::Paren(')'))?;
1984                }
1985                "incoming_payload" => {
1986                    lexer.require_enable_extension(
1987                        ImplementedEnableExtension::WgpuRayTracingPipeline,
1988                        name_span,
1989                    )?;
1990                    lexer.expect(Token::Paren('('))?;
1991                    incoming_payload.set(lexer.next_ident_with_span()?, name_span)?;
1992                    lexer.expect(Token::Paren(')'))?;
1993                }
1994                "workgroup_size" => {
1995                    lexer.expect(Token::Paren('('))?;
1996                    let mut new_workgroup_size = [None; 3];
1997                    for size in new_workgroup_size.iter_mut() {
1998                        *size = Some(self.expression(lexer, &mut ctx)?);
1999                        match lexer.next() {
2000                            (Token::Paren(')'), _) => break,
2001                            (Token::Separator(','), _) => {
2002                                if lexer.next_if(Token::Paren(')')) {
2003                                    break;
2004                                }
2005                            }
2006                            other => {
2007                                return Err(Box::new(Error::Unexpected(
2008                                    other.1,
2009                                    ExpectedToken::WorkgroupSizeSeparator,
2010                                )))
2011                            }
2012                        }
2013                    }
2014                    workgroup_size.set(new_workgroup_size, name_span)?;
2015                }
2016                "early_depth_test" => {
2017                    lexer.expect(Token::Paren('('))?;
2018                    let (ident, ident_span) = lexer.next_ident_with_span()?;
2019                    let value = if ident == "force" {
2020                        crate::EarlyDepthTest::Force
2021                    } else {
2022                        crate::EarlyDepthTest::Allow {
2023                            conservative: conv::map_conservative_depth(ident, ident_span)?,
2024                        }
2025                    };
2026                    lexer.expect(Token::Paren(')'))?;
2027                    early_depth_test.set(value, name_span)?;
2028                }
2029                "must_use" => {
2030                    must_use.set(name_span, name_span)?;
2031                }
2032                "coherent" => {
2033                    memory_decorations |= crate::MemoryDecorations::COHERENT;
2034                }
2035                "volatile" => {
2036                    memory_decorations |= crate::MemoryDecorations::VOLATILE;
2037                }
2038                _ => return Err(Box::new(Error::UnknownAttribute(name_span))),
2039            }
2040        }
2041
2042        let attrib_span = self.pop_rule_span(lexer);
2043        match (bind_group.value, bind_index.value) {
2044            (Some(group), Some(index)) => {
2045                binding = Some(ast::ResourceBinding {
2046                    group,
2047                    binding: index,
2048                });
2049            }
2050            (Some(_), None) => {
2051                return Err(Box::new(Error::MissingAttribute("binding", attrib_span)))
2052            }
2053            (None, Some(_)) => return Err(Box::new(Error::MissingAttribute("group", attrib_span))),
2054            (None, None) => {}
2055        }
2056
2057        // read item
2058        let start = lexer.start_byte_offset();
2059        let kind = match lexer.next() {
2060            (Token::Separator(';'), _) => {
2061                ensure_no_diag_attrs(
2062                    DiagnosticAttributeNotSupportedPosition::SemicolonInModulePosition,
2063                    diagnostic_filters,
2064                )?;
2065                None
2066            }
2067            (Token::Word(word), directive_span) if DirectiveKind::from_ident(word).is_some() => {
2068                return Err(Box::new(Error::DirectiveAfterFirstGlobalDecl {
2069                    directive_span,
2070                }));
2071            }
2072            (Token::Word("struct"), _) => {
2073                ensure_no_diag_attrs("`struct`s".into(), diagnostic_filters)?;
2074
2075                let name = lexer.next_ident()?;
2076
2077                let members = self.struct_body(lexer, &mut ctx)?;
2078
2079                Some(ast::GlobalDeclKind::Struct(ast::Struct {
2080                    name,
2081                    members,
2082                    doc_comments,
2083                }))
2084            }
2085            (Token::Word("alias"), _) => {
2086                ensure_no_diag_attrs("`alias`es".into(), diagnostic_filters)?;
2087
2088                let name = lexer.next_ident()?;
2089
2090                lexer.expect(Token::Operation('='))?;
2091                let ty = self.type_specifier(lexer, &mut ctx)?;
2092                lexer.expect(Token::Separator(';'))?;
2093                Some(ast::GlobalDeclKind::Type(ast::TypeAlias { name, ty }))
2094            }
2095            (Token::Word("const"), _) => {
2096                ensure_no_diag_attrs("`const`s".into(), diagnostic_filters)?;
2097
2098                let (name, ty) = self.optionally_typed_ident(lexer, &mut ctx)?;
2099
2100                lexer.expect(Token::Operation('='))?;
2101                let init = self.expression(lexer, &mut ctx)?;
2102                lexer.expect(Token::Separator(';'))?;
2103
2104                Some(ast::GlobalDeclKind::Const(ast::Const {
2105                    name,
2106                    ty,
2107                    init,
2108                    doc_comments,
2109                }))
2110            }
2111            (Token::Word("override"), _) => {
2112                ensure_no_diag_attrs("`override`s".into(), diagnostic_filters)?;
2113
2114                let (name, ty) = self.optionally_typed_ident(lexer, &mut ctx)?;
2115
2116                let init = if lexer.next_if(Token::Operation('=')) {
2117                    Some(self.expression(lexer, &mut ctx)?)
2118                } else {
2119                    None
2120                };
2121
2122                lexer.expect(Token::Separator(';'))?;
2123
2124                Some(ast::GlobalDeclKind::Override(ast::Override {
2125                    name,
2126                    id: id.value,
2127                    ty,
2128                    init,
2129                }))
2130            }
2131            (Token::Word("var"), _) => {
2132                ensure_no_diag_attrs("`var`s".into(), diagnostic_filters)?;
2133
2134                let mut var = self.variable_decl(lexer, &mut ctx)?;
2135                var.binding = binding.take();
2136                var.doc_comments = doc_comments;
2137                var.memory_decorations = memory_decorations;
2138                Some(ast::GlobalDeclKind::Var(var))
2139            }
2140            (Token::Word("fn"), _) => {
2141                let diagnostic_filter_leaf = Self::write_diagnostic_filters(
2142                    &mut out.diagnostic_filters,
2143                    diagnostic_filters,
2144                    out.diagnostic_filter_leaf,
2145                );
2146
2147                let function = self.function_decl(
2148                    lexer,
2149                    diagnostic_filter_leaf,
2150                    must_use.value,
2151                    out,
2152                    &mut dependencies,
2153                )?;
2154                Some(ast::GlobalDeclKind::Fn(ast::Function {
2155                    entry_point: if let Some(stage) = stage.value {
2156                        if stage.compute_like() && workgroup_size.value.is_none() {
2157                            return Err(Box::new(Error::MissingWorkgroupSize(
2158                                shader_stage_error_span,
2159                            )));
2160                        }
2161
2162                        match stage {
2163                            ShaderStage::AnyHit | ShaderStage::ClosestHit | ShaderStage::Miss => {
2164                                if incoming_payload.value.is_none() {
2165                                    return Err(Box::new(Error::MissingIncomingPayload(
2166                                        shader_stage_error_span,
2167                                    )));
2168                                }
2169                            }
2170                            _ => {}
2171                        }
2172
2173                        Some(ast::EntryPoint {
2174                            stage,
2175                            early_depth_test: early_depth_test.value,
2176                            workgroup_size: workgroup_size.value,
2177                            mesh_output_variable: mesh_output.value,
2178                            task_payload: payload.value,
2179                            ray_incoming_payload: incoming_payload.value,
2180                        })
2181                    } else {
2182                        None
2183                    },
2184                    doc_comments,
2185                    ..function
2186                }))
2187            }
2188            (Token::Word("const_assert"), _) => {
2189                ensure_no_diag_attrs("`const_assert`s".into(), diagnostic_filters)?;
2190
2191                // parentheses are optional
2192                let paren = lexer.next_if(Token::Paren('('));
2193
2194                let condition = self.expression(lexer, &mut ctx)?;
2195
2196                if paren {
2197                    lexer.expect(Token::Paren(')'))?;
2198                }
2199                lexer.expect(Token::Separator(';'))?;
2200                Some(ast::GlobalDeclKind::ConstAssert(condition))
2201            }
2202            (Token::End, _) => return Ok(()),
2203            (Token::UnterminatedBlockComment(_), span) => {
2204                return Err(Box::new(Error::UnterminatedBlockComment(span)))
2205            }
2206            other => {
2207                return Err(Box::new(Error::Unexpected(
2208                    other.1,
2209                    ExpectedToken::GlobalItem,
2210                )))
2211            }
2212        };
2213
2214        if let Some(must_use_span) = must_use.value {
2215            if !matches!(kind.as_ref(), Some(ast::GlobalDeclKind::Fn(_))) {
2216                return Err(Box::new(Error::FunctionMustUseOnNonFunction(must_use_span)));
2217            }
2218        }
2219
2220        if let Some(kind) = kind {
2221            out.decls.append(
2222                ast::GlobalDecl { kind, dependencies },
2223                lexer.span_from(start),
2224            );
2225        }
2226
2227        if !self.rules.is_empty() {
2228            log::error!("Reached the end of global decl, but rule stack is not empty");
2229            log::error!("Rules: {:?}", self.rules);
2230            return Err(Box::new(Error::Internal("rule stack is not empty")));
2231        };
2232
2233        match binding {
2234            None => Ok(()),
2235            Some(_) => Err(Box::new(Error::Internal(
2236                "we had the attribute but no var?",
2237            ))),
2238        }
2239    }
2240
2241    pub fn parse<'a>(
2242        &mut self,
2243        source: &'a str,
2244        options: &Options,
2245    ) -> Result<'a, ast::TranslationUnit<'a>> {
2246        self.reset();
2247
2248        let mut lexer = Lexer::new(source, !options.parse_doc_comments);
2249        let mut tu = ast::TranslationUnit::default();
2250        let mut enable_extensions = EnableExtensions::empty();
2251        let mut diagnostic_filters = DiagnosticFilterMap::new();
2252
2253        // Parse module doc comments.
2254        tu.doc_comments = lexer.accumulate_module_doc_comments();
2255
2256        // Parse directives.
2257        while let (Token::Word(word), _) = lexer.peek() {
2258            if let Some(kind) = DirectiveKind::from_ident(word) {
2259                self.push_rule_span(Rule::Directive, &mut lexer);
2260                let _ = lexer.next_ident_with_span().unwrap();
2261                match kind {
2262                    DirectiveKind::Diagnostic => {
2263                        let diagnostic_filter = self.diagnostic_filter(&mut lexer)?;
2264                        let span = self.peek_rule_span(&lexer);
2265                        diagnostic_filters
2266                            .add(diagnostic_filter, span, ShouldConflictOnFullDuplicate::No)
2267                            .map_err(|e| Box::new(e.into()))?;
2268                        lexer.expect(Token::Separator(';'))?;
2269                    }
2270                    DirectiveKind::Enable => {
2271                        self.directive_ident_list(&mut lexer, |ident, span| {
2272                            let kind = EnableExtension::from_ident(ident, span)?;
2273                            let extension = match kind {
2274                                EnableExtension::Implemented(kind) => kind,
2275                                EnableExtension::Unimplemented(kind) => {
2276                                    return Err(Box::new(Error::EnableExtensionNotYetImplemented {
2277                                        kind,
2278                                        span,
2279                                    }))
2280                                }
2281                            };
2282                            // Check if the required capability is supported
2283                            let required_capability = extension.capability();
2284                            if !options.capabilities.intersects(required_capability) {
2285                                return Err(Box::new(Error::EnableExtensionNotSupported {
2286                                    kind,
2287                                    span,
2288                                }));
2289                            }
2290                            enable_extensions.add(extension);
2291                            Ok(())
2292                        })?;
2293                    }
2294                    DirectiveKind::Requires => {
2295                        self.directive_ident_list(&mut lexer, |ident, span| {
2296                            match LanguageExtension::from_ident(ident) {
2297                                Some(LanguageExtension::Implemented(_kind)) => {
2298                                    // NOTE: No further validation is needed for an extension, so
2299                                    // just throw parsed information away. If we ever want to apply
2300                                    // what we've parsed to diagnostics, maybe we'll want to refer
2301                                    // to enabled extensions later?
2302                                    Ok(())
2303                                }
2304                                Some(LanguageExtension::Unimplemented(kind)) => {
2305                                    Err(Box::new(Error::LanguageExtensionNotYetImplemented {
2306                                        kind,
2307                                        span,
2308                                    }))
2309                                }
2310                                None => Err(Box::new(Error::UnknownLanguageExtension(span, ident))),
2311                            }
2312                        })?;
2313                    }
2314                }
2315                self.pop_rule_span(&lexer);
2316            } else {
2317                break;
2318            }
2319        }
2320
2321        lexer.enable_extensions = enable_extensions;
2322        tu.enable_extensions = enable_extensions;
2323        tu.diagnostic_filter_leaf =
2324            Self::write_diagnostic_filters(&mut tu.diagnostic_filters, diagnostic_filters, None);
2325
2326        loop {
2327            match self.global_decl(&mut lexer, &mut tu) {
2328                Err(error) => return Err(error),
2329                Ok(()) => {
2330                    if lexer.peek().0 == Token::End {
2331                        break;
2332                    }
2333                }
2334            }
2335        }
2336
2337        Ok(tu)
2338    }
2339
2340    fn increase_brace_nesting(brace_nesting_level: u8, brace_span: Span) -> Result<'static, u8> {
2341        // From [spec.](https://gpuweb.github.io/gpuweb/wgsl/#limits):
2342        //
2343        // > § 2.4. Limits
2344        // >
2345        // > …
2346        // >
2347        // > Maximum nesting depth of brace-enclosed statements in a function[:] 127
2348        const BRACE_NESTING_MAXIMUM: u8 = 127;
2349        if brace_nesting_level + 1 > BRACE_NESTING_MAXIMUM {
2350            return Err(Box::new(Error::ExceededLimitForNestedBraces {
2351                span: brace_span,
2352                limit: BRACE_NESTING_MAXIMUM,
2353            }));
2354        }
2355        Ok(brace_nesting_level + 1)
2356    }
2357
2358    fn diagnostic_filter<'a>(&self, lexer: &mut Lexer<'a>) -> Result<'a, DiagnosticFilter> {
2359        lexer.expect(Token::Paren('('))?;
2360
2361        let (severity_control_name, severity_control_name_span) = lexer.next_ident_with_span()?;
2362        let new_severity = diagnostic_filter::Severity::from_wgsl_ident(severity_control_name)
2363            .ok_or(Error::DiagnosticInvalidSeverity {
2364                severity_control_name_span,
2365            })?;
2366
2367        lexer.expect(Token::Separator(','))?;
2368
2369        let (diagnostic_name_token, diagnostic_name_token_span) = lexer.next_ident_with_span()?;
2370        let triggering_rule = if lexer.next_if(Token::Separator('.')) {
2371            let (ident, _span) = lexer.next_ident_with_span()?;
2372            FilterableTriggeringRule::User(Box::new([diagnostic_name_token.into(), ident.into()]))
2373        } else {
2374            let diagnostic_rule_name = diagnostic_name_token;
2375            let diagnostic_rule_name_span = diagnostic_name_token_span;
2376            if let Some(triggering_rule) =
2377                StandardFilterableTriggeringRule::from_wgsl_ident(diagnostic_rule_name)
2378            {
2379                FilterableTriggeringRule::Standard(triggering_rule)
2380            } else {
2381                diagnostic_filter::Severity::Warning.report_wgsl_parse_diag(
2382                    Box::new(Error::UnknownDiagnosticRuleName(diagnostic_rule_name_span)),
2383                    lexer.source,
2384                )?;
2385                FilterableTriggeringRule::Unknown(diagnostic_rule_name.into())
2386            }
2387        };
2388        let filter = DiagnosticFilter {
2389            triggering_rule,
2390            new_severity,
2391        };
2392        lexer.next_if(Token::Separator(','));
2393        lexer.expect(Token::Paren(')'))?;
2394
2395        Ok(filter)
2396    }
2397
2398    pub(crate) fn write_diagnostic_filters(
2399        arena: &mut Arena<DiagnosticFilterNode>,
2400        filters: DiagnosticFilterMap,
2401        parent: Option<Handle<DiagnosticFilterNode>>,
2402    ) -> Option<Handle<DiagnosticFilterNode>> {
2403        filters
2404            .into_iter()
2405            .fold(parent, |parent, (triggering_rule, (new_severity, span))| {
2406                Some(arena.append(
2407                    DiagnosticFilterNode {
2408                        inner: DiagnosticFilter {
2409                            new_severity,
2410                            triggering_rule,
2411                        },
2412                        parent,
2413                    },
2414                    span,
2415                ))
2416            })
2417    }
2418}
2419
2420const fn is_start_of_compound_statement<'a>(token: Token<'a>) -> bool {
2421    matches!(token, Token::Attribute | Token::Paren('{'))
2422}