I have a combined grammar where I need to provide for two identifier lexer rules. Both identifiers can be used at the same time. Identifier1 comes before Identifer2 in grammar.
First identifier is static, whereas second identifier rule changes on the basis of some flag.(Using predicate).
I want the second identifier to match in parser rules. But as both identifiers may match some common inputs, It does not fall on identifer2.
I have created small grammar to make it understandable. Grammar is as:
@lexer::members
{
private boolean flag;
public void setFlag(boolean flag)
{
this.flag = flag;
}
}
identifier1 :
ID1
;
identifier2 :
ID2
;
ID1 : (CHARS) *;
ID2 : (CHARS | ({flag}? '_'))* ;
fragment CHARS
:
('a' .. 'z')
;
If I try to match identifer2 rule as :
ANTLRStringStream in = new ANTLRStringStream("abcabde");
IdTestLexer lexer = new IdTestLexer(in);
lexer.setFlag(true);
CommonTokenStream tokens = new CommonTokenStream(lexer);
IdTestParser parser = new IdTestParser(tokens);
parser.identifier2();
It shows error: line 1:0 missing ID2 at 'abcabde'
ID1 : (CHARS) *;
ID2 : (CHARS | ({flag}? '_'))* ;
For ANTLR these two rules mean:
ID1
_
and flag == true
, it's ID2
Note that if flag == false
, ID2
will never be matched.
The two basic rules the Lexer follows are:
I believe your core issue is misunderstanding the difference between lexer and parser and their usage. The question you should ask yourself is: When should 'abcabde' be matched as ID1
and when as ID2
?
ID1
- then your grammar is correct as it is now.ID2
- then you should switch the two rules - but note that in such case ID1
will never be matched.flag
- then you need to modify the predicate according to your logic, just toggling the underscore isn't enough.