PLY YACC pythonic синтаксис для накопления списка значений, разделенных запятыми

Я использую YACC впервые и привыкаю к ​​использованию грамматики BNF.

В настоящее время я создаю list из type из списка, разделенного запятыми (например, int, float, string):

def p_type(p):
    '''type : primitive_type
            | array
            | generic_type
            | ID'''
    p[0] = p[1]


def p_type_list(p):
    '''type_list : type
                 | type COMMA type_list'''
    if not isinstance(p[0], list):
        p[0] = list()
    p[0].append(p[1])
    if len(p) == 4:
        p[0] += p[3]

Правила работают, но я чувствую, что моя логика p_type_list немного запутана и может быть упрощена до однострочника.

Я не нашел конкретных примеров PLY в Интернете. Любая помощь будет принята с благодарностью!


person Colin Basnett    schedule 24.12.2015    source источник


Ответы (2)


Есть два производства. Используйте две отдельные функции. (Дополнительных затрат нет :-))

def p_type_list_1(p):
    '''type_list : type'''
    p[0] = [p[1]]

def p_type_list_2(p):
    '''type_list : type_list COMMA type'''
    p[0] = p[1] + [p[3]]

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

def p_type_list_2(p):
    '''type_list : type_list COMMA type'''
    p[0] = p[1]
    p[0] += [p[3]]

что позволяет избежать копии списка.

person rici    schedule 24.12.2015

Или "упростить" p_type_list до (вы сокращаете на 1 строку кода, не уверен, что оно того стоит):

def p_type_list(p):
    '''type_list : type
                 | type_list COMMA type'''
    if len(p) == 2:
       p[0] = [p[1]]
    else:
       p[0] = p[1] + [p[3]]
person orange    schedule 24.12.2015