在 Ruby 中,redo
关键字可用于返回循环的开头,而无需消耗输入。我想在 JavaScript 中对for...of
循环做同样的事情。
const scan = lexer => function* (string) {
let [token, table] = lexer;
for (const character of string) {
const next = table.get(character);
if (next) {
[token, table] = next.value;
} else if (token) {
yield token.value;
[token, table] = lexer;
// redo the current iteration without consuming input
} else {
throw new SyntaxError("Unexpected character", character);
}
}
if (token) yield token.value;
else throw new SyntaxError("Unexpected end of input");
}
通常,您只需不增加常规for
循环的索引即可执行此操作。但是,我必须使用for...of
循环,因为它循环遍历字符串的 Unicode 代码点,而常规for
循环将循环字符串的 UTF-16 代码单元。
如何在不重复代码的情况下返回到循环的开头?
只需使用内部循环:
for (const character of string) {
while(true) {
const next = table.get(character);
if (next) {
[token, table] = next.value;
break;
} else if (token) {
yield token.value;
[token, table] = lexer;
// don't break, redo
} else {
throw new SyntaxError("Unexpected character", character);
break;
}
}
}
要重新启动整个循环:
在您的情况下,它实际上非常简单:
yield* scan(lexer)(string);
return;
当然,如果您不想重新启动整个函数,请添加一个 IIFE 并回忆一下:
yield* (function redo*() {
//...
yield* redo();
return;
})();
如果您确实需要跳转,请使用标签(请不要(:
restart: while(true) {
// do stuff
continue restart;
//...
break;
}