Antlr4: Как передать значение текущего токена в предикат лексера? - PullRequest
0 голосов
/ 09 июля 2019

Есть ли способ предоставить предикату лексера значение текущего токена? например, в моем lexer grammar FlowLexer я динамически загружаю токены:

Перед анализом я динамически загружаю токены:

var lexer = new FlowLexer(new AntlrInputStream(flowContent)) {
    TokenExists = tokenValue => tokensDictionary.ContainsKey(tokenValue)
};

А затем во время синтаксического анализа / лексирования предикат TokenExists называется:

@lexer::members{
    public Func<string,bool> TokenExists = null;
}

/* ... stuff ... */

TOK : [-_.0-9a-zA-Z]+ 
    {!TokenExists(/*WHAT GOES HERE?*/);}? 
    -> mode(IN_TOKEN);

/* ... stuff ... */

Но как передать значение токена в предикат TokenExists?

(Это попытка создать контекстно-зависимый лексер: у меня есть несколько mode, и в которых есть разные правила).

1 Ответ

1 голос
/ 10 июля 2019

Доступ к значениям токенов в предикатах ANTLR4 и действиях возможен с помощью специального синтаксиса.Для получения подробной информации см. Действия и атрибуты Документ.

В общем, вы получаете доступ к проанализированному токену, используя знак доллара и имя токена, например

a: x = INT {$x.text == "0"}?;

или безметка (и только если подправило существует только один раз в этом правиле синтаксического анализатора):

a: INT {$INT.text == "0"}?;

ANTLR4 переводит такой псевдокод в код целевого языка, чтобы разрешить доступ к свойствам токена (например, в C ++ это становится: INT->getText() == "0").

Однако в правилах лексера этот специальный доступ не возможен (его поддерживал ANTLR3, но не ANTLR4).Тем не менее, вы можете получить доступ к свойствам токена с помощью собственного кода (на самом деле это не токен напрямую, поскольку он еще не существует, но значения, которые будут использоваться для его создания после завершения правила лексера).Тем не менее, это часто не переносимо на другие целевые языки (что не имеет значения, если у вас не более одной цели синтаксического анализатора).

Код, запускаемый в действии лексера (который включает в себя предикаты):выполнено в контексте лексера.Этот лексер хранит значения, из которых будет создан новый токен после завершения правила.Это позволяет получить текущий согласованный текст:

TOK : [-_.0-9a-zA-Z]+ {!TokenExists(Text);}? -> mode(IN_TOKEN);

Text является свойством лексера C # .

...