why the intermediate exception?
I couldn't find a better way to propagate the exception. Throwing ParseException from the visitor can't be done, since the visitor is called from RuleContext.accept, which doesn't throw any exceptions.
I wouldn't want to catch a general IllegalArgumentException to convert it to ParseException, something unexpected inside visitor.visit could throw an IllegalArgumentException and I don't want to change the type of that.
Also, it looks like you are losing stack frames when creating a new exception from the intermediate.
Yes, unfortunately the ParseException doesn't support providing a cause in the constructor. I can add the cause by using: exception.initCause(e);. Attached new patch with this change and made the intermediate exception static