antlr - 遍历节点

时间:2014-10-31 14:40:07

标签: antlr antlr4

我有以下语法(简化):

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(),但它返回所有节点的计数(包括代表()等的终端节点),而不仅仅是有趣的{{ 1}}节点。

1 个答案:

答案 0 :(得分:2)

让我们说你的语法是这样的:

grammar F;

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

然后您可以扩展生成的FBaseListener并覆盖其enterAnd以转到FilterContext

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)