3

ANTLR 解析器生成以下生成的代码:

protected TreeAdaptor adaptor = new CommonTreeAdaptor();

我已经实现了自己的 TreeAdaptor,并且我希望解析器始终使用我的并且从不使用 CommonTreeAdaptor()。我发现的唯一方法是每次创建新解析器时将其设置在调用代码中:

Parser parser = new MyParser();
parser.setTreeAdaptor(new MyAdaptor());

有什么方法可以设置默认的 TreeAdaptor 或将一些初始化代码附加到生成的构造函数中?

4

2 回答 2

2

有什么方法可以设置默认的 TreeAdaptor 或将一些初始化代码附加到生成的构造函数中?

一种方法是添加一个设置自定义树适配器的静态方法:

grammar T;

options {
  output=AST;
  ASTLabelType=CommonTree;
}

@parser::members {

  public static TParser newTParser(TreeNodeStream input) {
    TParser parser = new TParser(input);
    parser.setTreeAdaptor(new MyAdaptor());
    return parser;
  }
}

parse
 : Any* EOF
 ;

Any
 : .
 ;

然后你可以替换:

TParser parser = new TParser(input);

TParser parser = TParser.newTParser(input);
于 2012-06-25T17:46:57.593 回答
0

我想我找到了比 Bart 的命名构造方法更好的解决方案。

我无法直接修改生成的构造函数(包括将其设为私有,这就是我不喜欢命名构造函数解决方案的原因)。但是,我可以引入一个初始化块:

grammar T;

options {
  output=AST;
  ASTLabelType=CommonTree;
}

@parser::members {
    {
        this.adaptor = new MyAdaptor();
    }
}

根据Java 文档,“Java 编译器将初始化程序块复制到每个构造函数中。因此,这种方法可用于在多个构造函数之间共享代码块。”

所以this.adaptor将首先new CommonTreeAdaptor()由生成的代码设置,然后new MyAdaptor()由我的初始化块设置。测试证实这是实际发生的情况。

这个解决方案的优点是我的解析器的调用者不需要知道它正在使用自定义 TreeAdaptor 或做任何不寻常的事情(我的适配器是 CommonTreeAdaptor 的子类,所以任何依赖它的代码都可以)。

于 2012-07-11T16:10:31.503 回答