proc-macro-workshop:seq-7

审题

// The previous examples all used an exclusive range, MIN..MAX. Now make it work
// for an inclusive range MIN..=MAX that includes the upper range bound!

use seq::seq;

seq!(N in 16..=20 {
    enum E {
        #(
            Variant~N,
        )*
    }
});

fn main() {
    let e = E::Variant16;

    let desc = match e {
        E::Variant16 => "min",
        E::Variant17 | E::Variant18 | E::Variant19 => "in between",
        E::Variant20 => "max",
    };

    assert_eq!(desc, "min");
}

这一关主要是增加了a..=b中的相等,也就是对end的调整。
解析的时候我们需要预读一下。

题解

pub(crate) fn parse_range(input: &syn::parse::ParseStream) -> syn::Result<(usize, usize)> {
    let begin = input.parse::<syn::LitInt>()?.base10_parse()?;
    let _ = input.parse::<syn::Token!(..)>()?;
    let mut incude_grater = false;
    if input.peek(syn::Token!(=)) {
        input.parse::<syn::Token!(=)>()?;
        incude_grater = true;
    }
    let mut end = input.parse::<syn::LitInt>()?.base10_parse()?;
    if incude_grater {
        end += 1;
    }
    syn::Result::Ok((begin, end))
}

其中使用peek方法,我们可以预读一下而不消耗token,十分方便。
这里parse方法对应的调整即可

impl syn::parse::Parse for crate::parser::SeqParser {
    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
        let variable_ident = input.parse::<syn::Ident>()?;
        let _ = input.parse::<syn::Token!(in)>()?;
        let (begin, end) = crate::solution7::parse_range(&input)?;
        let body_buf;
        let _ = syn::braced!(body_buf in input);
        let body = body_buf.parse::<proc_macro2::TokenStream>()?;
        syn::Result::Ok(crate::parser::SeqParser {
            variable_ident,
            begin,
            end,
            body,
        })
    }
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!