Aadit M Shah
Aadit M Shah

Reputation: 74234

How do I redo a for...of loop in JavaScript?

In Ruby, the redo keyword can be used to go back to the beginning of a loop without consuming input. I'd like to do the same with a for...of loop in JavaScript.

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");
}

Normally, you'd do this by simply not incrementing the index of a regular for loop. However, I have to use a for...of loop because it loops over the Unicode code points of the string, whereas the regular for loop would loop over the UTF-16 code units of the string.

How do I go back to the beginning of the loop without duplication of code?

Upvotes: 0

Views: 1049

Answers (1)

Jonas Wilms
Jonas Wilms

Reputation: 138487

Just use an inner loop:

 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;
    }
  }
}

To restart the whole loop:

In your case it's actually quite straightforward:

 yield* scan(lexer)(string);
 return;

For sure if you don't want to restart the whole function, add an IIFE and recall that:

 yield* (function redo*() {
   //...
  yield* redo();
  return;
})();

If you really need jumps, use labels (please don't):

 restart: while(true) {
  // do stuff
  continue restart;
  //...
  break;
}

Upvotes: 1

Related Questions