Как восстановить ParserRuleContext для конкретной строки и позиции символа с помощью antlr4? - PullRequest
0 голосов
/ 30 декабря 2018

Как только я инициализировал анализатор, лексер и получил контекст translationUnit, как я могу перейти непосредственно к (ближайшему) ParserRuleContext, который содержит определенную позицию строки и символа в antlr4 (время выполнения CPP)?

Обычно я использую шаблон Listener для обхода контекста translationUnit.В каждом посещенном контексте я могу получить соответствующую строку и символьную позицию контекста, используя следующий код:

antlr4::Token* tokenclass = _tokenstream->get(myContext->getSourceInterval().a); // use ".b" if end of interval is needed 
size_t CharPositionStartInLine = tokenclass->getCharPositionInLine();       
size_t LineStart = tokenclass->getLine();

Я хотел бы выполнить обратное: получить токен из определенной строки и позиции символа, а затем получить (первый) родительский контекст.Возможно ли это?

Я думаю, что могу достичь того, что хочу (т.е. найти контекст, основанный на позиции строки и символа), проверяя каждую строку и позицию символа context внутри функции enterEveryRule(antlr4::ParserRuleContext* context), но этокажется слишком сложным.Так есть ли более простой способ восстановить ParserRuleContext для определенной строки / символьной позиции?

1 Ответ

0 голосов
/ 31 декабря 2018

Подход довольно прост.ParserRuleContext содержит токены запуска и остановки с информацией о позиционировании.Следовательно, легко определить, включает ли контекст правила определенную позицию.Начните с корня дерева разбора и переберите его потомки.Найдите тот, который включает эту позицию (перекрытие невозможно).Продолжайте работу с этим узлом и его дочерними узлами, пока не найдете конечный узел, который вы ищете.Если для данного узла ни один дочерний узел не включает данную позицию, используйте вместо этого этот узел.

В MySQL Workbench Sources есть реализация C ++ для terminalFromPosition и contextFromPosition.Первая функция берет пару строка / столбец и стремится всегда возвращать терминал (даже если его нет непосредственно в данной позиции), в то время как последняя использует индекс символа и реализует подход в точности так, как я упоминал в предыдущем абзаце.

...