[英]S-expression in Rust macro_rules
我正在編寫自己的語言編譯器,我想用我的宏將 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
}
您需要一個單獨的宏來解析 arguments。 試試這個代碼:
#[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
}
如果你想用宏創建類似 Lisp 的語言,請檢查這個項目: https://github.com/JunSuzukiJapan/macro-lisp
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.