首页 > 解决方案 > 规则参数和规则返回值;antlr4 中的替代方案是什么?

问题描述

您可以为规则指定参数和返回值,如在这里接受的答案中所示。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;

这是虚拟数据集类的样子:

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() 调用。

标签: javainheritanceantlrantlr4generic-programming

解决方案


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

Jakub Dziworski 的例子很有帮助。它显示了如何解决这两个问题。


推荐阅读