Home > other >  Why is this procedural macro interpreting this expression as a function?
Why is this procedural macro interpreting this expression as a function?

Time:12-06

So my current code has a procedural macro that is interpreting this algebraic expression as a function this is the error

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)

I tried to install the nightly build and ran with the backtrace but ...

> 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)

same error any clues as to what this is? I may be missing something about rusts interpreter but as far as I can tell this should be reading this as an expression this is my current code for the macro:

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
    }
}

CodePudding user response:

It's not the macro trying to interpret anything as function. Your macro produces a fn item because you tell it to produce one here:

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

Since you ignore all other input writing this:

symbolic!{whatever garbage}

is equivalent to writing this:

fn answer() -> u32 { 42 }

which seems to be illegal in the context you're trying to call symbolic.

  • Related