我正在尝试实现一个可以扩展brainfuck程序的宏(在从一些更简单的代码开始之后,我已经在提出解决方案时遇到了问题:How to parse single tokens in rust macros)。问题是在递归匹配的某个点它永远无法匹配结尾:
error: recursion limit reached while expanding the macro `brainfuck`
--> src/lib.rs:119:9
|
119 | brainfuck!(@impl cell; $($all_tokens)*);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
124 | brainfuck!(++++++++++[>+++++++>++++++++++>+++++++++++>+++>+<<<<<-]>++.>>+.---.<---.>>++.<+.++++++++.-------.<+++.>+.>+.>.);
| --------------------------------------------------------------------------------------------------------------------------- in this macro invocation
|
= help: consider adding a `#![recursion_limit="2000"]` attribute to your crate
这是宏代码:
#[macro_export]
macro_rules! brainfuck {
(@impl $var:ident;) => {};
(@impl $var:ident; + $($t:tt)*) => {
$var.inc();
brainfuck!(@impl $var; $($t)*);
};
(@impl $var:ident; - $($t:tt)*) => {
$var.dec();
brainfuck!(@impl $var; $($t)*);
};
(@impl $var:ident; > $($t:tt)*) => {
$var.next();
brainfuck!(@impl $var; $($t)*);
};
(@impl $var:ident; < $($t:tt)*) => {
$var.prev();
brainfuck!(@impl $var; $($t)*);
};
(@impl $var:ident; . $($t:tt)*) => {
$var.printVal();
brainfuck!(@impl $var; $($t)*);
};
(@impl $var:ident; , $($t:tt)*) => {
$var.getInput();
brainfuck!(@impl $var; $($t)*);
};
(@impl $var:ident; [$($t:tt)*] $($ts:tt)*) => {
while $var.getVal() != 0 {
brainfuck!(@impl $var; $($t)*);
}
brainfuck!(@impl $var; $($ts)*);
};
($($all_tokens:tt)*) => {
let mut cell = CellData::new();
brainfuck!(@impl cell; $($all_tokens)*);
};
}
它基于自定义的扩展方法struct
。完整的代码编译问题可以在这个操场上重现
我对这种匹配不是很自信:
(@impl $var:ident; [$($t:tt)*] $($ts:tt)*) => {
while $var.getVal() != 0 {
brainfuck!(@impl $var; $($t)*);
}
brainfuck!(@impl $var; $($ts)*);
};
我认为这[$($t:tt)*] $($ts:tt)*
是为了匹配包含[]
在里面的任何标记的代码部分,然后是任何标记。但我不确定它是否应该工作。
我已经处理这个问题一段时间了,我完全被困住了。欢迎任何形式的帮助。提前致谢!