规则参数和规则返回值; antlr4的替代方案是什么?

时间:2019-01-25 19:05:09

标签: java inheritance antlr antlr4 generic-programming

您可以指定参数并为规则返回值,如接受的答案here中所示。山姆·哈威尔(Sam Harwell)回答了已接受的答案:

  

请记住,每次使用此功能都将使过渡到ANTLR 4更加困难,在这种情况下,最好不要“禁止”使用用户指定的参数和语法中的返回值。

我猜测这样做的方法不是将其嵌入语法中,但是我不知道该怎么做(覆盖/重载我猜的方法?但是怎么做?)

这是一个虚拟语法:

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;

这是虚拟Dataset类的样子:

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);
    }
}

我的应用程序类:

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[]) {

    }

}

输入:

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;

预期结果:

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*/

问题是,如果我从testingBaseVisitor重载方法,则不会从超类的常规visit()中调用它们。

1 个答案:

答案 0 :(得分:0)

  1. 与其将数据集传递给语句,不如(和 可能更好)返回语句生成的值 数据集访问者的访问者。
  2. 应该在Tests类中实现testBaseBaseVisitor类的多个扩展,对于特定访问者返回的每种T类型,都应实现一个扩展。

Jakub Dziworski's example非常有用。它显示了如何解决这两个问题。