【问题标题】:Why is this procedural macro interpreting this expression as a function?为什么这个过程宏将这个表达式解释为一个函数?
【发布时间】:2022-12-20 09:38:30
【问题描述】:

所以我当前的代码有一个过程宏,它将这个代数表达式解释为一个函数,这是错误

error: expected expression, found keyword `fn`
 --> src\main.rs:5:5
  |
5 |     symbolic!(x^2 + 2*x)
  |     ^^^^^^^^^^^^^^^^^^^^ expected expression
  |
= note: this error originates in the macro `symbolic` (in Nightly builds, run with -Z macro-backtrace for more info)

我尝试安装每晚构建并使用回溯运行但是......

> cargo run +nightly -Z macro-backtrace

5 |     symbolic!(x^2 + 2*x)
  |     ^^^^^^^^^^^^^^^^^^^^ expected expression
  = note: this error originates in the macro `symbolic` (in Nightly builds, run with -Z macro-backtrace for more info)

同样的错误关于这是什么的任何线索?我可能遗漏了一些关于生锈解释器的东西,但据我所知,这应该是作为一种表达来阅读的 这是我当前的宏代码:

use proc_macro::*;

#[proc_macro]
pub fn symbolic(body: TokenStream) -> TokenStream {
    // ---shunting yard---
    let mut stack : Vec<TokenTree> = vec![];
    let mut que : Vec<TokenTree> = vec![];

    shunting_yard(body, &mut stack, &mut que);
    println!(stringify!(output_que));
    "fn answer() -> u32 { 42 }".parse().unwrap()
}

fn shunting_yard(body: TokenStream, 
    stack: &mut Vec<TokenTree>,
    que: &mut Vec<TokenTree>,
) {
    for tt in body.into_iter(){
        match tt {
            TokenTree::Ident(_) => que.push(tt),
            TokenTree::Punct(_) => {
                while precedence(Some(&tt)) <= precedence(stack.last()){
                    if let Some(punct) = stack.pop() { que.push(punct); }
                }
                stack.push(tt)
            },
            TokenTree::Literal(_) => que.push(tt),
            TokenTree::Group(group) => shunting_yard(group.stream() , stack, que),
        }
    } while let Some(op) = stack.pop() {
        que.push(op);
    }
}

fn precedence(tt: Option<&TokenTree>) -> usize{
    if let Some(TokenTree::Punct(punct)) = tt{
        match punct.as_char() {
            '^' => 3,
            '/' | '*' => 2,
            '-' | '+' => 1,
            _ => 0
        }
    } else {
        0
    }
}

【问题讨论】:

  • 请放完整代码以使用宏。

标签: parsing rust macros rust-proc-macros


【解决方案1】:

这不是试图将任何东西解释为函数的宏。 您的宏会生成一个 fn 项目,因为您告诉它在这里生成一个项目:

"fn answer() -> u32 { 42 }".parse().unwrap()

因为你忽略了所有其他输入,所以写这个:

symbolic!{whatever garbage}

相当于这样写:

fn answer() -> u32 { 42 }

这在您尝试调用 symbolic 的上下文中似乎是非法的。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2013-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-04
相关资源
最近更新 更多