Во-первых, давайте поговорим о import
.
Что такое import
делает аналогично #include
на языке C/C++, который копирует src в dst. ANTLR4 попытается объединить две грамматики, если есть конфликты.
Использование import
является своего рода разочарование, потому что есть очень много ограничений:
Не каждый вид грамматики может импортировать любой другой вид грамматики.
- Lexer grammars может импортировать лексерные грамматики.
- Углеродные грамматики могут импортировать грамматики парсера.
- Комбинированные грамматики могут импортировать лексеры или грамматики парсера.
При импорте options
в грамматике будет проигнорирован.
- При импорте в лексерской грамматике не допускается
mode
.
Таким образом, вы фактически не можете импортировать грамматику лексера в грамматику парсера, потому что они не такие же. Но вы можете импортировать лексер в комбинированную грамматику.
Эти ограничения сузили использование import
. Я думаю, что лучшая ситуация для использования import
будет разделять большую лексируемую или парсерную грамматику на несколько частей, чтобы упростить управление.
Теперь, помните, что мы не можем импортировать грамматику лексера в грамматику анализатора, используя import
? Вот почему нам нужен tokenVocab
, который предназначен для использования отдельного лексера в парсере или комбинированной грамматике.
Заключение выше будет:
- В грамматике лексического анализатора, вы можете использовать только
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, приходит сообщение об ошибке:
error(160): G3.g4:3:21: cannot find tokens file ./G1.tokens
Однако, если мы составляем G1 первых, будет G1.tokens. Теперь сбор G3 будет успешным.