【发布时间】:2017-09-10 00:08:12
【问题描述】:
我正在尝试使用 Rust 的 macro_rules 并想制作一个可以解析类似 HTML 的语法并将 HTML 简单地作为字符串回显的宏。下面的宏得到了大部分的方式:
macro_rules! html {
() => ("");
($text:tt) => {{
format!("{}", $text)
}};
(<$open:ident>[$($children:tt)*]</$close:ident>$($rest:tt)*) => {{
format!("<{}>{}</{}>{}",
stringify!($open),
html!($($children)*),
stringify!($close),
html!($($rest)*))
}};
}
然后使用宏:
println!("{}",
html!(
<html>[
<head>[
<title>["Some Title"]</title>
]</head>
<body>[
<h1>["This is a header!"]</h1>
]</body>
]</html>
)
);
但是,我真的很想删除多余的开始和结束方括号。我尝试这样做:
macro_rules! html_test {
() => ("");
($text:tt) => {{
format!("{}", $text)
}};
(<$open:ident>$($children:tt)*</$close:ident>$($rest:tt)*) => {{
format!("<{}>{}</{}>{}",
stringify!($open),
html!($($children)*),
stringify!($close),
html!($($rest)*))
}};
}
但是,当我去使用这个宏时:
println!("{}",
html_test!(
<html>
<head>
<title>"Some Title"</title>
</head>
<body>
<h1>"This is a header!"</h1>
</body>
</html>
)
);
我收到error: local ambiguity: multiple parsing options: built-in NTs tt ('children') or 1 other option.
我知道此错误的一般解决方案是添加语法以消除大小写的歧义(例如添加方括号)。对于这个特定的例子,有没有其他方法可以解决这个问题?我知道使用过程宏将是一个极端的解决方案,但如果可能的话,我更愿意使用macro_rules。
我意识到使用宏来简单地获取包含 HTML 的字符串是多余的,但这仅仅是为了解决这个问题。潜在地,可以用宏做更多有趣的事情,例如调用函数来构建表示 HTML 结构的树。
【问题讨论】: