AST с фиксированными узлами вместо узлов ошибок в antlr
У меня есть синтаксический анализатор, сгенерированный antlr, который использует цель C, и он работает довольно хорошо. Проблема в том, что я также хочу, чтобы он анализировал ошибочный код и создавал значимый AST. Если я передаю ему минимальный Java-класс с одним импортом, после которого точка с запятой отсутствует, он создает два объекта "Tree Error Node", в которых должны быть токен import и токены импортируемого класса.
Но поскольку он правильно анализирует следующий код и создает правильные узлы для этого кода, он должен восстановиться после ошибки, добавив точку с запятой или повторив синхронизацию. Есть ли способ заставить antlr отражать этот фиксированный ввод, который он вырабатывает внутри AST? Или я могу хотя бы получить токены / текст, которые как-то породили "Ошибки узлов дерева"?
В целях C antlr3commontreeadaptor.c около строки 200 следующий фрагмент указывает, что цель C до сих пор создает только фиктивные узлы ошибок:
static pANTLR3_BASE_TREE
errorNode (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_TOKEN_STREAM ctnstream, pANTLR3_COMMON_TOKEN startToken, pANTLR3_COMMON_TOKEN stopToken, pANTLR3_EXCEPTION e)
{
// Use the supplied common tree node stream to get another tree from the factory
// TODO: Look at creating the erronode as in Java, but this is complicated by the
// need to track and free the memory allocated to it, so for now, we just
// want something in the tree that isn't a NULL pointer.
//
return adaptor->createTypeText(adaptor, ANTLR3_TOKEN_INVALID, (pANTLR3_UINT8)"Tree Error Node");
}
Мне здесь не повезло, и только те узлы с ошибками, которые выдает цель Java, позволят мне получить текст ошибочных узлов?
2 ответа
Я решил проблему, добавив новые альтернативные правила в грамматику для всех возможных ошибочных утверждений.
Каждый оператор импорта Java транслируется, например, в поддерево AST с искусственным символом IMPORT в качестве корня. Чтобы убедиться, что я могу отличить AST от правильного и ошибочного кода, правила для ошибочных операторов переписывают их в AST с корневым символом с префиксом ERR_, поэтому в примере с оператором импорта искусственным корневым символом будет ERR_IMPORT.
Более разные корневые символы могут быть использованы для кодирования более подробной информации об ошибке разбора.
Мой синтаксический анализатор теперь настолько терпим к ошибкам, насколько мне нужно, и очень легко добавлять правила для новых типов ошибочного ввода всякий раз, когда мне это нужно. Вы должны остерегаться, чтобы не вносить двусмысленности в вашу грамматику.
Я не очень много использовал antlr, но обычно вы обрабатываете ошибки такого типа, чтобы добавить правила для соответствия неправильному синтаксису, заставить их создавать узлы ошибок и пытаться исправить ошибки, чтобы вы могли продолжать анализ. Последующее исправление является проблемой, потому что вы не хотите, чтобы одна ошибка вызывала все больше и больше ошибок для каждого нового токена до конца.