метод рекурсивного спуска сверху вниз для реализации синтаксического анализатора в python

#python #python-3.x #parsing

#python #python-3.x #синтаксический анализ

Вопрос:

Мне нужно переписать грамматику в EBNF. Используйте метод рекурсивного спуска сверху вниз для реализации синтаксического анализатора (т.е. tdrd parser.py ) в python3 для грамматики EBNF. Имя файла входных данных задается из командной строки. Предположим, что между двумя терминалами (например, a a a c c b ) в файле данных есть пробел.

Вот грамматика:

 <S> -> <A> c c <B> | <B> d d <A>
<A> -> a <A> | a
<B> -> b <B> | b 
  

Вот код:

 import sys


def lexan():
    global mitr

    try:
        return next(mitr)
    except StopIteration:
        return ''


def match(ch):
    global lookahead

    if ch == lookahead:
        lookahead = lexan()
    else:
        print("Syntax Error")
        exit()


def S(): 
    #<S> -> <A> c c <B> | <B> d d <A>
    global lookahead
    if lookahead == 'a':
        A()
        #match('c')
        C()
    elif lookahead == 'b':
        B()
        #match('c')
        C()
    else:
        print("Syntax Error")
        exit()


def A():
    # <A> -> a <A> | a
    global lookahead
    match('a')
    if lookahead == 'a':
        A()


def B():  # <B> -> b <B> | b

    global lookahead
    match('b')
    if lookahead == 'b':
        B()


def C():

    global lookahead
    match('c')
    if lookahead == 'c':
        C()

file = open(sys.argv[1], "r")
wlist = file.read().split()
mitr = iter(wlist)

lookahead = lexan()
S()
if lookahead == '':
    print("Pass")
else:
    print("Syntax Error")
    exit()
  

Всякий раз, когда я его запускаю: python3 tdrd_parser.py data.txt если я удалю b из файла — я получу «Пропуск». В противном случае — синтаксическая ошибка.

Не могли бы вы помочь?

Комментарии:

1. Откуда C взялся? В грамматике нет такого нетерминала. Кроме того, ваша интерпретация в S() двух производствах верхнего уровня, похоже, останавливается в середине правой части.

2. Ну, так что я не очень хорошо разбираюсь в грамматике EBNF, но я подумал, что, поскольку у нас есть c c между A и B, мы должны включить C? Кроме того, я не уверен, почему он застревает? Нужно ли включать больше операторов if?

3. Если я не ошибаюсь, S() должен выглядеть следующим образом: def s(): if lookahead == ‘a’: A() match(‘c’) match(‘d’) B() elif lookahead == ‘b’: match(‘d’) match(‘c’) A() else: print («Синтаксическая ошибка») exit() @rici

4. Закрыть. Согласно вашей грамматике, A(); match('c'); match('c'); B(); и B(); match('d'); match('d'); A(); . Но это не то, что у вас есть, не так ли? Запускаемая продукция A() никогда B() не вызывается, поэтому неудивительно, что a b в конце ввода не распознается.

5. @rici теперь имеет смысл! Спасибо, чувак! Попытаюсь реализовать его сегодня! 🙂