I have some rules like this
@parser::header
{
import com.almondtools.antlr4multichannel.MultiChannelTokenStream;
}
@parser::members
{
private static final int HIDDEN = Token.HIDDEN_CHANNEL;
public void enableWs() {
((MultiChannelTokenStream) _input).enable(HIDDEN);
}
public void disableWs() {
((MultiChannelTokenStream) _input).disable(HIDDEN);
}
}
expression
: functionCallNoParen
| chain
;
functionCallNoParen
: chain {enableWs();} Whitespace {disableWs();} expression
;
chain
: chainBase memberAccess* {disableWs();}
| constant
;
memberAccess
: '.' identifier functionCallInsideMember?
;
chainBase
: identifier {enableWs();} ('::' identifier)* functionCallInsideMember?
| '(' expression ')'
;
functionCallInsideMember
: '(' {disableWs();} expression? CloseRoundBracket {enableWs();}
;
constant
: Decimal
;
identifier
: VarName
;
// Lexer
Whitespace: [ \t\r\u000B\f\b]+ -> channel(HIDDEN);
OpenRoundBracket: '(';
CloseRoundBracket: ')';
Decimal: Digit+;
fragment Digit: [0-9];
VarName: [a-zA-Z] [a-zA-Z0-9]*;
Where I use some control over HIDDEN tokens with this TokenStream https://stackoverflow.com/a/29115489/11630974
The problem is my parser can parse abc (123).qwe
properly as (functionCallNoParen (chain (chainBase (identifier abc))) (expression (chain (chainBase ( (expression (chain (constant 123))) )) (memberAccess . (identifier qwe)))))
if I specify start rule as functionCallNoParen
.
But If I use expression
, antlr4's adaptivePredict don't execute {enableWs();} code I guess, so it tries to find whitespace inside DEFAULT_CHANNEL and then choosing second alternative just as (expression (chain (chainBase (identifier abc))))
.
Is my assumption right? And if yes, do I need to override some core prediction functions or is there some better solutions?