wgsl_parser/
traversal.rs

1//! Defines the [`Visitor`] and [`Walk`] traits for traversing a WGSL syntax tree.
2
3use gramatika::Token as _;
4
5use crate::{
6	common::{AttributeList, TypeDecl},
7	decl::{
8		legacy::{ExtensionDecl, ModuleDecl},
9		Decl, FieldDecl, FunctionDecl, ImportDecl, ImportPath, ImportPathBlock, ImportPathDecl,
10		NamespacedImportPath, ParamDecl, StructDecl, TypeAliasDecl, VarDecl,
11	},
12	expr::{
13		BinaryExpr, BitcastExpr, Expr, FnCallExpr, GroupExpr, IdentExpr, PostfixExpr, PrimaryExpr,
14		TypeCtorExpr, UnaryPostExpr, UnaryPreExpr,
15	},
16	stmt::{
17		BlockStmt, CaseStmt, ContinuingStmt, ElseStmt, ExprStmt, ForStmt, IfStmt, LoopStmt,
18		ReturnStmt, Stmt, SwitchStmt,
19	},
20	SyntaxTree, Token,
21};
22
23#[derive(Clone, Copy, Default, PartialEq, PartialOrd, Eq, Ord)]
24pub enum FlowControl {
25	#[default]
26	Continue,
27	Break,
28}
29
30#[allow(unused_variables)]
31#[rustfmt::skip]
32pub trait Visitor {
33	#[must_use] fn visit_decl(&mut self, decl: &Decl) -> FlowControl { FlowControl::Continue }
34	#[must_use] fn visit_stmt(&mut self, stmt: &Stmt) -> FlowControl { FlowControl::Continue }
35	#[must_use] fn visit_expr(&mut self, expr: &Expr) -> FlowControl { FlowControl::Continue }
36
37	#[must_use] fn visit_type(&mut self, decl: &TypeDecl) -> FlowControl { FlowControl::Continue }
38	fn visit_attributes(&mut self, attr: &AttributeList) {}
39
40	#[must_use] fn visit_var_decl(&mut self, decl: &VarDecl) -> FlowControl { FlowControl::Continue }
41	#[must_use] fn visit_type_alias_decl(&mut self, decl: &TypeAliasDecl) -> FlowControl { FlowControl::Continue }
42	#[must_use] fn visit_struct_decl(&mut self, decl: &StructDecl) -> FlowControl { FlowControl::Continue }
43	#[must_use] fn visit_field_decl(&mut self, decl: &FieldDecl) -> FlowControl { FlowControl::Continue }
44	#[must_use] fn visit_func_decl(&mut self, decl: &FunctionDecl) -> FlowControl { FlowControl::Continue }
45	#[must_use] fn visit_param_decl(&mut self, decl: &ParamDecl) -> FlowControl { FlowControl::Continue }
46	#[must_use] fn visit_import_path_decl(&mut self, decl: &ImportPathDecl) -> FlowControl { FlowControl::Continue }
47	#[must_use] fn visit_import_decl(&mut self, decl: &ImportDecl) -> FlowControl { FlowControl::Continue }
48	#[must_use] fn visit_import_path(&mut self, path: &ImportPath) -> FlowControl { FlowControl::Continue }
49	fn visit_extension_decl(&mut self, decl: &ExtensionDecl) {}
50	fn visit_module_decl(&mut self, decl: &ModuleDecl) {}
51
52	#[must_use] fn visit_return_stmt(&mut self, stmt: &ReturnStmt) -> FlowControl { FlowControl::Continue }
53	#[must_use] fn visit_if_stmt(&mut self, stmt: &IfStmt) -> FlowControl { FlowControl::Continue }
54	#[must_use] fn visit_else_stmt(&mut self, stmt: &ElseStmt) -> FlowControl { FlowControl::Continue }
55	#[must_use] fn visit_switch_stmt(&mut self, stmt: &SwitchStmt) -> FlowControl { FlowControl::Continue }
56	#[must_use] fn visit_case_stmt(&mut self, stmt: &CaseStmt) -> FlowControl { FlowControl::Continue }
57	#[must_use] fn visit_loop_stmt(&mut self, stmt: &LoopStmt) -> FlowControl { FlowControl::Continue }
58	#[must_use] fn visit_continuing_stmt(&mut self, stmt: &ContinuingStmt) -> FlowControl { FlowControl::Continue }
59	#[must_use] fn visit_for_stmt(&mut self, stmt: &ForStmt) -> FlowControl { FlowControl::Continue }
60	#[must_use] fn visit_expr_stmt(&mut self, stmt: &ExprStmt) -> FlowControl { FlowControl::Continue }
61
62	#[must_use] fn visit_unary_pre_expr(&mut self, expr: &UnaryPreExpr) -> FlowControl { FlowControl::Continue }
63	#[must_use] fn visit_unary_post_expr(&mut self, expr: &UnaryPostExpr) -> FlowControl { FlowControl::Continue }
64	#[must_use] fn visit_binary_expr(&mut self, expr: &BinaryExpr) -> FlowControl { FlowControl::Continue }
65	#[must_use] fn visit_assignment_expr(&mut self, expr: &BinaryExpr) -> FlowControl { FlowControl::Continue }
66	#[must_use] fn visit_fn_call_expr(&mut self, expr: &FnCallExpr) -> FlowControl { FlowControl::Continue }
67	#[must_use] fn visit_type_ctor_expr(&mut self, expr: &TypeCtorExpr) -> FlowControl { FlowControl::Continue }
68	#[must_use] fn visit_group_expr(&mut self, expr: &GroupExpr) -> FlowControl { FlowControl::Continue }
69	#[must_use] fn visit_bitcast_expr(&mut self, expr: &BitcastExpr) -> FlowControl { FlowControl::Continue }
70	#[must_use] fn visit_primary_expr(&mut self, expr: &PrimaryExpr) -> FlowControl { FlowControl::Continue }
71	#[must_use] fn visit_postfix_expr(&mut self, expr: &PostfixExpr) -> FlowControl { FlowControl::Continue }
72	fn visit_literal_expr(&mut self, expr: &Token) {}
73	fn visit_ident_expr(&mut self, expr: &IdentExpr) {}
74}
75
76pub trait Walk {
77	fn walk(&self, visitor: &mut dyn Visitor);
78}
79
80impl Walk for SyntaxTree {
81	fn walk(&self, visitor: &mut dyn Visitor) {
82		for decl in self.inner.iter() {
83			decl.walk(visitor);
84		}
85	}
86}
87
88// --- Declarations ----------------------------------------------------------------------
89
90impl Walk for Decl {
91	fn walk(&self, visitor: &mut dyn Visitor) {
92		use Decl::*;
93
94		if visitor.visit_decl(self) == FlowControl::Continue {
95			match self {
96				Var(decl) | Const(decl) => decl.walk(visitor),
97				TypeAlias(decl) => decl.walk(visitor),
98				Struct(decl) => decl.walk(visitor),
99				Field(decl) => decl.walk(visitor),
100				Function(decl) => decl.walk(visitor),
101				Param(decl) => decl.walk(visitor),
102				Extension(decl) => decl.walk(visitor),
103				ImportPath(decl) => decl.walk(visitor),
104				Import(decl) => decl.walk(visitor),
105				Module(decl) => decl.walk(visitor),
106			}
107		}
108	}
109}
110
111impl Walk for VarDecl {
112	fn walk(&self, visitor: &mut dyn Visitor) {
113		if visitor.visit_var_decl(self) == FlowControl::Continue {
114			if let Some(ref attributes) = self.attributes {
115				visitor.visit_attributes(attributes);
116			}
117
118			if let Some(ref ty) = self.ty {
119				ty.walk(visitor);
120			}
121
122			if let Some(ref expr) = self.assignment {
123				expr.walk(visitor);
124			}
125		}
126	}
127}
128
129impl Walk for TypeAliasDecl {
130	fn walk(&self, visitor: &mut dyn Visitor) {
131		if visitor.visit_type_alias_decl(self) == FlowControl::Continue {
132			self.value.walk(visitor);
133		}
134	}
135}
136
137impl Walk for StructDecl {
138	fn walk(&self, visitor: &mut dyn Visitor) {
139		if visitor.visit_struct_decl(self) == FlowControl::Continue {
140			for field in self.body.fields.iter() {
141				field.walk(visitor);
142			}
143		}
144	}
145}
146
147impl Walk for FieldDecl {
148	fn walk(&self, visitor: &mut dyn Visitor) {
149		if visitor.visit_field_decl(self) == FlowControl::Continue {
150			self.ty.walk(visitor);
151		}
152	}
153}
154
155impl Walk for FunctionDecl {
156	fn walk(&self, visitor: &mut dyn Visitor) {
157		if visitor.visit_func_decl(self) == FlowControl::Continue {
158			for param in self.params.iter() {
159				param.walk(visitor);
160			}
161
162			if let Some(ref ty) = self.return_ty {
163				ty.walk(visitor);
164			}
165
166			self.body.walk(visitor);
167		}
168	}
169}
170
171impl Walk for ParamDecl {
172	fn walk(&self, visitor: &mut dyn Visitor) {
173		if visitor.visit_param_decl(self) == FlowControl::Continue {
174			self.ty.walk(visitor);
175		}
176	}
177}
178
179impl Walk for ExtensionDecl {
180	fn walk(&self, visitor: &mut dyn Visitor) {
181		visitor.visit_extension_decl(self);
182	}
183}
184
185impl Walk for ImportPathDecl {
186	fn walk(&self, visitor: &mut dyn Visitor) {
187		if visitor.visit_import_path_decl(self) == FlowControl::Continue {
188			self.path.walk(visitor);
189		}
190	}
191}
192
193impl Walk for ImportDecl {
194	fn walk(&self, visitor: &mut dyn Visitor) {
195		if visitor.visit_import_decl(self) == FlowControl::Continue {
196			self.path.walk(visitor);
197		}
198	}
199}
200
201impl Walk for ImportPath {
202	fn walk(&self, visitor: &mut dyn Visitor) {
203		if visitor.visit_import_path(self) == FlowControl::Continue {
204			match self {
205				ImportPath::Namespaced(NamespacedImportPath { path, .. }) => {
206					path.walk(visitor);
207				}
208				ImportPath::Block(ImportPathBlock { paths, .. }) => {
209					for path in paths.iter() {
210						path.walk(visitor);
211					}
212				}
213				ImportPath::Leaf(_) => {}
214			}
215		}
216	}
217}
218
219impl Walk for ModuleDecl {
220	fn walk(&self, visitor: &mut dyn Visitor) {
221		visitor.visit_module_decl(self);
222	}
223}
224
225// --- Statements ------------------------------------------------------------------------
226
227impl Walk for Stmt {
228	fn walk(&self, visitor: &mut dyn Visitor) {
229		use Stmt::*;
230
231		if visitor.visit_stmt(self) == FlowControl::Continue {
232			match self {
233				Block(stmt) => stmt.walk(visitor),
234				Return(stmt) => stmt.walk(visitor),
235				If(stmt) => stmt.walk(visitor),
236				Switch(stmt) => stmt.walk(visitor),
237				Loop(stmt) => stmt.walk(visitor),
238				Continuing(stmt) => stmt.walk(visitor),
239				For(stmt) => stmt.walk(visitor),
240				Var(decl) => decl.walk(visitor),
241				Expr(stmt) => stmt.walk(visitor),
242				_ => {}
243			}
244		}
245	}
246}
247
248impl Walk for BlockStmt {
249	fn walk(&self, visitor: &mut dyn Visitor) {
250		for stmt in self.stmts.iter() {
251			stmt.walk(visitor);
252		}
253	}
254}
255
256impl Walk for ReturnStmt {
257	fn walk(&self, visitor: &mut dyn Visitor) {
258		if visitor.visit_return_stmt(self) == FlowControl::Continue {
259			if let Some(ref expr) = self.value {
260				expr.walk(visitor);
261			}
262		}
263	}
264}
265
266impl Walk for IfStmt {
267	fn walk(&self, visitor: &mut dyn Visitor) {
268		if visitor.visit_if_stmt(self) == FlowControl::Continue {
269			self.condition.walk(visitor);
270			self.then_branch.walk(visitor);
271
272			if let Some(ref stmt) = self.else_branch {
273				stmt.walk(visitor);
274			}
275		}
276	}
277}
278
279impl Walk for ElseStmt {
280	fn walk(&self, visitor: &mut dyn Visitor) {
281		if visitor.visit_else_stmt(self) == FlowControl::Continue {
282			self.body.walk(visitor);
283		}
284	}
285}
286
287impl Walk for SwitchStmt {
288	fn walk(&self, visitor: &mut dyn Visitor) {
289		if visitor.visit_switch_stmt(self) == FlowControl::Continue {
290			self.subject.walk(visitor);
291
292			for stmt in self.body.cases.iter() {
293				stmt.walk(visitor);
294			}
295		}
296	}
297}
298
299impl Walk for CaseStmt {
300	fn walk(&self, visitor: &mut dyn Visitor) {
301		if visitor.visit_case_stmt(self) == FlowControl::Continue {
302			for expr in self.selectors.iter() {
303				expr.walk(visitor);
304			}
305			self.body.walk(visitor);
306		}
307	}
308}
309
310impl Walk for LoopStmt {
311	fn walk(&self, visitor: &mut dyn Visitor) {
312		if visitor.visit_loop_stmt(self) == FlowControl::Continue {
313			self.body.walk(visitor);
314		}
315	}
316}
317
318impl Walk for ContinuingStmt {
319	fn walk(&self, visitor: &mut dyn Visitor) {
320		if visitor.visit_continuing_stmt(self) == FlowControl::Continue {
321			self.body.walk(visitor);
322		}
323	}
324}
325
326impl Walk for ForStmt {
327	fn walk(&self, visitor: &mut dyn Visitor) {
328		if visitor.visit_for_stmt(self) == FlowControl::Continue {
329			if let Some(ref stmt) = self.initializer {
330				stmt.walk(visitor);
331			}
332
333			if let Some(ref expr) = self.condition {
334				expr.walk(visitor);
335			}
336
337			if let Some(ref expr) = self.increment {
338				expr.walk(visitor);
339			}
340
341			self.body.walk(visitor);
342		}
343	}
344}
345
346impl Walk for ExprStmt {
347	fn walk(&self, visitor: &mut dyn Visitor) {
348		if visitor.visit_expr_stmt(self) == FlowControl::Continue {
349			self.expr.walk(visitor);
350		}
351	}
352}
353
354// --- Expressions -----------------------------------------------------------------------
355
356impl Walk for Expr {
357	fn walk(&self, visitor: &mut dyn Visitor) {
358		use Expr::*;
359
360		if visitor.visit_expr(self) == FlowControl::Continue {
361			match self {
362				UnaryPre(expr) => expr.walk(visitor),
363				UnaryPost(expr) => expr.walk(visitor),
364				Binary(expr) => expr.walk(visitor),
365				Assignment(expr) => expr.walk(visitor),
366				FnCall(expr) => expr.walk(visitor),
367				TypeCtor(expr) => expr.walk(visitor),
368				Group(expr) => expr.walk(visitor),
369				Bitcast(expr) => expr.walk(visitor),
370				Literal(expr) => visitor.visit_literal_expr(expr),
371				Ident(expr) => visitor.visit_ident_expr(expr),
372				Primary(expr) => expr.walk(visitor),
373			};
374		}
375	}
376}
377
378impl Walk for UnaryPreExpr {
379	fn walk(&self, visitor: &mut dyn Visitor) {
380		if visitor.visit_unary_pre_expr(self) == FlowControl::Continue {
381			self.expr.walk(visitor);
382		}
383	}
384}
385
386impl Walk for UnaryPostExpr {
387	fn walk(&self, visitor: &mut dyn Visitor) {
388		if visitor.visit_unary_post_expr(self) == FlowControl::Continue {
389			self.expr.walk(visitor);
390		}
391	}
392}
393
394impl Walk for BinaryExpr {
395	fn walk(&self, visitor: &mut dyn Visitor) {
396		let visit_method = match self.op.lexeme().as_str() {
397			"=" => Visitor::visit_assignment_expr,
398			_ => Visitor::visit_binary_expr,
399		};
400
401		if visit_method(visitor, self) == FlowControl::Continue {
402			self.lhs.walk(visitor);
403			self.rhs.walk(visitor);
404		}
405	}
406}
407
408impl Walk for FnCallExpr {
409	fn walk(&self, visitor: &mut dyn Visitor) {
410		if visitor.visit_fn_call_expr(self) == FlowControl::Continue {
411			visitor.visit_ident_expr(&self.ident);
412
413			for arg in self.arguments.arguments.iter() {
414				arg.walk(visitor);
415			}
416		}
417	}
418}
419
420impl Walk for TypeCtorExpr {
421	fn walk(&self, visitor: &mut dyn Visitor) {
422		if visitor.visit_type_ctor_expr(self) == FlowControl::Continue {
423			self.ty.walk(visitor);
424
425			for arg in self.arguments.arguments.iter() {
426				arg.walk(visitor);
427			}
428		}
429	}
430}
431
432impl Walk for GroupExpr {
433	fn walk(&self, visitor: &mut dyn Visitor) {
434		if visitor.visit_group_expr(self) == FlowControl::Continue {
435			self.expr.walk(visitor);
436		}
437	}
438}
439
440impl Walk for BitcastExpr {
441	fn walk(&self, visitor: &mut dyn Visitor) {
442		if visitor.visit_bitcast_expr(self) == FlowControl::Continue {
443			self.ty.walk(visitor);
444			self.expr.walk(visitor);
445		}
446	}
447}
448
449impl Walk for PrimaryExpr {
450	fn walk(&self, visitor: &mut dyn Visitor) {
451		if visitor.visit_primary_expr(self) == FlowControl::Continue {
452			self.expr.walk(visitor);
453
454			if let Some(ref expr) = self.postfix {
455				expr.walk(visitor);
456			}
457		}
458	}
459}
460
461impl Walk for PostfixExpr {
462	fn walk(&self, visitor: &mut dyn Visitor) {
463		if visitor.visit_postfix_expr(self) == FlowControl::Continue {
464			self.expr.walk(visitor);
465
466			if let Some(ref expr) = self.postfix {
467				expr.walk(visitor);
468			}
469		}
470	}
471}
472
473// --- Common ----------------------------------------------------------------------------
474
475impl Walk for TypeDecl {
476	fn walk(&self, visitor: &mut dyn Visitor) {
477		if visitor.visit_type(self) == FlowControl::Continue {
478			if let Some(ref attributes) = self.attributes {
479				visitor.visit_attributes(attributes);
480			}
481
482			if let Some(ref ty) = self.child_ty {
483				ty.walk(visitor);
484			}
485
486			visitor.visit_ident_expr(&self.name);
487		}
488	}
489}