Как указать несколько правил лексера в одном правиле?

У меня такое правило парсера:

declaration     : (KW_VARIABLE DT_IDENTIFIER) |
                  (KW_VARIABLE DT_IDENTIFIER OP_ASSIGNMENT DT_DATA_TYPES) OP_SEMICOLON;

и следующие правила лексера:

KW_VARIABLE     : 'var';

OP_ASSIGNMENT   : '=';
OP_SEMICOLON    : ';';

DT_IDENTIFIER   : [a-z]+;
DT_INTEGER      : [0-9]+;
DT_DATA_TYPES   : (DT_IDENTIFIER | DT_INTEGER);

С помощью приведенных выше правил я хочу написать следующий код:

var a = 10;
var b = 40;
var c = 50;
var d = c;

Мой код слушателя для выхода из объявления выглядит так:

public override void ExitDeclaration([NotNull] PyroParser.DeclarationContext context)
{
    bool isAssigned = context.OP_ASSIGNMENT() != null;

    if (!isAssigned)
    {
        return;
    }

    Console.WriteLine(context.DT_DATA_TYPES().GetText());
    base.ExitDeclaration(context);
}

Я получаю сообщение об ошибке в первой строке, когда бегу и говорю:

строка 1:8 несоответствующий ввод '10' ожидает DT_DATA_TYPES

Я просто хочу иметь возможность ссылаться на все типы данных в одном правиле, как я могу это сделать?

1 ответ

Это неверно:

DT_IDENTIFIER   : [a-z]+;
DT_INTEGER      : [0-9]+;
DT_DATA_TYPES   : (DT_IDENTIFIER | DT_INTEGER);

Когда DT_IDENTIFIER или DT_INTEGER совпадает, он никогда не станет DT_DATA_TYPES. Лексер сопоставляет правила сверху вниз, и как только совпадение будет найдено, он не откажется от него. И просто изменив порядок правил:

DT_DATA_TYPES   : (DT_IDENTIFIER | DT_INTEGER);
DT_IDENTIFIER   : [a-z]+;
DT_INTEGER      : [0-9]+;

тоже не будет работать: таким образом лексер никогда не произведет DT_IDENTIFIER а также DT_INTEGER жетоны.

Вместо этого вы можете сделать что-то вроде этого:

dt_data_types   : (DT_IDENTIFIER | DT_INTEGER);

DT_IDENTIFIER   : [a-z]+;
DT_INTEGER      : [0-9]+;
Другие вопросы по тегам