【问题标题】:S-expression in Rust macro_rulesRust 宏规则中的 S 表达式
【发布时间】:2020-05-08 02:19:56
【问题描述】:

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

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

#[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!($left)), OP::Add, Box::new(ast!($right)))
    };
    ($other:tt) => {
        Expression::from($other)
    };
}

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)); // error: expected expression, found `+`
              // ^ expected expression
}

【问题讨论】:

    标签: rust


    【解决方案1】:

    您需要一个单独的宏来解析参数。试试这个代码:

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

    游乐场链接:https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=e35fcd9aa7b126cd34aea6b33857e6c9

    如果您想使用宏创建类 Lisp 语言,请查看此项目:https://github.com/JunSuzukiJapan/macro-lisp

    【讨论】:

    • 感谢您的回答!您的代码运行良好!我有一个小问题,( ( $e:tt ) ) =&gt; (ast!($e));,这条线有必要吗?没有这个看起来很好。
    • 是的,你完全正确,第一条规则是不必要的,因为第二条规则涵盖了这种情况。
    猜你喜欢
    • 1970-01-01
    • 2013-03-15
    • 1970-01-01
    • 2014-09-26
    • 2018-03-02
    • 1970-01-01
    • 2014-04-18
    • 1970-01-01
    • 2016-03-16
    相关资源
    最近更新 更多