Add macro for parsing dictionaries

This commit is contained in:
hal8174 2025-08-10 22:07:44 +02:00
parent b56f952e9b
commit d6662da7b9
Signed by: hal8174
SSH key fingerprint: SHA256:NN98ZYwnrreQLSOV/g+amY7C3yL/mS1heD7bi5t6PPw

View file

@ -47,42 +47,74 @@ fn parse_look_at(iter: &mut Tokenizer) -> Result<Statement> {
))
}
macro_rules! parse_dict {
($tokenizer:expr => $($name_decl:ident, $type:ty, $default:expr);+ => $($name_parsing:ident, $expr:expr, $parsing:expr);+
) => {
{
$(
let mut $name_decl = None;
)+
while let Some(p) = $tokenizer.next_if(|p| p.starts_with('"')).transpose()? {
match p.as_str() {
$(
$expr => {
if $name_parsing.is_none() {
$name_parsing = Some($parsing);
} else {
return Err(miette!("dfs"))
}
}
)+
_ => {todo!()}
}
}
#[derive(Debug)]
struct Dict {
$(
$name_decl: $type,
)+
}
$(
let $name_decl = $name_decl.unwrap_or_else(|| $default);
)*
Dict {
$($name_decl,)*
}
}
};
}
fn parse_shape(iter: &mut Tokenizer) -> Result<Statement> {
let shape_type = iter.next().ok_or(miette!("unable to get shape type"))??;
match shape_type.as_str() {
"\"sphere\"" => {
let mut radius = 1.0;
let zmin = -radius;
let zmax = radius;
let phimax = 360.0;
let mut alpha = ShapeAlpha::None;
while let Some(p) = iter.next_if(|p| p.starts_with('"')).transpose()? {
match p.as_str() {
"\"float radius\"" => {
radius = iter.parse_parameter()?;
}
"\"float alpha\"" => {
alpha = ShapeAlpha::Value(iter.parse_parameter()?);
}
"\"texture alpha\"" => {
alpha = ShapeAlpha::Texture(iter.parse_parameter()?);
}
_ => {
bail!("unknown argument {}", p)
}
}
}
let t = parse_dict!(iter =>
radius, Float, 1.0;
zmin, Float, {-radius};
zmax, Float, {radius};
phimax, Float, 360.0;
alpha, ShapeAlpha, ShapeAlpha::None
=>
radius, "\"float radius\"", iter.parse_parameter()?;
zmin, "\"float zmin\"", iter.parse_parameter()?;
zmax, "\"float zmax\"", iter.parse_parameter()?;
phimax, "\"float phimax\"", iter.parse_parameter()?;
alpha, "\"float alpha\"", ShapeAlpha::Value(iter.parse_parameter()?);
alpha, "\"texture alpha\"", ShapeAlpha::Texture(iter.parse_parameter()?)
);
Ok(Statement::Shape(
ShapeType::Sphere {
radius,
zmin,
zmax,
phimax,
radius: t.radius,
zmin: t.zmin,
zmax: t.zmax,
phimax: t.phimax,
},
alpha,
t.alpha,
))
}
"\"trianglemesh\"" => {