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