Обработка ошибок PLY.yacc с помощью ресинхронизации парсера - PullRequest
0 голосов
/ 31 декабря 2018

Я пытаюсь реализовать удобную синтаксическую обработку ошибок при синтаксическом анализе.Из того, что я наблюдал в официальной документации PLY .Один из способов - вызвать исключение, когда происходит первый SyntaxError, и прекратить анализ.Тем не менее, я хотел бы сделать нечто подобное, как предлагается в документации, использовать технику ресинхронизации синтаксического анализатора.

В документации сказано:

Наиболее корректный подход для обработки синтаксических ошибок.это написать правила грамматики, которые включают токен ошибки.Например, предположим, что в вашем языке есть грамматическое правило для оператора печати, например, так:

def p_statement_print(p):
  'statement : PRINT expr SEMI'
  ...

Чтобы учесть возможность неправильного выражения, вы можете написать дополнительное правило грамматики, например:

def p_statement_print_error(p):
    'statement : PRINT error SEMI'
     print("Syntax error in print statement. Bad expression")

У меня есть такой отрывок из грамматики:

def p_operation(self, p) -> None:
    '''
    operation : unaryOperation
              | binaryOperation
    '''

def p_unaryOperation(self, p) -> None:
    '''
    unaryOperation : unaryOperation L_SQUARE_BRACKET projection R_SQUARE_BRACKET
                   | RELATION_NAME
    '''

def p_projection(self, p) -> None:
    '''
    projection : multipleAttributes
               | attribute
    '''

def p_multipleAttributes(self, p) -> None:
    '''
    multipleAttributes : projection COMMA attribute
    '''

def p_attribute(self, p) -> None:
    '''
    attribute : ATTRIBUTE
    '''

Я совершенно не уверен, как мне определить такие новые правила, включая токен error.Должен ли я заменить каждый нетерминал токеном error?

Ждем ваших ответов!Большое спасибо за вашу помощь

1 Ответ

0 голосов
/ 01 января 2019

Определенно не следует добавлять выдачу ошибок для каждого нетерминала.

Ресинхронизация работает, когда есть какой-то токен, который обычно сбрасывает контекст анализа в известное состояние.В языках с четким маркером конца оператора - точка с запятой в приведенном вами примере - этот маркер работает как точка ресинхронизации.Сброс текста до следующей точки с запятой и последующий синтаксический анализ оттуда не будет работать 100% времени, но он работает во многих случаях.

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

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

Несогласованный отступполезный триггер ресинхронизации с парой предостережений.Во-первых, вы не должны отклонять допустимый ввод с «вводящим в заблуждение» отступом, поэтому триггер должен быть более чувствительным при повторной синхронизации, чем при обычном разборе.Во-вторых, для отслеживания несовместимых отступов обязательно требуется обратный канал синтаксического анализатора.Таким образом, это больше, чем простое восстановление от паники, но оно может быть эффективным.

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

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

...