For asynchronous IO, we now have async-await in many modern languages. The feature pretty much solves IO related callback hell; the compiler builds these state machines automatically, and keeps them abstracted behind a nice API making code easy to read, write and debug.
I wish someone would invent an approach suitable for generic FSMs, not just for async IO. External code generators work when you have grammar or protocol state UML, but aren’t without their problems.