我无法使用声明性宏来处理 rust

问题描述 投票:0回答:1

我正在深入研究 Rust 宏,我想尝试一些东西,但我就是无法让它工作

macro_rules! expr_enum {
    (base($ch:expr)) => {
        {
            let expression = Enum::Base($ch);
            expression
        }
    };

    (not($inner:tt)) => {
        {
            let inner_expr = expr_enum!($inner);
            let pointer_inner = Box::new(inner_expr);
            Enum::Not(pointer_inner)
        }   
    };
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Enum {
    Base(char),
    Not(Box<Enum>),
    And(Vec<Enum>),
    Or(Vec<Enum>),
}

fn main() {
    let expr1:Enum = expr!(base('A'));
    let expr2:Enum = expr!(not(base('A')));

    println!("{:?}",expr1);
    println!("{:?}",expr2);
    println!("{:?}",expr3);
    println!("{:?}",expr4);
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Enum {
    Base(char),
    Not(Box<Enum>),}

fn main() {
    let expr1:Enum = expr!(base('A'));
    let expr2:Enum = expr!(not(base('A')));

    println!("{:?}",expr1);
    println!("{:?}",expr2);
}

我尝试观看一些视频,阅读编译器错误,观看大学演示,到处阅读一些在线信息,无论我做什么,都会出现一些错误。我让它只与底座一起工作,但是当我尝试实现时,甚至底座都没有下划线,并且有些东西不起作用。

我正在尝试成功创建一个声明性宏,它接受给定的内容并从 Enum 返回一个对象 我尝试使用不同的变量属性更改变量属性,例如 expr、tt、literal、item 以及可能的其他属性,但我就是无法使其工作。

rust macros macro-rules
1个回答
0
投票

你的第一个宏臂是正确的。您可以指定要匹配的标记,甚至可以添加括号,就像您所做的那样。

错误出在你的第二只手臂上。您试图将

not(base('A'))
之类的内容与
not($inner:tt)
相匹配,这是不正确的。原因是,
base('A')
根本就不是一个单独的
tt

解决你的问题的最原始的解决方案看起来像这样:

macro_rules! expr_enum {
    ( base ( $ch:expr ) ) => {{
        Enum::Base($ch)
    }};

    ( not ( $inner:tt ( $ch:expr ) ) ) => {{
        Enum::Not(
            Box::new(
                expr_enum!($inner($ch))
            )
        )
    }};
}

您必须明白

base(expr)
不是
tt
。它实际上是一个
tt tt expr tt
。每个标记都与
tt
匹配。

但是,由于您想要括号,您可以进一步指定它们:

tt ( expr )

现在,通过捕获第二个臂内的参数列表,您将能够以任意深度嵌套

not
指令。

macro_rules! expr_enum {
    ( base( $ch:expr ) ) => {{
        Enum::Base($ch)
    }};

    ( not ( $inner:tt ( $($args:tt)* ) ) ) => {{
        Enum::Not(
            Box::new(
                expr_enum!($inner($($args)*))
            )
        )
    }};
}

说明:

模式

not( $inner:tt ( $($args:tt)* ) )
将匹配具有带有任意参数的嵌套
not
指令的外部
inner
指令。之后,它将调用自身,但这一次,
inner
指令将成为外部指令,并且它会执行此操作,直到找到
base
指令。

一个例子可以更好地说明这一点:

  • not(base('A'))
    not
    关键字和
    (
    标记与宏模式的第一部分匹配。然后,嵌套的
    base
    关键字和后面的
    (
    标记将通过
    $inner:tt (
    进行匹配。然后,
    inner
    (又名
    base
    )内的任何内容都与
    $($args:tt)*
    匹配。此语法意味着零个或多个标记。最后,剩余的
    )
    标记被匹配。

  • not(not(not(base('A'))))
    :与第一个示例类似,但
    not
    指令嵌套得更深。第一个
    not(
    与宏模式的第一部分匹配。然后第二个
    not(
    $inner:tt (
    匹配。然后,第二个
    not
    中的任何内容都与
    $($args:tt)*
    匹配。最后,剩余的
    )
    标记被匹配。

第二个宏臂以

$inner($($args)*)
作为参数调用自身。对于
not(not(not(base('A'))))
,内部
not(not(base('A')))
将被传递。然后
not(base('A'))
,最后
base('A')
,完成递归。

© www.soinside.com 2019 - 2024. All rights reserved.