简体   繁体   中英

Why cant rust macro_rules! pat be followed by "<"?

In L-System notation a pattern would look something like this:

A(a)<A(x)>B(b, c) if a+b+c < 10 => B(a+b, a+c)A(x+a+b+c)

I'm trying to write rust macros to expand these. So I have something like this:

macro_rules! test {
    ($lc:pat < $a:pat > $rc:pat) => { ... };
}

But it won't let me. It says:

error: `$a:pat` is followed by `>`, which is not allowed for `pat` fragments
 --> src/main.rs:7:23
  |
7 |     ($lc:pat < $a:pat > $rc:pat) => { log_syntax!($lc); log_syntax!($a); log_syntax!($rc); };
  |                       ^ not allowed after `pat` fragments
  |
  = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`

Why aren't these allowed after the pat type? What can I match against to get this?

I can't use tt because apparently parenthesis aren't allowed for that.

Tokens fed into a macro_rules macro have been emitted by the Rust lexer; the same lexer that is part of the Rust parser. The lexer permits many sequences of tokens that are not valid Rust which, when parsing normal Rust code, would be caught by grammar rules down the pipeline. However, the lexer is aware of some level of context, for example it can distinguish things like << (left shift operator) from << (the start of nested type parameters), based on whether it is processing a type or an expression.

In many cases macros can match token streams that are not valid Rust, but the implementation errs on the side of caution to forbid many combinations that the lexer might happily emit. The reason for this is to allow the language developers some flexibility to do things like adding new syntax without breaking existing macros. The line might seem fairly arbitrary, and is partly due to history - how the language developed and the macros that people published early on - but the line had to be drawn somewhere.

We are guaranteed forwards-compatibility in macros that ingest valid Rust code (as well as a many that ingest invalid Rust code) for the price of disallowing a lot creative applications. It's possible for the rules to be gradually relaxed over time, as the language and compiler become more and more stable, but I imagine that will happen slowly, if at all.

Your macro matches input which is not valid Rust: a pattern never can appear between < and > . Unfortunately, it is also not permitted in macros and you may have to just pick different syntax.

Procedural macros have fewer restrictions and could also be an option.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM