ANTLR4 返回值及传参的几种方式
写在之前
我们已经熟知了ANTLR4的Listener以及Visitor模式。
虽然我们用java来编写应用程序,但是我们想将语法文件和应用文件解耦合出来,因此暂时不用内嵌动作
。
接下来我们会介绍三种方式:带标签的Visitor模式
(java自带函数栈)、自定义的栈
、ANTLR4辅助数据结构ParseTreeProperty
。
标签的Visitor
这种模式我们之前介绍过,会省略中间的介绍。
语法文件
三种方法对应的语法文件都是统一的,后面不会重复列举。
类似于一个只会乘法和加法的计算器。
grammar LExpr;
s
: e
;
e
: e MULT e #Mult
| e ADD e #Add
| INT #Int
;
CLEAR : '!' ;
MULT : '*' ; // assigns token name to '*' used above in grammar
DIV : '/' ;
ADD : '+' ;
SUB : '-' ;
ID : [a-zA-Z]+ ; // match identifiers
INT : [0-9]+ ; // match integers
NEWLINE:'\r'? '\n' ; // return newlines to parser (is end-statement signal)
WS : [ \t]+ -> skip ; // toss out whitespace
自定义Visitor
可以看到,EvalVisitor继承了泛型
LExprBaseVisitor,类型为Integer。
这导致了后续visit的函数返回值类型
都是Int,这个举措有好有坏。好处是我们终于可以设置每个树结点的返回值
了,坏处是返回值类型被
同一
,而且没办法传参
。
还有一个问题是,非叶子结点
如果需要访问子结点,必须要显式
地要用visit。
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.*;
public class TestEvalVisitor{
public static class EvalVisitor extends LExprBaseVisitor<Integer>{
public Integer visitMult(LExprParser.MultContext ctx