考虑如下目录结构中的两个 ANTLR 语法:
antlr-4.12.0-complete.jar
generated-code/
grammars/
com/
example/
version1/
Grammar.g4
version2/
Grammar.g4
想法是为语法的每个版本保留一个解析器以实现向后兼容性。语法具有相同的名称,但并不完全相同并且在不同的包中:
Grammar.g4 (version 1)
----------------------
grammar Grammar;
@header {
package com.example.version1;
}
start: 'abc'.*?'def';
Grammar.g4 (version 2)
----------------------
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
结果如下:
generated-code/
com/
example/
version1/
GrammarLexer.java
GrammarParser.java
...
没有
version2
。原因似乎在ANTLR的Tool
类中,在
public List<GrammarRootAST> sortGrammarByTokenVocab(List<String> fileNames)
仅按名称收集语法。文件名列表包含两个语法,但返回值只包含一个 AST。
显然,有几个简单的解决方法 - (1) 给语法不同的名称,(2) 运行该工具两次,或 (3) 创建一个可以处理所有版本的语法。我可以做(1),这使得这个问题的优先级很低。我不能轻易做到 (2),因为我使用的是 ANTLR gradle 插件,它一次对所有语法进行操作(并且因为不能保证文件顺序,我随机获得版本 1 或版本 2 的生成代码,但从来没有两个都)。我做不到(3),因为这些 ANTLR 语法不是手写的,而是从具有非 ANTLR 语法的数千行专有语法生成的,这些语法多年来发生了重大变化。
这应该被认为是一个 ANTLR 错误,因为语法不同并且在不同的包中?在一次调用中为该工具提供多个同名的不相关语法是否是用户错误(在这种情况下,gradle 插件也会犯该错误,尽管这是合理的)?