wgsl-parser 0.5.0

A zero-copy recursive-descent parser for WebGPU shading language
Documentation
use crate::{decl::Decl, expr::Expr, utils, ParseStream, SyntaxTree};
use gramatika::{span, ParseStreamer, Span};
use snapshot::{begin_snapshots, snapshot, snapshot_test};

const PROGRAM: &str = include_str!("../../test-files/shader.wgsl");

begin_snapshots!();

#[snapshot_test]
fn find_field_decl() {
	let tree = parse();
	// `position` on line 16
	// Expecting to match the field declaration `@location(0) position: vec3<f32>;`
	let target = span![16:18..16:26];

	snapshot!("{:#?}", utils::find_parent::<Decl>(&tree, target));
}

#[snapshot_test]
fn find_ident_expr() {
	let tree = parse();
	// `matrix` on line 43
	// Expecting to match the IdentExpr `model_matrix_1`
	let target = span![43:18..43:24];
	let line = get_line(target);
	let slice = &line[target.start.character..target.end.character];
	assert_eq!(slice, "matrix");

	snapshot!("{:#?}", utils::find_parent::<Expr>(&tree, target));
}

#[snapshot_test]
fn find_binary_expr() {
	let tree = parse();
	// `*` on line 78
	// Expecting to match the BinaryExpr `light.color * ambient_strength`
	let target = span![78:34..78:35];
	let line = get_line(target);
	let slice = &line[target.start.character..target.end.character];
	assert_eq!(slice, "*");

	snapshot!("{:#?}", utils::find_parent::<Expr>(&tree, target));
}

#[snapshot_test]
fn find_expression_tree() {
	let tree = parse();
	// `model_matrix_1` on line 43
	// Expecting to find all expression parents of the identifier
	let target = span![43:12..43:26];
	let line = get_line(target);
	let slice = &line[target.start.character..target.end.character];
	assert_eq!(slice, "model_matrix_1");

	snapshot!("{:#?}", utils::find_parents::<Expr>(&tree, target));
}

fn parse() -> SyntaxTree {
	match ParseStream::from(PROGRAM).parse::<SyntaxTree>() {
		Ok(tree) => tree,
		Err(err) => {
			eprintln!("{}", err);
			panic!();
		}
	}
}

fn get_line(target: Span) -> &'static str {
	let Some(line) = PROGRAM.lines().enumerate().find_map(|(idx, line)| {
		if idx == target.start.line {
			Some(line)
		} else {
			None
		}
	}) else {
		panic!(
			"Incorrect target span -- line {} does not exist in the source file",
			target.start.line + 1,
		);
	};

	line
}