wgsl_parser/decl/
var.rs

1use std::sync::Arc;
2
3use gramatika::{Parse, ParseStreamer, Span, Spanned, Token as _};
4
5use crate::{
6	common::{AttributeList, TypeDecl},
7	expr::Expr,
8	token::{operator, punct, Token, TokenKind},
9	ParseStream,
10};
11
12#[derive(Clone, DebugLisp)]
13pub struct VarDecl {
14	pub attributes: Option<AttributeList>,
15	pub storage: Token,
16	pub storage_qualifiers: Option<Arc<[Token]>>,
17	pub name: Token,
18	pub ty: Option<TypeDecl>,
19	pub assignment: Option<Expr>,
20	pub semicolon: Token,
21}
22
23impl Parse for VarDecl {
24	type Stream = ParseStream;
25
26	fn parse(input: &mut Self::Stream) -> gramatika::Result<Self> {
27		let storage = input.consume_kind(TokenKind::Keyword)?;
28		assert!(matches!(
29			storage.as_matchable(),
30			(TokenKind::Keyword, "let" | "const" | "override" | "var", _)
31		));
32
33		let storage_qualifiers = if input.check(operator![<]) {
34			input.consume(operator![<])?;
35			let mut qual = vec![input.consume_kind(TokenKind::Keyword)?];
36			if input.check(punct![,]) {
37				input.consume(punct![,])?;
38				qual.push(input.consume_kind(TokenKind::Keyword)?);
39			}
40			input.consume(operator![>])?;
41			Some(qual.into())
42		} else {
43			None
44		};
45
46		let name = input.consume_kind(TokenKind::Ident)?;
47		let ty = if input.check(punct![:]) {
48			Some(input.parse::<TypeDecl>()?)
49		} else {
50			None
51		};
52
53		let assignment = if input.check(operator![=]) {
54			input.next().unwrap();
55
56			Some(input.parse::<Expr>()?)
57		} else {
58			None
59		};
60
61		let semicolon = input.consume(punct![;])?;
62
63		Ok(Self {
64			attributes: None,
65			storage,
66			storage_qualifiers,
67			name,
68			ty,
69			assignment,
70			semicolon,
71		})
72	}
73}
74
75impl Spanned for VarDecl {
76	fn span(&self) -> Span {
77		self.storage.span().through(self.semicolon.span())
78	}
79}