Full-qualified identifier in "syn"

I want to support only identifiers in the following forms when parsing a certain syntax through the syn crate:

  • id
  • prefix::id_1::id_n
  • ::id_1::id_2::id_n

Where prefix may be the keywords self, crate, super, or any identifier.

I have done this for parsing the prefix:

fn parse_full_qualified_id_prefix(input: &ParseStream) -> Result<proc_macro2::TokenTree> {
    // `crate`/`super`/`self`
    if input.peek(Token![crate]) {
        let id = input.cursor().ident().map(|(id, _)| id);
        input.parse::<Token![crate]>()?;
        return Ok(proc_macro2::TokenTree::Ident(id.unwrap()));
    }
    if input.peek(Token![super]) {
        let id = input.cursor().ident().map(|(id, _)| id);
        input.parse::<Token![super]>()?;
        return Ok(proc_macro2::TokenTree::Ident(id.unwrap()));
    }
    if input.peek(Token![self]) {
        let id = input.cursor().ident().map(|(id, _)| id);
        input.parse::<Token![self]>()?;
        return Ok(proc_macro2::TokenTree::Ident(id.unwrap()));
    }

    let id = input.cursor().ident().map(|(id, _)| id);
    input.parse::<Ident>()?;
    Ok(proc_macro2::TokenTree::Ident(id.unwrap()))
}

I have done this for parsing the segments:

fn parse_full_qualified_id(input: &ParseStream) -> Result<proc_macro2::TokenStream> {
    let mut result: Vec<proc_macro2::TokenTree> = vec![];

    // Beginning tokens
    if input.peek(Token![::]) {
        result.push(proc_macro2::TokenTree::Punct(input.cursor().punct().map(|(p, _)| p).unwrap()));
        input.parse::<Token![::]>()?;
    }
    result.push(parse_full_qualified_id_prefix(&input)?);

    // Following segments
    while input.peek(Token![::]) {
        result.push(proc_macro2::TokenTree::Punct(input.cursor().punct().map(|(p, _)| p).unwrap()));
        input.parse::<Token![::]>()?;
        let id = input.cursor().ident().map(|(id, _)| id);
        input.parse::<Ident>()?;
        result.push(proc_macro2::TokenTree::Ident(id.unwrap()));
    }

    // Return result
    Ok(proc_macro2::TokenStream::from_iter(result))
}

It works for a simple id, but not for id_1::id_2::id_n. What am I doing wrong? I am getting an error spanning at the first colon in something like self::C.

Is there a particular reason you aren't parsing a Path instead of the individual Idents?

2 Likes

I was not aware of Path, I am not always proper with finding names

I have simplified the above function to:

fn parse_full_qualified_id(input: &ParseStream) -> Result<proc_macro2::TokenStream> {
    Ok(input.parse::<Path>()?.to_token_stream())
}

But I get in trouble with the < tokens. I am using them in:

entity_inherits!(B < A < Entity, use BComponent, EntityTypeError);

Path::parse_mod_style()


BTW, if you already went through the trouble of parsing into a strongly-typed Path, you shouldn't just convert it back to a raw TokenStream.

1 Like