public class Variable{
public static void checkVarNameLength(CParser.VarNameContext ctx){
if(15 > ctx.getTextLength()){
CStyleListener.addError(new StyleError(ctx.getText(), line, col));
}
}
}
public class MainListener{
public static ArrayList<StyleErrors> errors;
static{
errors = new ArrayList<StyleErrors();
}
@Overridepublic static void enterDirectDeclarator(CParser.DirectDeclaratorContext ctx) {Variable.checkVarNameLength(ctx);}
Start walking the tree using MainListener:
this.mainListener = new MainListener(tokens, 0); ParseTreeWalker.DEFAULT.walk(mainListener, tree);
2. Create separate listeners for each style group and combine @Override & method implementations into one class such as:
public class VariableListener{
public ArrayList<StyleErrors> errors;
public VariableListener () {
this.errors = new ArrayList<StyleErrors();
}
@Overridepublic static void enterDirectDeclarator(CParser.DirectDeclaratorContext ctx) {Variable.checkVarNameLength(ctx);}
public void checkVarNameLength(CParser.VarNameContext ctx){if(15 > ctx.getTextLength()){}this.errors.add(new StyleError(ctx.getText(), line, col));}
And for each listener walk the AST:
ParseTreeWalker walker = new ParseTreeWalker(); listeners.forEach(listener -> walker.walk(listener, tree));
I have seen that Tailor, a popular linter for Swift, uses this approach: https://github.com/sleekbyte/tailor/tree/master/src/main/java/com/sleekbyte/tailor/listeners
To do so, I see two options:
- Create classes for each style group and write methods to check each style rule - these methods would then be invoked through the tree walk in the CStyleListener i.e. all @ "overriding" would happen in CStyleListener.
2. Create separate listeners for each style group and combine @Override & method implementations into one class such as:
Is option 2 indeed noticeably slower? And is there a best-practice / recommended architecture for such implementations with ANTLR?
Am 26.08.2016 um 22:38 schrieb Gerald Rosenberg <gbrose...@gmail.com>:As an empirical point of comparison, I use an approach similar to your option 1. I have tested the performance difference between doing a single tree-walk, calling a context-type specific class for each node, versus performing multiple sequential walks, each walk only calling context classes for a subset of the nodes. With all relevant things being equal, the performance difference was not really measurable: well under 10ms (typically just 2 or 3ms) for parse trees of ~30K+ nodes and ~60 node types largely independent of the number of walks implemented.