没有办法访问 GrammarRootAST
there's no way to visit a GrammarRootAST
多年来我一直在尝试创建一个实现 GrammarASTVisitor
.
的访问者
我正在 Grammar
object:
上加载语法规则
final Grammar g = Grammar.load("....dslGrammar.g4");
之后,我尝试使用我实现的 GrammarASTVisitor
接口访问语法的 AST
:
public class DSLGrammarVisitor implements GrammarASTVisitor {
@Override
public Object visit(GrammarAST node)
{
}
@Override
public Object visit(GrammarRootAST node)
{
return null;
}
@Override
public Object visit(RuleAST node)
{
return null;
}
@Override
public Object visit(BlockAST node)
{
return null;
}
@Override
public Object visit(OptionalBlockAST node)
{
return null;
}
@Override
public Object visit(PlusBlockAST node)
{
return null;
}
@Override
public Object visit(StarBlockAST node)
{
return null;
}
@Override
public Object visit(AltAST node)
{
return null;
}
@Override
public Object visit(NotAST node)
{
return null;
}
@Override
public Object visit(PredAST node)
{
return null;
}
@Override
public Object visit(RangeAST node)
{
return null;
}
@Override
public Object visit(SetAST node)
{
return null;
}
@Override
public Object visit(RuleRefAST node)
{
return null;
}
@Override
public Object visit(TerminalAST node)
{
return null;
}
}
因此,从文件加载语法后,我会:
GrammarASTVisitor v = new GrammarASTVisitorImpl();
g.ast.visit(v)
之后,执行visit(grammarRootAST)
方法。然而,我刚刚意识到我不太清楚到底如何访问 children。我不太明白 如何让 children AST 节点保持其类型。
我试过 node.getChildren()
,但是 returns 是 List<? extends Object>
,所以 GrammarASTVisitor
上没有 visit(Object)
方法实现 visit(Object)
.
我也尝试过 node.getChildrenAsArray()
,但是,每个项目都是一个 GrammarAST
节点,而不是 RuleAST
、SetAST
、TerminalAST
和等等...
有什么想法吗?
遗憾的是Java不支持双重调度。您必须手动覆盖 visit(GrammarAST node) ,它由节点的 class 切换并分派到适当的方法。实际上,他们应该给出一些抽象的 class 来执行此操作,但它不存在。
所以基本上类似于下面的代码(用 xtend 编写,但您可以将其转换为 java)应该可以解决问题:
GrammarASTVisitor() {
override visit(GrammarAST node) {
node.children?.forEach[
switch(it) {
case RuleAST: visit(it as RuleAST)
case BlockAST: visit(it as BlockAST)
case OptionalBlockAST: visit(it as OptionalBlockAST)
case PlusBlockAST: visit(it as PlusBlockAST)
case StarBlockAST: visit(it as StarBlockAST)
case AltAST: visit(it as AltAST)
case NotAST: visit(it as NotAST)
case PredAST: visit(it as PredAST)
case RangeAST: visit(it as RangeAST)
case SetAST: visit(it as SetAST)
case RuleRefAST: visit(it as RuleRefAST)
case TerminalAST: visit(it as TerminalAST)
default: visit(it as GrammarAST)
}
]
node
}
override visit(GrammarRootAST node) {
node.children?.forEach[this.visit(it as GrammarAST)]
node
}
...
多年来我一直在尝试创建一个实现 GrammarASTVisitor
.
我正在 Grammar
object:
final Grammar g = Grammar.load("....dslGrammar.g4");
之后,我尝试使用我实现的 GrammarASTVisitor
接口访问语法的 AST
:
public class DSLGrammarVisitor implements GrammarASTVisitor {
@Override
public Object visit(GrammarAST node)
{
}
@Override
public Object visit(GrammarRootAST node)
{
return null;
}
@Override
public Object visit(RuleAST node)
{
return null;
}
@Override
public Object visit(BlockAST node)
{
return null;
}
@Override
public Object visit(OptionalBlockAST node)
{
return null;
}
@Override
public Object visit(PlusBlockAST node)
{
return null;
}
@Override
public Object visit(StarBlockAST node)
{
return null;
}
@Override
public Object visit(AltAST node)
{
return null;
}
@Override
public Object visit(NotAST node)
{
return null;
}
@Override
public Object visit(PredAST node)
{
return null;
}
@Override
public Object visit(RangeAST node)
{
return null;
}
@Override
public Object visit(SetAST node)
{
return null;
}
@Override
public Object visit(RuleRefAST node)
{
return null;
}
@Override
public Object visit(TerminalAST node)
{
return null;
}
}
因此,从文件加载语法后,我会:
GrammarASTVisitor v = new GrammarASTVisitorImpl();
g.ast.visit(v)
之后,执行visit(grammarRootAST)
方法。然而,我刚刚意识到我不太清楚到底如何访问 children。我不太明白 如何让 children AST 节点保持其类型。
我试过 node.getChildren()
,但是 returns 是 List<? extends Object>
,所以 GrammarASTVisitor
上没有 visit(Object)
方法实现 visit(Object)
.
我也尝试过 node.getChildrenAsArray()
,但是,每个项目都是一个 GrammarAST
节点,而不是 RuleAST
、SetAST
、TerminalAST
和等等...
有什么想法吗?
遗憾的是Java不支持双重调度。您必须手动覆盖 visit(GrammarAST node) ,它由节点的 class 切换并分派到适当的方法。实际上,他们应该给出一些抽象的 class 来执行此操作,但它不存在。
所以基本上类似于下面的代码(用 xtend 编写,但您可以将其转换为 java)应该可以解决问题:
GrammarASTVisitor() {
override visit(GrammarAST node) {
node.children?.forEach[
switch(it) {
case RuleAST: visit(it as RuleAST)
case BlockAST: visit(it as BlockAST)
case OptionalBlockAST: visit(it as OptionalBlockAST)
case PlusBlockAST: visit(it as PlusBlockAST)
case StarBlockAST: visit(it as StarBlockAST)
case AltAST: visit(it as AltAST)
case NotAST: visit(it as NotAST)
case PredAST: visit(it as PredAST)
case RangeAST: visit(it as RangeAST)
case SetAST: visit(it as SetAST)
case RuleRefAST: visit(it as RuleRefAST)
case TerminalAST: visit(it as TerminalAST)
default: visit(it as GrammarAST)
}
]
node
}
override visit(GrammarRootAST node) {
node.children?.forEach[this.visit(it as GrammarAST)]
node
}
...