Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I differentiate between reserved words and variables using ANTLR?

Tags:

antlr

antlr3

I'm using ANTLR to tokenize a simple grammar, and need to differentiate between an ID:

ID              : LETTER (LETTER | DIGIT)* ;

fragment DIGIT  : '0'..'9' ;
fragment LETTER : 'a'..'z' | 'A'..'Z' ;

and a RESERVED_WORD:

RESERVED_WORD : 'class' | 'public' | 'static' | 'extends' | 'void' | 'int' | 'boolean' | 'if' | 'else' | 'while' | 'return' | 'null' | 'true' | 'false' | 'this' | 'new' | 'String' ;

Say I run the lexer on the input:

class abc

I receive two ID tokens for "class" and "abc", while I want "class" to be recognized as a RESERVED_WORD. How can I accomplish this?

like image 346
Chris Covert Avatar asked Mar 15 '12 19:03

Chris Covert


1 Answers

Whenever 2 (or more) rules match the same amount of characters, the one defined first will "win". So, if you define RESERVED_WORD before ID, like this:

RESERVED_WORD : 'class' | 'public' | 'static' | 'extends' | 'void' | 'int' | 'boolean' | 'if' | 'else' | 'while' | 'return' | 'null' | 'true' | 'false' | 'this' | 'new' | 'String' ;

ID              : LETTER (LETTER | DIGIT)* ;

fragment DIGIT  : '0'..'9' ;
fragment LETTER : 'a'..'z' | 'A'..'Z' ;

The input "class" will be tokenized as a RESERVED_WORD.

Note that it doesn't make a lot of sense to create a single token that matches any reserved word: usually it is done like this:

// ...

NULL  : 'null';
TRUE  : 'true';
FALSE : 'false;

// ...

ID              : LETTER (LETTER | DIGIT)* ;

fragment DIGIT  : '0'..'9' ;
fragment LETTER : 'a'..'z' | 'A'..'Z' ;

Now "false" will become a FALSE token, and "falser" an ID.

like image 154
Bart Kiers Avatar answered Nov 20 '22 07:11

Bart Kiers