В Python2.7 ANTLR4 извлеките токены из правила синтаксического анализатора и сохраните их в списке

В моей грамматике я проверяю логические выражения, которые выглядят примерно так:

((foo == true) && (bar != false) || (qux == norf))

Я получаю строку из объекта контекста ANTLR4, вызывая getText():

def enterBody(self, ctx):
    expression = ctx.condition.getText() # condition here being shorthand for a grammar rule (`condition=expr`)

Тем не менее, строка возвращается целиком (то есть без пробелов между каждым отдельным токеном), и у меня нет возможности узнать, что представляет собой каждый токен:

((foo==true)&&(bar!=false)||(qux==norf))

В идеале, я бы хотел, чтобы он хранился в списке в следующем формате:

['(', '(', 'foo', '==', 'true', ')', '&&', '(', 'bar', '!=', 'false', ')', '||', '(', 'qux', '==', 'norf', ')', ')']

Документация по ANTLR4 Python довольно скудная, и я не уверен, что есть метод, который выполняет это.

1 ответ

Среда исполнения Python действительно похожа на среду исполнения Java, поэтому вы можете посмотреть документацию по Java, и, скорее всего, такой же метод существует в Python. Или просмотрите исходный код, его довольно легко прочитать.

Вы просите получить плоский список строк. Но вся идея парсера - избежать этого. Поэтому я думаю, что это, скорее всего, не то, что вам нужно. Убедитесь, что вы знаете о дереве разбора и о том, как работают слушатели. В основном вы должны работать с деревом, а не с плоским списком. То, что вы, вероятно, ищетеParserRuleContext.getChildren(), Вы можете использовать его для доступа ко всем дочерним узлам:

def enterBody(self, ctx):
    print(list(ctx.getChildren()))

Что еще более вероятно, вы хотите получить доступ к определенному типу дочернего узла для какого-либо действия. Посмотрите на парсер, сгенерированный ANTLR для вас. Вы найдете кучу *Context классы, которые содержат методы для доступа к каждому типу подузла. Например ctx параметр enterBody() Метод является экземпляром BodyContext и вы можете использовать все его методы для доступа к дочерним узлам определенного типа.

UPD Если ваша грамматика определяет только логическое выражение и вы используете его только для валидации и токенизации, вам вообще не понадобится парсер. Просто используйте lexer, чтобы получить список всех токенов:

input_stream = antlr4.FileStream('input.txt')

# Instantiate an run generated lexer
lexer = BooleanLexer(input_stream)
tokens = antlr4.CommonTokenStream(lexer)

# Parse all tokens until EOF
tokens.fill()

# Print tokens as text (EOF is stripped from the end)
print([token.text for token in tokens.tokens][:-1])
Другие вопросы по тегам