2016-12-13 101 views
0

我正在尝试为玩具语言实现解析器。如何正确实现ANTLR4访问者

我已经写过语法,但是当我尝试从CST创建AST时遇到问题。

我定义了一个继承自MyParserVisitor<ASTNode>的类,其中ASTNode是一个虚拟类,我的类中的每个类都继承了这个类。现在

,是我的两个语法规则如下:

program: 
    funcDecl* expr 
; 
expr: 
    constant          # constExpr 
| identifier         # idExpr 
; 

其中funcDeclconstantidentifier是终端规则。

当我尝试实现program的访问者时,无论何时调用函数visit,都必须将结果转换为正确的类型。例如:

@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); 
} 

这将有可能省去在某种程度上所有这些铸件?我觉得我在这里做错了一些事情。

FuncDecl的情况下,我可能这条线变为 funcs.add(visitFuncDecl(f)); 并具有以下签名 pubic FuncDecl visitFuncDecl(fopplParser.FuncDeclContext ctx); 实施visitFuncDecl但我不能做到这一点与表达,因为没有一个visitExpr功能,但两种功能,即visitConstExprvisitIdExpr

而且,如果我有这样的,在这种情况下 idList: identifier* 我不能返回List<Identifier>的规则。我是否应该创建一个仅仅是List<Identifier>的包装的类,还是应该直接让我的访问者类继承MyParserVisitor<Object>

回答

1

我认为你会混淆ANTLR访问者类的含义和你走分析树的意图。 ANTLR访问者类用于评估。它可以被参数化为返回给定的类作为访问节点的结果(例如,当您评估表达式时的数学值)。对于漫游解析树,请改为使用分析树侦听器。然后,您可以重写enterXXX和exitXXX函数并构建您的符号表或任何您喜欢的东西。