use expression_core::expression::Expression;
use expression_core::parsing;
use proc_macro::TokenStream;
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use syn::{LitStr, parse_macro_input};
#[proc_macro]
pub fn expr(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as LitStr);
let expr_str = input.value();
let tokens = match parsing::tokenize(&expr_str) {
Ok(t) => t,
Err(e) => {
return syn::Error::new_spanned(&input, e).to_compile_error().into();
}
};
let mut parser = parsing::Parser::new(tokens);
let expr = match parser.parse_expression() {
Ok(expr) => expr,
Err(e) => {
return syn::Error::new_spanned(&input, e).to_compile_error().into();
}
};
expression_to_tokens(&expr).into()
}
fn expression_to_tokens(expr: &Expression) -> TokenStream2 {
match expr {
Expression::Number(n) => {
quote! { expression_core::expression::Expression::Number(#n) }
}
Expression::Variable(name) => {
quote! { expression_core::expression::Expression::Variable(#name.to_string()) }
}
Expression::Add(left, right) => {
let left_tokens = expression_to_tokens(left);
let right_tokens = expression_to_tokens(right);
quote! { expression_core::expression::Expression::Add(Box::new(#left_tokens), Box::new(#right_tokens)) }
}
Expression::Subtract(left, right) => {
let left_tokens = expression_to_tokens(left);
let right_tokens = expression_to_tokens(right);
quote! { expression_core::expression::Expression::Subtract(Box::new(#left_tokens), Box::new(#right_tokens)) }
}
Expression::Multiply(left, right) => {
let left_tokens = expression_to_tokens(left);
let right_tokens = expression_to_tokens(right);
quote! { expression_core::expression::Expression::Multiply(Box::new(#left_tokens), Box::new(#right_tokens)) }
}
Expression::Divide(left, right) => {
let left_tokens = expression_to_tokens(left);
let right_tokens = expression_to_tokens(right);
quote! { expression_core::expression::Expression::Divide(Box::new(#left_tokens), Box::new(#right_tokens)) }
}
Expression::Power(base, exponent) => {
let base_tokens = expression_to_tokens(base);
let exponent_tokens = expression_to_tokens(exponent);
quote! { expression_core::expression::Expression::Power(Box::new(#base_tokens), Box::new(#exponent_tokens)) }
}
Expression::Sin(inner) => {
let inner_tokens = expression_to_tokens(inner);
quote! { expression_core::expression::Expression::Sin(Box::new(#inner_tokens)) }
}
Expression::Cos(inner) => {
let inner_tokens = expression_to_tokens(inner);
quote! { expression_core::expression::Expression::Cos(Box::new(#inner_tokens)) }
}
Expression::Tan(inner) => {
let inner_tokens = expression_to_tokens(inner);
quote! { expression_core::expression::Expression::Tan(Box::new(#inner_tokens)) }
}
Expression::ArcSin(inner) => {
let inner_tokens = expression_to_tokens(inner);
quote! { expression_core::expression::Expression::ArcSin(Box::new(#inner_tokens)) }
}
Expression::ArcCos(inner) => {
let inner_tokens = expression_to_tokens(inner);
quote! { expression_core::expression::Expression::ArcCos(Box::new(#inner_tokens)) }
}
Expression::ArcTan(inner) => {
let inner_tokens = expression_to_tokens(inner);
quote! { expression_core::expression::Expression::ArcTan(Box::new(#inner_tokens)) }
}
}
}