But in practice, in my hobby projects, I've found it's trivially easy to skip this step and just operate directly on characters in the recursive-descent pass. And by doing so your code is simpler, and you avoid repeating a bit of work (for example: identifying the bounds of a number literal in one pass and then fully parsing it in another pass).
Is it more necessary in full-scale compilers? Is it an old-fashioned practice that people don't really do anymore? Or am I missing something?
There can also be performance advantages, at least in some cases.