ANTLR4如何设置sourceName:解决URL解析时Token源名返回unknown的问题
ANTLR4 设置输入源名称的实现方案
问题根因
你遇到的Token.getSourceName()返回"unknown"的问题,本质是创建CharStream时使用了不带源名称入参的重载方法。这类方法的内部实现会硬编码将"unknown"作为默认源名称存入CharStream实例,后续Lexer、Token读取来源名时就会拿到这个默认值。
本地文件解析时表现正常,是因为之前使用的CharStreams.fromFileName()系列方法,本身就会把文件路径作为sourceName传入,自然不会出现"unknown"问题。
官方标准实现
ANTLR4 没有在CharStream实例、Lexer类上提供公开的setSourceName()修改接口,在创建CharStream实例的阶段直接传入sourceName参数是官方设计的唯一标准入口,不需要额外写代理类包装现有对象。
具体替换CharStream创建逻辑的方式有两种,可按所用的ANTLR4版本选择:
- 4.7及以上版本可直接调用带sourceName参数的
fromStream重载,无需手动包装流,直接把URL的字符串形式作为sourceName传入即可:// 参数顺序:输入流、解码字符集、自定义sourceName CharStream charStream = CharStreams.fromStream( conn.getInputStream(), StandardCharsets.UTF_8, u.toString() ); - 如果使用的ANTLR4版本较低,没有上述
fromStream重载,可先将输入流包装为Reader,再调用带sourceName入参的fromReader重载,最终效果完全一致:Reader inputReader = new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8); CharStream charStream = CharStreams.fromReader(inputReader, u.toString());
替换后的完整代码参考
private parseDocument(URL u) { URLConnection conn = u.openConnection(); CharStream charStream = CharStreams.fromStream( conn.getInputStream(), StandardCharsets.UTF_8, u.toString() ); MyLexer lexer = new MyLexer(charStream); CommonTokenStream tokenstream = new CommonTokenStream(lexer); MyParser parser = new MyParser(tokenstream); MyParser.ParseContext pc = parser.parse(); // 原有后续逻辑保持不变 }
完成替换后,所有生成的Token调用getSourceName()就会返回传入的URL字符串,错误提示的来源辨识度问题即可解决。
内容的提问来源于stack exchange,提问作者queeg
相关产品推荐
相关产品推荐

