Reputation: 170
I am trying to implement a parser for a toy language.
I have already written the grammar, but when I try to create the AST from the CST I encounter a problem.
I define a class that inherits from MyParserVisitor<ASTNode>
where ASTNode
is a dummy class from which every class in my class estructure inherits.
Now, two of the rules of my grammar are as follows:
program:
funcDecl* expr
;
expr:
constant # constExpr
| identifier # idExpr
;
where funcDecl
, constant
and identifier
are terminal rules.
When I try to implement the visitor for program
, whenever I call the function visit
I have to cast the result to the correct type. For example:
@Override
public Program visitProgram(fopplParser.ProgramContext ctx){
// Rule: funcDecl* expr
List<FuncDecl> funcs = new LinkedList<FuncDecl>();
for(fopplParser.FuncDeclContext f : ctx.funcDecl())
funcs.add((FuncDecl) visit(f));
Expr expr = (Expr)visit(ctx.expr());
return new Program(funcs, expr);
}
Would it be possible to omit all those castings in some way? I feel like I am doing something incorrectly here.
In the case of the FuncDecl
, I could change that line to
funcs.add(visitFuncDecl(f));
and implement visitFuncDecl
with the following signature
pubic FuncDecl visitFuncDecl(fopplParser.FuncDeclContext ctx);
but I cannot do that with the expression, since there is not a visitExpr
function, but two functions, namely visitConstExpr
and visitIdExpr
.
Furthermore, if I have a rule such that
idList: identifier*
in this case I cannot return a List<Identifier>
. Should I create a class that is nothing but a wrapper for List<Identifier>
, or should I directly make my Visitor class inherit from MyParserVisitor<Object>
?
Upvotes: 0
Views: 4022
Reputation: 53337
I think you are confusing the meaning of the ANTLR visitor class and your intention of walking the parse tree. The ANTLR visitor class is meant for evaluations. It can be parameterized to return a given class as the result of visiting nodes (e.g. a mathematical value when you evaluate an expression). For walking the parse tree use a parse tree listener instead. You can then override the enterXXX and exitXXX functions and build your symbol table or whatever you like.
Upvotes: 2