Rust宏规则中的S-表达式

Rust宏规则中的S-表达式,rust,Rust,我正在编写自己的语言编译器,我想用宏将AST描述为S表达式 下面是不起作用的最小示例代码 #[派生(调试,部分Q)] 发布枚举表达式{ BinOP(盒子,OP,盒子), 编号(f64), } #[派生(调试,部分Q)] 发布枚举操作{ 添加 } 宏规则!ast{ (+$left:tt$right:tt)=>{ 表达式::BinOP(Box::new(ast!($left)),OP::Add,Box::new(ast!($right))) }; ($其他:tt)=>{ 表达式::from($oth

我正在编写自己的语言编译器,我想用宏将AST描述为S表达式

下面是不起作用的最小示例代码

#[派生(调试,部分Q)]
发布枚举表达式{
BinOP(盒子,OP,盒子),
编号(f64),
}
#[派生(调试,部分Q)]
发布枚举操作{
添加
}
宏规则!ast{
(+$left:tt$right:tt)=>{
表达式::BinOP(Box::new(ast!($left)),OP::Add,Box::new(ast!($right)))
};
($其他:tt)=>{
表达式::from($other)
};
}
用于表达式的impl From{
fn from(u:usize)->Self{
表达式::编号(u为f64)
}
}
fn main(){
dbg!(ast!(+12));//这很有效。
dbg!(ast!(+(+3 4)2));//错误:应为表达式,已找到`+`
//^预期表达式
}

您需要一个单独的宏来解析参数。请尝试以下代码:

#[derive(Debug, PartialEq)]
pub enum Expression {
    BinOP(Box<Expression>, OP, Box<Expression>),
    Number(f64),
}

#[derive(Debug, PartialEq)]
pub enum OP {
    Add,
}

macro_rules! ast {
    (+ $left:tt $right:tt) => {
        Expression::BinOP(Box::new(ast_arg!($left)), OP::Add, Box::new(ast_arg!($right)))
    };
}

#[macro_export]
macro_rules! ast_arg {
    ( ( $e:tt ) ) => (ast!($e));
    ( ( $($e:tt)* ) ) => ( ast!( $($e)* ) );
    ($e:expr) => (Expression::from($e));
}

impl From<usize> for Expression {
    fn from(u: usize) -> Self {
        Expression::Number(u as f64)
    }
}

fn main() {
    dbg!(ast!(+ 1 2)); // this works
    dbg!(ast!(+ (+ 3 4) 2)); // also works now
}
#[派生(调试,部分Q)]
发布枚举表达式{
BinOP(盒子,OP,盒子),
编号(f64),
}
#[派生(调试,部分Q)]
发布枚举操作{
添加
}
宏规则!ast{
(+$left:tt$right:tt)=>{
表达式::BinOP(Box::new(ast_arg!($left)),OP::Add,Box::new(ast_arg!($right)))
};
}
#[宏_导出]
宏规则!阿斯特阿格{
($e:tt))=>(ast!($e));
($($e:tt)*)=>(ast!($($e)*);
($e:expr)=>(表达式::from($e));
}
用于表达式的impl From{
fn from(u:usize)->Self{
表达式::编号(u为f64)
}
}
fn main(){
dbg!(ast!(+12));//这很有效
dbg!(ast!(+(+34)2));//现在也可以工作了
}
游乐场连接:


如果您想用宏创建类似Lisp的语言,请检查此项目:

谢谢您的回答!你的代码运行良好!我有一个小问题,
($e:tt))=>(ast!($e)),是否需要此行?没有这个看起来很好。是的,你完全正确,第一条规则是不必要的,因为第二条规则涵盖了这种情况。