Что вы можете сделать, это создать отдельную лексерскую грамматику, чтобы вы могли использовать лексические режимы .
Таким образом, вы начинаете в режиме объявления по умолчанию, и когда вы впервые сталкиваетесь с %%
, вы нажимаете на RULE_MODE
. Когда вы сталкиваетесь с другим %%
, вы нажимаете на SUBROUTINE_MODE
. В этом последнем режиме вы просто skip
видите всех персонажей.
Небольшая демонстрация:
// File: YaccLexer.g4
lexer grammar YaccLexer;
DECLARATION_TOKEN
: [a-zA-Z]+
;
SPACES
: [ \t\r\n]+ -> skip
;
DECLARATION_END
: '%%' -> skip, pushMode(RULE_MODE)
;
mode RULE_MODE;
RULE_TOKEN
: [a-zA-Z]+
;
SPACES_RULE_TOKEN
: [ \t\r\n]+ -> skip
;
RULE_END
: '%%' -> skip, pushMode(SUBROUTINE_MODE)
;
mode SUBROUTINE_MODE;
ANY
: . -> skip
;
Если вы генерируете лексер из приведенной выше грамматики и токенизируете ввод:
foo
bar
%%
baz
%%
ignore
me
будут созданы следующие токены:
DECLARATION_TOKEN 'foo'
DECLARATION_TOKEN 'bar'
RULE_TOKEN 'baz'
Вы можете использовать YaccLexer
в грамматике вашего синтаксического анализатора следующим образом:
// File: YaccParser.g4
parser grammar YaccParser;
options {
tokenVocab= YaccLexer;
}
// your parser rules here