It appears this can be done by providing a custom implementation of CharStream. However, we're running into an issue because the substring method is called. It is called from CommonToken.getText which is called by the generated parser. I thought maybe we could buffer back to the latest mark call, but it is not called at all.
So, is there either a straightforward way to determine how far back one has to buffer to handle future substring calls, or is there a way we can modify our lexer/parser grammar to get the string data in some way that doesn't involve the getText call, or that constructs the CommonToken using the constructor that takes a String instead of start/end pair?