我是Rust的新手,甚至是宏引擎的新手,我正试图想出一种创建DSL的方法,我将用于HTML模板,如下所示,
h! {
foo(
"bar",
tag_with_parens(),
tag_without_parens,
"some other expression",
element(child),
),
"tags and strings can be siblings",
}
我玩了一下,但我不确定它是否可能
macro_rules! h {
// single idents and strings are matched here
($t:tt) => { h!($t(),) };
($t:tt( $($inner:tt),* )) => {h!($t($($inner),*),)};
($t:tt( $($inner:tt),* ), $($rest:tt),*) => {{
// recursion with the contents of the tag
h!($($inner),*);
// do something with the rest of the parameters
h!($($rest),*);
}};
}
在这个简单的例子中,我使用tt
,因为它匹配标识符和字符串文字,但是当括号后跟括号时它会中断,因为我认为它认为它是一个单独的标记。我得到error: no rules expected the token (
。另外,如果我不仅要支持传递字符串,而且要支持任何表达式,那么它必须是不同的
如果我让前一个工作起作用,那么下一步的额外信用分配将是可选属性作为第一个参数。 :)
h!(foo({ident="expr", bar}, "content"))
答案 0 :(得分:0)
使用当前的Rust宏系统,似乎无法实现这样的宏规则。
简化,所需规则听起来像:
输入是"literal"
和tag(elem)
形式的不同和混合模式的列表。
零个或多个文字"a","b" ...
可以与规则匹配:
( $(label:tt),* )
零个或多个tag(element)
可以与:
( $( $tag:ident ( $inner:tt ) ),* )
但是如何定义匹配不同结构化项目序列的规则?
这也是一个简单的规则(零个或多个literal
后跟零个或多个tag(element))
:
$( $literal:tt ),* $( $tag:ident ( $($inner:tt)* ) ),*
给出错误:
error: local ambiguity: multiple parsing options: built-in NTs tt ('literal') or ident ('tag').