Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi-character repetition separators not parseable #8

Open
durka opened this Issue Aug 14, 2018 · 5 comments

Comments

Projects
None yet
3 participants
@durka
Copy link

durka commented Aug 14, 2018

[Edit: problem has been identified, see next comment]


The macro below results in ParseError(None) from parse_str::<MacroRules>. Not very helpful. Is there any way to get more output?

macro_rules! unborrow {
    // =========================================================================================================
    // PRIVATE RULES

    // This rule fires when we have parsed all the arguments.
    // It just falls through to output stage.
    // (FIXME could fold the output rule into this one to reduce recursion)
    (@parse () -> ($names:tt $lets:tt) $($thru:tt)*) => {
        unborrow!(@out $names $lets $($thru)*)
    };

    // Parse an argument and continue parsing
    // This is the key rule, assigning a name for the argument and generating the let statement.
    (@parse ($arg:expr, $($rest:tt)*) -> ([$($names:ident),*] [$($lets:stmt);*]) $($thru:tt)*) => {
        unborrow!(@parse ($($rest)*) -> ([$($names,)* arg] [$($lets;)* let arg = $arg]) $($thru)*)
        //                                            ^                    ^
        // Right here an ident is created out of thin air using hygiene.
        // Every time the macro recurses, we get a new syntax context, so "arg" is actually a new identifier!
    };

    // Output stage for free functions.
    // Assembles the let statements and variable names into a block which computes the arguments,
    // calls the method, and returns its result.
    (@out [$($names:ident),*] [$($lets:stmt);*] ($($meth:ident)::+) $arg1:expr) => {{
        $($lets;)*
        $($meth)::+($arg1, $($names),*)
    }};
    
    // Output stage for object methods.
    (@out [$($names:ident),*] [$($lets:stmt);*] $($obj:ident).+) => {{
        $($lets;)*
        $($obj).+($($names),*)
    }};

    // =========================================================================================================
    // PUBLIC RULES

    // Macro entry point for object methods.
    ($($obj:ident).+ ($($args:expr),*)) => {
        unborrow!(@parse ($($args,)*) -> ([] []) $($obj).+)
        //                |               |  |   ^ info about the method call, saved for later
        //                |               |  ^ generated let statements
        //                |               ^ generated argument names
        //                ^ arguments to be parsed
    };

    // Macro entry point for free functions.
    ($($meth:ident)::+ ($arg1:expr, $($args:expr),*)) => {
        unborrow!(@parse ($($args,)*) -> ([] []) ($($meth)::+) $arg1)
    };
}
@lukaslueg

This comment has been minimized.

Copy link
Owner

lukaslueg commented Aug 14, 2018

Minimal example is

macro_rules! a {
    ($($m:ident)::+) => {};

}

The problem is the :: on the repetition. : works fine, foo is fine too, :: is flat out.

@durka

This comment has been minimized.

Copy link
Author

durka commented Aug 14, 2018

Likely related to #4 then?

@lukaslueg

This comment has been minimized.

Copy link
Owner

lukaslueg commented Aug 14, 2018

In a general sense, yes, yet I believe what we see here are the various intricacies of parsing rust's macro syntax. One will have to investigate.

@durka

This comment has been minimized.

Copy link
Author

durka commented Aug 14, 2018

My hunch is you ought to be allowing for a Separator to be simply a token, rather than a Punct (which can only be a single character). But I don't see a Token type in proc_macro2...

@durka durka changed the title Can't parse this macro Multi-character repetition separators not parseable Aug 14, 2018

@dtolnay

This comment has been minimized.

Copy link
Contributor

dtolnay commented Aug 14, 2018

There isn't a Token type in proc-macro2 or Syn because that is exclusively a macro_rules concept and neither crate is geared around manipulating macro_rules. There is no such thing as multi-character punctuation tokens like :: in the procedural macro token API.

It should be possible to define a parser for multi-character punctuation in this crate, as you have with all the other macro_rules parsing logic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.