Python - Ply Parser: Как я могу остановить анализ, где я хочу? - PullRequest
0 голосов
/ 13 апреля 2020

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

Поскольку я нахожусь в al oop, он прекратит анализ и снова запросит новый ввод.

while True:
    question = input('>>> ')
    try:
        answer = parser.parse(question)
        if answer is not None:
            print(answer)
    except EOFError:
        break

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

    def error(self, op, other):
        print('Illegal operation "{} {} {}" for {}'.format(self, op, other, type(self).__name__))

Что хорошо, если после деления больше ничего нет, но это будет проблемой для this: 10/0 - 3 + 2, потому что анализ продолжается и будет выдано несколько ошибок. Я хочу иметь возможность остановить синтаксический анализ после самой первой ошибки.

Я думал что-то вроде lexer.skip(1), но для всей строки, а не только для одного токена. Есть ли подобный метод для этого? Большое спасибо!

1 Ответ

0 голосов
/ 13 апреля 2020

Если вы просто хотите прервать синтаксический анализ и отбросить оставшуюся часть анализируемой строки, вызовите исключение (или позвольте Python делить на ноль исключения через). Здесь я создал класс исключений для ошибок калькулятора, так что ошибки в коде синтаксического анализатора по-прежнему будут приводить к обратным следам. Код, который не показан, основан на examples/calc/calc.py.

class CalcError(Exception):
    def __init__(self, message):
        self.message = message
# ...

def p_expression_div(p):
    '''expression : expression '/' expression'''
    if p[3] == 0:
        raise CalcError("Divide by zero")
    p[0] = p[1] / p[3]

Тогда вам просто нужно немного изменить основной l oop:

import readline
try:
    while True:
        question = input('>>> ')
        try:
            answer = parser.parse(question)
            if answer is not None:
                print(answer)
        except CalcError as e:
            print(e.message)
except EOFError:
    print()
    break
...