如何用Python中ANTLR生成的Java8词法/解析器获取变量类型?
获取ANTLR Token类型并提取Java变量类型
一、直接获取Token的类型信息
在Python的ANTLR环境中,每个生成的Token实例自带type属性,这是一个对应词法规则编号的整数。如果需要可读的类型名称,可通过生成的词法分析器类的symbolicNames数组转换。
示例代码:
from antlr4 import FileStream, CommonTokenStream from Java8Lexer import Java8Lexer # 读取目标Java文件 input_stream = FileStream("test.java") lexer = Java8Lexer(input_stream) token_stream = CommonTokenStream(lexer) # 填充Token流 token_stream.fill() # 遍历Token并输出类型信息 for token in token_stream.getTokens(): token_type_num = token.type # 排除EOF标记(type为-1) if token_type_num != -1: token_type_name = Java8Lexer.symbolicNames[token_type_num] print(f"Token文本: {token.text}, 类型编号: {token_type_num}, 类型名称: {token_type_name}")
二、提取Java变量类型的可靠方式
单纯遍历Token无法准确识别变量类型(类型需结合语法上下文,比如区分变量类型与方法返回值类型),更稳妥的方式是使用ANTLR的**监听器(Listener)或访问者(Visitor)**模式,直接从语法规则的上下文节点中提取信息。
方法1:使用监听器
自定义监听器继承自动生成的Java8BaseListener,重写对应语法规则的方法,比如针对变量声明的variableDeclaration规则:
from antlr4 import FileStream, CommonTokenStream, ParseTreeWalker from Java8Lexer import Java8Lexer from Java8Parser import Java8Parser from Java8BaseListener import Java8BaseListener class VariableTypeListener(Java8BaseListener): def enterVariableDeclaration(self, ctx: Java8Parser.VariableDeclarationContext): # 获取类型节点并提取文本 type_text = ctx.typeType().getText() print(f"变量类型: {type_text}") # 初始化语法分析流程 input_stream = FileStream("test.java") lexer = Java8Lexer(input_stream) token_stream = CommonTokenStream(lexer) parser = Java8Parser(token_stream) tree = parser.compilationUnit() # 遍历语法树触发监听器 walker = ParseTreeWalker() walker.walk(VariableTypeListener(), tree)
方法2:使用访问者
如果需要更灵活的流程控制(比如返回结果、跳过特定节点),可使用访问者模式,继承Java8BaseVisitor并重写对应方法:
from antlr4 import FileStream, CommonTokenStream from Java8Lexer import Java8Lexer from Java8Parser import Java8Parser from Java8BaseVisitor import Java8BaseVisitor class VariableTypeVisitor(Java8BaseVisitor): def visitVariableDeclaration(self, ctx: Java8Parser.VariableDeclarationContext): type_text = ctx.typeType().getText() print(f"变量类型: {type_text}") # 继续访问子节点 return self.visitChildren(ctx) # 初始化语法分析流程 input_stream = FileStream("test.java") lexer = Java8Lexer(input_stream) token_stream = CommonTokenStream(lexer) parser = Java8Parser(token_stream) tree = parser.compilationUnit() # 遍历语法树 visitor = VariableTypeVisitor() visitor.visit(tree)
注意事项
- 确保生成的ANTLR类(Java8Lexer、Java8Parser等)名称与实际生成文件一致,名称可能随ANTLR命令参数变化。
- 对于泛型类型(如
List<String>),getText()会直接返回完整的类型文本,无需额外处理。 - 若需区分局部变量、成员变量、方法参数的类型,可对应重写
localVariableDeclaration、fieldDeclaration、formalParameter等规则的方法。
内容的提问来源于stack exchange,提问作者saman Esmaeili
相关产品推荐
相关产品推荐

