Nora
Nora

Reputation: 21

Using multiple lexer commands on one lexer rule in Antlr

I'm trying to use more than one lexer command on a lexer rule. My code looks something like that:

LEXER_RULE: something->mode(NUMBER);

mode NUMBER;
NU: [0-9]+ ->mode(ANOTHER_MODE); //Going into another mode in case the NU rule is used

//now leaving the NUMBER mode, in case there is no number written

NO_NUM: ~[0-9]->mode(DEFAULT_MODE);

The lexer rule NU is only optional, so I have to cover the case that it is not used. However, I would also like to skip everything that is inside NO_NUM. Something like

NO_NUM:~[0-9]->skip ->mode(DEFAULT_MODE);

I know that I am not allowed to use more than one lexer command on one lexer rule. Does anyone know any other approach? I need to be able to leave the mode somehow. Btw I am not allowed to use semantic predicates. Thanks!

Upvotes: 1

Views: 223

Answers (1)

Bart Kiers
Bart Kiers

Reputation: 170308

You were almost there! Use a comma insetad:

NO_NUM : ~[0-9] -> skip, mode(DEFAULT_MODE);

This, obviously, discards anything that ~[0-9] matches. So, if you have this grammar:

ID : [a-zA-Z]+;
...

mode NUMBER;
  NU.    : [0-9]+ -> mode(ANOTHER_MODE);
  NO_NUM : ~[0-9] -> skip, mode(DEFAULT_MODE);

mode ANOTHER_MODE;
  ...

And in mode NUMBER you encounter abc, then a is discarded, and bc will be made into an ID. If you also want the a to be part of the ID, then you need to do this:

ID : [a-zA-Z]+;
...

mode NUMBER;
  NU.    : [0-9]+ -> mode(ANOTHER_MODE);
  NO_NUM : ~[0-9] -> more, mode(DEFAULT_MODE);

mode ANOTHER_MODE;
  ...

More about Lexer Command: https://github.com/antlr/antlr4/blob/master/doc/lexer-rules.md#lexer-commands

Upvotes: 1

Related Questions