PLY: проблема смещения токенов в C-парсере - PullRequest
3 голосов
/ 20 сентября 2008

Я пишу синтаксический анализатор C, используя PLY, и недавно столкнулся с проблемой. Этот код:

typedef int my_type;
my_type x;

Правильный код C, потому что my_type определен как тип, ранее используется как таковой. Я справляюсь с этим, заполняя таблицу символов типа в синтаксический анализатор, который используется лексером для различения типов и простые идентификаторы.

Однако, хотя правило объявления типа заканчивается символом SEMI (токен ';'), PLY сдвигает токен my_type со второй строки, прежде чем решить, что это сделано с первой. Из-за этого у меня нет шансов передать обновление в таблице символов типа лексеру, и это видит my_type как идентификатор, а не как тип.

Есть идеи для исправления?

Полный код: http://code.google.com/p/pycparser/source/browse/trunk/src/c_parser.py Не уверен, как я могу создать меньший пример из этого.

Edit:

Проблема решена. Смотрите мое решение ниже.

Ответы [ 3 ]

3 голосов
/ 20 сентября 2008

Не уверен, почему вы проводите такой уровень анализа в своем лексере.

Лексический анализ, вероятно, следует использовать для разделения входного потока на лексические токены (число, изменение строки, ключевое слово и т. Д.). Именно на этом этапе анализа должен выполняться этот уровень анализа, включая поиск в таблицах для typedefs и тому подобное.

Так я всегда разделял обязанности между lexx и yacc, моими инструментами выбора.

2 голосов
/ 20 сентября 2008

С помощью от Дейва Бизли (создателя PLY) моя проблема была решена.

Идея состоит в том, чтобы использовать специальные под-правила и выполнять в них действия. В моем случае я разделил правило declaration на:

def p_decl_body(self, p):
    """ decl_body : declaration_specifiers init_declarator_list_opt
    """
    # <<Handle the declaration here>>        

def p_declaration(self, p):
    """ declaration : decl_body SEMI 
    """
    p[0] = p[1]

decl_body всегда уменьшается перед токеном после сдвига SEMI, поэтому мое действие выполняется в правильное время.

1 голос
/ 20 сентября 2008

Я думаю, вам нужно переместить проверку того, является ли идентификатор TYPEID, с c_lexer.py на c_parser.py.

Как вы сказали, так как анализатор смотрит вперед на 1 токен, вы не можете принять это решение в лексере.

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

Как сказал Пакс Диабло в своем превосходном ответе, задача лексера / токенизатора состоит не в том, чтобы принимать такие решения относительно токенов. Это работа парсера.

...