Я выбираю этот способ ответа из-за ограниченного пространства и отсутствия возможностей форматирования. Так или иначе:
Нет. CHUNK и LABEL - это правила Lexer (Scanner), тогда как fillInTheBlank - это правило синтаксического анализатора. Парсер работает поверх сканера, то есть сканер не знает о парсере (правилах). Вы должны ввести состояний лексера :
Во-первых, вы должны ввести еще одного члена лексера, который будет следить за состоянием, сообщая вам, хотите ли вы прочитать этикетку или нет:
@lexer::members {
private boolean readLabel = false;
}
Затем вы должны ввести явные определения токенов для '$ {' и '}' (я называю их BEGIN_VAR и END_VAR), которые изменяют эту переменную состояния. Кроме того, токены END_VAR могут быть созданы, только если readLabel имеет значение true:
BEGIN_VAR
: '${' { readLabel = true; };
END_VAR : { readLabel }?=> '}' { readLabel = false; };
Вы также должны сообщить лексеру, что токены LABEL также должны генерироваться только в этом состоянии:
LABEL
: { readLabel }?=> ('a'..'z'|'A'..'Z') ('a'..'z'|'A'..'Z'|'0'..'9')*
;
Обратите внимание, что здесь важно, чтобы это определение появилось до CHUNK.
Наконец, вам нужно изменить правило fillInTheBlanks, используя приведенные выше определения токенов:
fillInTheBlank returns [String value]
: BEGIN_VAR LABEL END_VAR
{ ...
Надеюсь, это поможет, кажется, работает для меня.