Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why is this procedural macro interpreting this expression as a function?

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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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

>Solution :

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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading