首先,让我们谈一下
import
。
import
与C/C++语言中的
#include
类似,即将src复制到dst。如果有冲突,ANTLR4会尝试合并两个语法。
使用
import
有点令人沮丧,因为有很多限制:
1.并非所有类型的语法都可以导入其他类型的语法。
- Lexer语法可以导入Lexer语法。
- Parser语法可以导入Parser语法。
- Combined语法可以导入Lexer或Parser语法。
2.导入时,语法中的选项将被忽略。
3.导入时,在Lexer语法中不允许使用mode。
因此,您实际上不能在解析器语法中导入词法分析器语法,因为它们不属于同一种类型。但是您可以在组合语法中导入Lexer语法。
这些限制已经缩小了
import
的用途范围。我认为使用
import
的最佳情况是将大型词法或解析器语法分解为几个部分,以便更易于管理。
现在,还记得我们不能使用
import
在解析器语法中导入词法分析器语法吗?这就是为什么我们需要
tokenVocab
,它是设计用于在解析器或组合语法中使用单独的词法分析器。
总之,以上结论为:
- 在Lexer语法中,您只能使用
import
。
- 在解析器语法中,您只能使用
import
导入另一个解析器语法。您只能使用
tokenVocab
来使用另一个词法分析器语法。
- 在组合语法中,您可以同时使用
import
和
tokenVocab
。
对于第三个,现在有什么区别?
区别在于使用
tokenVocab
需要先编译词法分析器,因为
tokenVocab
只是声明需要另一个语法的选项。而使用
import
不需要这样做,因为它会将src复制到当前语法中。
例如,有三个语法文件:
G1.g4
grammar G1;
r: B;
G2.g4
grammar G2;
import G1
G3.g4
grammar G3;
options { tokenVocab=G2; }
t: A;
如果我们直接编译G2,那么就没有问题。但是如果我们尝试编译G3,则会出现错误:
错误(160):G3.g4:3:21:找不到./G1.tokens令牌文件。
然而,如果我们先编译G1,就会生成G1.tokens文件。现在编译G3将会成功。