Keep in mind, I'm 37 years old and have smoked since I was 13
Lua (by design) doesn't provide termination guarantees or a good way to force an untrusted program to terminate. If you accept untrusted lua input, be prepared for your program to halt indefinitely.
Lua is great for semi-trusted input, AKA things you download from the internet, where you do a minimal amount of due diligence, but in case the code is actually malicious, you want to severely limit (but not completely eliminate) the harm it can do.
If you actually need Javascript-style completely untrusted input,, what you want is the Roblox fork called Luau[1].
For example, termination you can solve by unwinding the stack in efficiently polled safepoints. You need to take down the entire sandbox-capable Lua VM instance but you can.
If he says yes to changing his name you have my full support.
In other words antlr and truffle are a great fit. We even use this pairing for our example language simplelanguage.
Especially the Futamura projections. It's almost magic and very few people have even heard of them.
Here is one of the many: https://youtu.be/bf5pQVgux3c?si=S8Dm5d_GXYXgJtnY
If you go looking for more you will find many more marbles.