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::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 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 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 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 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 |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 |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 |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 |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 let handle = context.parse_binary_op(
802 lexer,
803 |token| match token {
804 Token::LogicalOperation('|') => Some(crate::BinaryOperator::LogicalOr),
805 _ => None,
806 },
807 |lexer, context| {
809 context.parse_binary_op(
810 lexer,
811 |token| match token {
812 Token::LogicalOperation('&') => Some(crate::BinaryOperator::LogicalAnd),
813 _ => None,
814 },
815 |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 |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 |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 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 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 _ => 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 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 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 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 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 break this.block(lexer, ctx, brace_nesting_level)?.0;
1312 }
1313
1314 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 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 match lexer.next() {
1354 (Token::Word("case"), _) => {
1355 let value = loop {
1357 let value = this.switch_value(lexer, ctx)?;
1358 if lexer.next_if(Token::Separator(',')) {
1359 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 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 (Token::Word("const_assert"), _) => {
1528 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 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 lexer.expect(Token::Word("if"))?;
1593
1594 let condition = self.expression(lexer, ctx)?;
1595 break_if = Some(condition);
1598
1599 lexer.expect(Token::Separator(';'))?;
1601 lexer.expect(Token::Paren('}'))?;
1604 break;
1606 } else if lexer.next_if(Token::Paren('}')) {
1607 break;
1610 } else {
1611 self.statement(lexer, ctx, &mut continuing, brace_nesting_level)?;
1613 }
1614 }
1615 lexer.expect(Token::Paren('}'))?;
1618 break;
1619 }
1620 if lexer.next_if(Token::Paren('}')) {
1621 break;
1624 }
1625 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 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 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 ctx.local_table.push_scope();
1731 ctx.local_table.reduce_lookup_scope();
1734
1735 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 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 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 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 let mut binding = None;
1847 let mut stage = ParsedAttribute::default();
1848 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 let mut payload = ParsedAttribute::default();
1858 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 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 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 tu.doc_comments = lexer.accumulate_module_doc_comments();
2255
2256 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 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 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 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}