Antlr4 parser integrated code handling at the pred

2019-08-19 18:38发布

问题:

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?

标签: antlr antlr4