0

You can specify parameters and return values for rules as shown in accepted answer here. Sam Harwell replies to accepted answer:

Keep in mind that every use of this feature will make transitioning to ANTLR 4 more difficult, where the use of user-specified arguments and return values in the grammar is "discouraged" at best.

I am guessing way of doing it is not embedding it in the grammar, but I can't figure out how to do it (overriding/overloading the methods I guess? but how??)

This is a dummy grammar:

grammar testing;
@header{package testing;}

program: dataset+;
dataset: ID ds_options* ';';
ds_options
    : (NEW|DROP) ID+ #newdrop
    | RENAME ID      #rename
    ;
DROP: 'drop';
NEW: 'new';
RENAME: 'rename';
ID: [A-Z0-9]+;
WS: [ \r\t\u000C\n]+ -> skip;

this is how dummy Dataset class looks like:

package testing;

import java.util.ArrayList;

public class Dataset {
    public String name;
    public ArrayList<String> dropList;

    public Dataset(String name) {
        this.name = name;
        dropList = new ArrayList<String>();
    }

    public void addDropVar(String var) {
        dropList.add(var);
    }
}

My application class:

package testing;

import java.util.ArrayList;
import testing.testingParser.DatasetContext;
import testing.testingParser.NewdropContext;
import testing.testingParser.RenameContext;


public class Testing {
    ArrayList<Dataset> datasets = new ArrayList<Dataset>();
    public static class MyVisitor<T> extends testingBaseVisitor<T>{
        @Override
        public T visitDataset(DatasetContext ctx) {
            return super.visitDataset(ctx);
        }

        @Override
        public T visitNewdrop(NewdropContext ctx) {
            // TODO Auto-generated method stub
            return super.visitNewdrop(ctx);
        }

        @Override
        public T visitRename(RenameContext ctx) {
            // TODO Auto-generated method stub
            return super.visitRename(ctx);
        }
    }

    public static void main(String args[]) {

    }

}

input:

TEST0 new A B C D E F G H; 
TEST0 drop A B C new U;
TEST1 drop J K;
TEST1 rename TEST88;
TEST0 new E F;
TEST0;
TEST1;
TEST1;
TEST1 new A B;
TEST0;
TEST0 new A B X Y drop B C D Q R;
TEST1 rename TEST3;

expected result:

TEST0 new A B C D E F G H; /*called TEST0 new dataset with vars A to H*/
TEST0 drop A B C new U; /*A B C removed from TEST0, U created in TEST0*/
TEST1 drop J K; /*does nothing because TEST1 hasn't been created*/
TEST1 rename TEST88; /*does nothing*/
TEST0 new E F; /*does nothing these already exist in this dataset*/
TEST0;
TEST1;
TEST1;
TEST1 new A B; /*TEST1 created with vars A B*/
TEST0;
TEST0 new A B X Y drop B C D Q R; /*A B X Y created in TEST0, B C D Q R deleted from TEST0*/
TEST1 rename TEST3; /*TEST1 renamed to TEST3*/

/*I should have TEST3 with vars A B and TEST1 with vars A E-H U X Y*/

Problem is that if I overload methods from testingBaseVisitor they won't get called from general visit() in the super-class.

1 Answers1

0
  1. Instead of passing the dataset to the statement, it's easier (and probably better) to return the value generated by the statement visitor to the dataset visitor.
  2. Multiple extensions of class testingBaseVisitor should be implemented in class Testing, one for each T type returned by the specific visitor.

Jakub Dziworski's example is very helpful. It shows how to solve both problems.