如何正确实现 ANTLR4 访问者
How to correctly implement an ANTLR4 visitor
我正在尝试为玩具语言实现解析器。
我已经写好了语法,但是当我尝试从 CST 创建 AST 时遇到了问题。
我定义了一个继承自 MyParserVisitor<ASTNode>
的 class,其中 ASTNode
是一个虚拟 class,我的 class 中的每个 class结构继承。
现在,我的两个语法规则如下:
program:
funcDecl* expr
;
expr:
constant # constExpr
| identifier # idExpr
;
其中 funcDecl
、constant
和 identifier
是终端规则。
当我尝试为 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));
并使用以下签名实现 visitFuncDecl
pubic FuncDecl visitFuncDecl(fopplParser.FuncDeclContext ctx);
但我不能用表达式来做到这一点,因为没有 visitExpr
函数,而是两个函数,即 visitConstExpr
和 visitIdExpr
.
此外,如果我有这样的规则
idList: identifier*
在这种情况下,我不能 return a List<Identifier>
。我应该创建一个 class 只是 List<Identifier>
的包装器,还是应该直接让我的访客 class 继承自 MyParserVisitor<Object>
?
我认为您混淆了 ANTLR 访问者 class 的含义和您遍历解析树的意图。 ANTLR 访问者 class 用于评估。它可以参数化为 return 给定的 class 作为访问节点的结果(例如,计算表达式时的数学值)。要遍历解析树,请改用解析树侦听器。然后您可以覆盖 enterXXX 和 exitXXX 函数并构建您的符号 table 或任何您喜欢的符号。
我正在尝试为玩具语言实现解析器。
我已经写好了语法,但是当我尝试从 CST 创建 AST 时遇到了问题。
我定义了一个继承自 MyParserVisitor<ASTNode>
的 class,其中 ASTNode
是一个虚拟 class,我的 class 中的每个 class结构继承。
现在,我的两个语法规则如下:
program:
funcDecl* expr
;
expr:
constant # constExpr
| identifier # idExpr
;
其中 funcDecl
、constant
和 identifier
是终端规则。
当我尝试为 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));
并使用以下签名实现 visitFuncDecl
pubic FuncDecl visitFuncDecl(fopplParser.FuncDeclContext ctx);
但我不能用表达式来做到这一点,因为没有 visitExpr
函数,而是两个函数,即 visitConstExpr
和 visitIdExpr
.
此外,如果我有这样的规则
idList: identifier*
在这种情况下,我不能 return a List<Identifier>
。我应该创建一个 class 只是 List<Identifier>
的包装器,还是应该直接让我的访客 class 继承自 MyParserVisitor<Object>
?
我认为您混淆了 ANTLR 访问者 class 的含义和您遍历解析树的意图。 ANTLR 访问者 class 用于评估。它可以参数化为 return 给定的 class 作为访问节点的结果(例如,计算表达式时的数学值)。要遍历解析树,请改用解析树侦听器。然后您可以覆盖 enterXXX 和 exitXXX 函数并构建您的符号 table 或任何您喜欢的符号。