ANTLR编译同名不同包多版本语法文件仅生成单版本问题咨询
ANTLR同名跨版本语法编译问题
场景说明
现有如下目录结构的ANTLR项目:
antlr-4.12.0-complete.jar generated-code/ grammars/ com/ example/ version1/ Grammar.g4 version2/ Grammar.g4
两个语法文件名称相同,但分属不同包、内容不同,目的是保留各版本解析器以实现向后兼容:
version1/Grammar.g4
grammar Grammar; @header { package com.example.version1; } start: 'abc'.*?'def';
version2/Grammar.g4
grammar Grammar; @header { package com.example.version2; } start: 'qrs'.*?'tuv';
执行编译命令
在grammars/目录下执行:
java -jar ../antlr-4.12.0-complete.jar -o ../generated-code ./com/example/version1/Grammar.g4 ./com/example/version2/Grammar.g4
异常结果
仅生成version1相关代码,未生成version2相关文件:
generated-code/ com/ example/ version1/ GrammarLexer.java GrammarParser.java ...
问题根源
排查发现ANTLR的Tool类中public List<GrammarRootAST> sortGrammarByTokenVocab(List<String> fileNames)方法存在逻辑问题:该方法仅按语法名称收集语法,导致传入两个文件名后,返回的AST列表仅保留一个元素,从而只编译了其中一个版本的语法。
可行方案分析
现有三种潜在解决办法,但仅一种可行:
- 修改语法文件名称:唯一可行方案
- 分两次执行编译工具:无法通过ANTLR Gradle插件轻松实现,且文件顺序不固定时会随机生成其中一个版本的代码,无法同时生成两个版本
- 编写兼容所有版本的语法:因语法由数千行自动生成的专有语法构成,且多年来变化巨大,无法合并
核心疑问
这种同名但分属不同包、内容不同的语法文件,单次传入ANTLR编译时仅生成一个版本代码的情况,属于ANTLR的Bug吗?还是说单次传入多个同名无关语法文件本身属于用户错误(若如此,ANTLR Gradle插件也存在同类问题)?
内容的提问来源于stack exchange,提问作者Sapo Enojado
相关产品推荐
相关产品推荐

