When you don't want to check for non-semantic rule such as comments / whitespace, you can throw them away with → skip but if you want to preserve them, you use channels.
Only lexer grammars can contain custom channels specifications
channels {
WHITESPACE_CHANNEL,
COMMENTS_CHANNEL
}
Those channels can then be used like enums within lexer rules:
WS : [ \r\t\n]+ -> channel(WHITESPACE_CHANNEL) ;