2014-10-31 161 views
2

我有以下的语法(简体):ANTLR - 遍历节点

filter : eq | and; 

eq  : 'eq' '(' property ',' value ')'; 

and  : 'and' '(' filter ',' filter (',' filter)* ')'; 

... 

我解析简单的前缀结构,如:

and(eq(name,john),eq(location,usa)) 

什么是最好的方式,依次通过filter节点一个and节点?生成的类AndContext有一个功能filter(int index),但仅此而已。我想要做的事,如:

AndContext c = ...; 

for (int i = 0; i < c.numberOfFilters(); ++i) { 
    FilterContext f = c.filter(i); 
} 

有功能getChildCount(),但它返回的所有节点的数量(包括代表()等终端节点),而不仅仅是有趣filter节点。

回答

1

比方说,你的语法如下:

grammar F; 

eq  : 'eq' '(' property ',' value ')'; 
and  : 'and' '(' filter ',' filter (',' filter)* ')'; 
filter : eq | and; 
property : 'name' | 'location'; 
value : 'john' | 'usa'; 

,那么你可以扩展生成FBaseListener并覆盖其enterAnd才能到FilterContext S:

public class Main { 

    public static void main(String[] args) throws Exception { 
     FLexer lexer = new FLexer(new ANTLRInputStream("and(eq(name,john),eq(location,usa))")); 
     FParser parser = new FParser(new CommonTokenStream(lexer)); 
     ParseTreeWalker.DEFAULT.walk(new AndListener(), parser.and()); 
    } 
} 

class AndListener extends FBaseListener { 

    @Override 
    public void enterAnd(@NotNull FParser.AndContext ctx) { 
     for (FParser.FilterContext filterContext : ctx.filter()) { 
      System.out.println("filterContext=" + filterContext.getText()); 
     } 
    } 
} 

,它将打印:

filterContext=eq(name,john) 
filterContext=eq(location,usa) 
+0

这个答案中的关键部分是除了在问题中提到的方法'AndContext.filter(int)'外,OP错过了'AndContext.filter()'的存在。 – 2014-10-31 15:01:21

+0

谢谢。我完全忽略了'filter()'函数。我认为只有一个'filter(int index)'函数。 – 2014-10-31 15:02:35

+0

FWIW,我没有使用walker/listener解析方式,因为我递归地将解析树转换为我的'pojo树'。 – 2014-10-31 15:03:54