gpt4 book ai didi

rust - 如何从我的宏中删除 'block' 的使用以使其更有用?

转载 作者:行者123 更新时间:2023-11-29 08:19:21 25 4
gpt4 key购买 nike

我编写了这个宏来将任意术语扩展到一个标记列表中进行解析,这让我可以这样做:

let q = query!({T::U32_(&foo.x)} > {T::U32(0)});
// [U32_(100), Greater, U32(0)]

let q = query!({T::U32_(&foo.x)} != {T::U32_(&bar)});
// [U32_(100), NotEqual, U32_(10)]

let q = query!(
({T::U32_(&foo.x)} > {T::U32(0)}) ||
(({T::U32_(&bar)} == {T::U32(1)}) && ({T::U32_(&bar)} <= {T::U32(10)}))
);
// [Left, U32_(100), Greater, U32(0), Right, Or, Left, Left, U32_(10),
// Equal, U32(1), Right, And, Left, U32_(10), LesserEquals, U32(10),
// Right, Right]

但是,我觉得语法很烦人;请注意每个枚举如何必须位于其自己的 { ... } block 中才能正确扩展为最终的 vec。我更喜欢这个:

let q = query!(T::U32_(&foo.x) > T::U32(0));

let q = query!(T::U32_(&foo.x) != T::U32_(&bar));

let q = query!(
(T::U32_(&foo.x) > T::U32(0)) ||
((T::U32_(&bar) == T::U32(1)) && (T::U32_(&bar) <= T::U32(10)))
);

我一整天都在阅读宏示例,试图弄清楚这一点,但我无法弄清楚是否存在允许我执行此操作的有效标记组合。

帮助!我该怎么做?

围栏上的完整宏代码:http://is.gd/VM71VQ

#![feature(trace_macros)]
#![allow(dead_code)]

#[derive(Debug)]
enum T<'a> {
Left,
Right,
Equal,
NotEqual,
And,
Or,
Greater,
Lesser,
GreaterEquals,
LesserEquals,
U32(u32),
U32_(&'a u32),
}

macro_rules! query(

// Expand an inner block into its tokens
( EXPAND_BLOCK $x:block ) => (vec!( $x ));

// Expand (
( ( ) => (vec!(T::Left));

// Expand )
( ) ) => (vec!( T::Right ));

// Expand &&
( && ) => (vec!( T::And ));

// Expand >
( > ) => (vec!( T::Greater ));

// Expand <
( < ) => (vec!( T::Lesser ));

// Expand >=
( >= ) => (vec!( T::GreaterEquals ));

// Expand >
( <= ) => (vec!( T::LesserEquals ));

// Expand ==
( == ) => (vec!( T::Equal ));

// Expand !=
( != ) => (vec!( T::NotEqual ));

// Expand ||
( || ) => (vec!( T::Or ));

// Expand ( ... ) into Left, query!(...), Right
(( $($ps:tt)* )) => {
{
let mut rtn:Vec<T> = Vec::new();
rtn.push(T::Left);
for item in query!($($ps)*).into_iter() {
rtn.push(item);
}
rtn.push(T::Right);
rtn
}
};

// Expand a syntax tree parent into it's immediate child elements
// ie. { ... } into query!(...)
({ $($ps:tt)* }) => {
query!(EXPAND_BLOCK { $($ps)* })
};

// Top level expansion into a query using syntax tree rules
($($ps:tt)*) => {
{
let mut rtn:Vec<T> = Vec::new();
$(
for item in query!($ps).into_iter() {
rtn.push(item);
}
)*
rtn
}
};
);

struct Expr {
x: u32
}

fn main() {
let foo = Expr { x: 100u32 };
let bar = 10;

// trace_macros!(true);

let q = query!({T::U32_(&foo.x)} > {T::U32(0)});
println!("{:?}", q);

let q = query!({T::U32_(&foo.x)} != {T::U32_(&bar)});
println!("{:?}", q);

let q = query!(
({T::U32_(&foo.x)} > {T::U32(0)}) ||
(({T::U32_(&bar)} == {T::U32(1)}) && ({T::U32_(&bar)} <= {T::U32(10)}))
);
println!("{:?}", q);
}

最佳答案

这似乎可行:

#![feature(trace_macros)]

#[derive(Debug)]
enum Item {
Value(u8),
LParen,
RParen,
And,
Or,
LessThan,
GreaterThan,
LessThanEqual,
Equal,
}

macro_rules! query0(
( ( $( $v:tt )* ) ) => ({
let mut result = vec![Item::LParen];
$( result.extend(query0!($v)) );*;
result.push(Item::RParen);
result
});
( || ) => ( vec![Item::Or] );
( && ) => ( vec![Item::And] );
( < ) => ( vec![Item::LessThan] );
( > ) => ( vec![Item::GreaterThan] );
( <= ) => ( vec![Item::LessThanEqual] );
( == ) => ( vec![Item::Equal] );
( $v:expr ) => ( vec![Item::Value($v)] );
);

macro_rules! query(
( $( $v:tt )* ) => ({
let mut result = vec![];
$( result.extend(query0!( $v )) );*;
result
});
);

fn main() {
//trace_macros!(true);

let a = query!(5);
println!("{:?}", a);

let b = query!((1 < 3) == 5);
println!("{:?}", b);

let c = query!((42 > 0) ||
((13 == 13) && (12 <= 99)));
println!("{:?}", c);
}

( playpen link )

让我知道哪些部分最有趣,我可以解释这些(在我睡了一会之后......^_^)。

关于rust - 如何从我的宏中删除 'block' 的使用以使其更有用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28804235/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com