0
votes

In ANTLR, for a given token, is there a way to tell which parser rule is matched?

For example, from the ANTLR grammar:

tokens
{
    ADD='Add';
    SUB='Sub';
}

fragment
ANYDIGIT    :   '0'..'9';

fragment
UCASECHAR   :   'A'..'Z';

fragment
LCASECHAR   :   'a'..'z';

fragment
DATEPART    :   ('0'..'1') (ANYDIGIT) '/' ('0'..'3') (ANYDIGIT) '/' (ANYDIGIT) (ANYDIGIT) (ANYDIGIT) (ANYDIGIT);

fragment
TIMEPART    :   ('0'..'2') (ANYDIGIT) ':' ('0'..'5') (ANYDIGIT) ':' ('0'..'5') (ANYDIGIT);

SPACE       :   ' ';

NEWLINE     :   '\r'? '\n';

TAB         :   '\t';

FORMFEED    :   '\f';

WS          :   (SPACE|NEWLINE|TAB|FORMFEED)+ {$channel=HIDDEN;};

IDENTIFIER  :   (LCASECHAR|UCASECHAR|'_') (LCASECHAR|UCASECHAR|ANYDIGIT|'_')*;

TIME        :   '\'' (TIMEPART) '\'';

DATE        :   '\'' (DATEPART) (' ' (TIMEPART))? '\'';

STRING      :   '\''! (.)* '\''!;

DOUBLE      :   (ANYDIGIT)+ '.' (ANYDIGIT)+;

INT         :   (ANYDIGIT)+;

literal     :   INT|DOUBLE|STRING|DATE|TIME;

var         :   IDENTIFIER;

param       :   literal|fcn_call|var;

fcn_name    :   ADD | 
                SUB | 
                DIVIDE | 
                MOD | 
                DTSECONDSBETWEEN | 
                DTGETCURRENTDATETIME |
                APPEND |
                STRINGTOFLOAT;

fcn_call    :   fcn_name WS? '('! WS? ( param WS? ( ','! WS? param)*)* ')'!;

expr        :   fcn_call WS? EOF;

And in Java:

  CommonTreeNodeStream nodes = new CommonTreeNodeStream(tree);
  nodes.reset();
  Object obj;
  while((obj = nodes.nextElement()) != null)
  {
      if(nodes.isEOF(obj))
      {
          break;
      }
      System.out.println(obj);
  }

So, what I want to know, at System.out.println(obj), did the node match the fcn_name rule, or did it match the var rule.

The reason being, I am trying to handle vars differently than fcn_names.

2

2 Answers

0
votes

No, you cannot get the name of a parser rule (at least, not without an ugly hack ).

But if tree is an instance of CommonTree, it means you've already invoked the expr rule of your parser, which means you already know expr matches first (which in its turn matches fcn_name).

On a related note, see: Get active Antlr rule

3
votes

Add this to your listener/visitor:

String[] ruleNames;
public void loadParser(gramParser parser) {  //get parser
    ruleNames = parser.getRuleNames(); //load parser rules from parser
}

Call loadParser() from wherever you create your listener/visitor, eg.:

MyParser parser = new MyParser(tokens);
MyListener listener = new MyListener(); 
listener.loadParser(parser);  //so we can access rule names

Then inside each rule you can get the name of the rule like this:

ruleName = ruleNames[ctx.getRuleIndex()];