macro_rules! puzzle_info {
    (
		name = $name:literal ;
		year = $year:literal ;
		day = $day:literal ;
		$($rest4:tt)*
	) => { ... };
    ( @rest ($parse_input:ident, $parse_expr:expr, $num_parts:expr) ) => { ... };
    ( @rest ($parse_input_old:ident, $parse_expr_old:expr, $num_parts:expr)
		parse = |$parse_input:ident| $parse_expr:expr;
		$($rest1:tt)*
	) => { ... };
    ( @rest ($parse_input:ident, $parse_expr:expr, $num_parts:expr)
		part_one = |$part_input:ident $(, $param_name:ident : $param_type:ty)*| $part_expr:expr;
		$($rest0:tt)*
	) => { ... };
    ( @rest ($parse_input:ident, $parse_expr:expr, $num_parts:expr)
		part_two = |$part_input:ident $(, $param_name:ident : $param_type:ty)*| $part_expr:expr;
		$($rest0:tt)*
	) => { ... };
    ( @rest ($parse_input:ident, $parse_expr:expr, $num_parts:expr)
		commands = [ $($commands:tt)* ];
		$($rest3:tt)*
	) => { ... };
    ( @rest ($parse_input:ident, $parse_expr:expr, $num_parts:expr)
		params = [ $($params:tt)* ];
		$($rest:tt)*
	) => { ... };
    ( @params ) => { ... };
    ( @params $self:ident $name:ident : $type:ty = $val:expr ; $($rest:tt)* ) => { ... };
    ( @commands $commands:ident ) => { ... };
    ( @commands $commands:ident (
		name = $name:literal ;
		method = $method:expr ;
	) ) => { ... };
    ( @commands $commands:ident (
		name = $name:literal ;
		method = $method:expr ;
	) , $($rest:tt)* ) => { ... };
}