Как удалить нетерминал в файле грамматики с помощью PLY (Python Lex-Yacc)

Я столкнулся с проблемой при использовании PLY. Я хочу создать генератор графа вызовов с помощью PLY. В какой-то ситуации мне нужно отбросить некоторые токены в файле грамматики. Это потому, что мне нужно что-то сделать, когда синтаксический анализатор распознает этот токен, прежде чем я его отбрасываю, поэтому я не могу просто отбросить его в файле лексера. Например, токен «IF» — это тот, который я хочу отбросить. Поэтому я пытаюсь что-то сделать, чтобы отбросить его в файле грамматики. Как:

def p_if(p):
    'if : IF'
    print "if"
    parser.symstack.pop()

Но все пошло не так, как я думаю. Я печатаю симстек (это атрибут синтаксического анализатора, а синтаксический анализатор является экземпляром LRParser yacc.py), и список симстека содержит только предыдущие токены, но не «если». Поэтому мне интересно, как отказаться от токена в этой ситуации. Кто-нибудь может мне помочь? Большое спасибо!


person wani    schedule 27.02.2012    source источник


Ответы (2)


Вы спросили об этом некоторое время назад, и до сих пор нет комментариев или ответов. Вот возможное объяснение, почему.

Я просматриваю документацию на http://www.dabeaz.com/ply/ply.html. . Там ничего не говорится об управлении стеком parser.symstack. Это не открытый документированный интерфейс.

т.е. ты втыкаешь вилку в тостер.

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

Кроме того, не существует задокументированного объекта глобального синтаксического анализатора. Вы должны определить эту переменную анализатора следующим образом: "parser = yacc.yacc()" (задокументировано в Разделе 7: Несколько парсеров и лексеров). Поскольку вы затем ссылаетесь на эту переменную в самих правилах парсера, это выглядит очень неуклюжим. Для правил существует правильный способ обращения к синтаксическому анализатору через параметр p, который они получают: вам нужен p.parser. (Задокументировано в Разделе 7, снова).

person Kaz    schedule 06.03.2012

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

I. определить функцию p_error(p)

def p_error(p):
tok = yacc.token() # Get the next token
yacc.errok()
return tok #Return the next token

II. поднять синтаксическую ошибку в нужной вам функции

def p_somerule(p):
' a : A '
raise SyntaxError
person wani    schedule 10.03.2012